0

読み取り専用 FIFO から数行を読み取るときに問題が発生しました。具体的には、number 、 a 、および stringnが続く2 行を読み取る必要があり、C プログラムは書き込み専用 FIFO に数回書き込む必要があります。これが私の試みです。\nstrstrn

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

char *readline(int fd);

int main(int  argc, char** argv) {
    int in = open(argv[1], O_RDONLY);
    mkfifo(argv[2], 0666);
    int out = open(argv[2] ,O_WRONLY);
    char *line = (char *) malloc(50);
    int n;

    while (1) {
        sscanf(readline(in), "%d", &n);
        strcpy(line, readline(in));

        int i;
        for (i = 0; i < n; i++) {
            write(out, line, strlen(line));
            write(out, "\n", 1);
        }
    }

    close(in);
    close(out);
    return 0;
}

char *readline(int fd) {
    char *c = (char *) malloc(1);
    char line[50];

    while (read(fd, c, 1) != 0) {
        if (strcmp(c, "\n") == 0) { 
            break;
        }
        strcat(line, c);
    }
    return line;
}

コードは正常に動作していますが、最後の文字列の繰り返しの後に乱数の改行が挿入されています。また、この数は実行ごとに変わります。

誰か助けてくれませんか?

4

3 に答える 3

1

文字ごとに読み取ることと、「文字列」比較を使用して2つの文字を比較することの両方が効率的であるという事実に加えて、ローカルに宣言されているreadline()メモリへのポインタを返します。未定義の動作。readline()line[50]readline()

これを修正する 1 つの可能性は、行を外部に読み込むようにバッファーを宣言し、次のreadline()ように参照を渡すことです。

char * readline(int fd, char * line, size_t size) 
{
  if ((NULL != line) && (0 < size))
  {
    char c = 0;
    size_t i = 0;
    while (read(fd, &c, 1) >0) 
    {
      if ('\n' == c) or (size < i) { 
        break;
      }
      line[i] = c;
      ++i;
    }
    line [i] = 0;
  }

  return line;
}

そして、次のように呼び出します。

char * readline(int fd, char * line, size_t size);

int main(void)
{
  ...
  char line[50] = "";
  ...
  ... readline(in, line, sizeof(line) - 1) ...
于 2013-11-09T18:08:20.250 に答える
0

私はあなたのコードを実行しようとはしませんでしたが、あなたのreadline関数lineでは null ( '\0') 文字で終了していません。文字をヒットし'\n'たら、ループを壊してwhile文字列を返すだけlineです。'\0'関数から戻る前に文字を追加してみてくださいreadline

詳細については、ここをクリックしください。

于 2013-11-09T17:43:28.343 に答える
-1

あなたのコードは私のマシンでは機能しませんでした。意味のある結果が得られたのは幸運だと思います。

考慮すべきいくつかの問題を次に示します。

  • readlineローカルに定義された static char バッファ ( line) を返します。このバッファは、関数が終了すると破棄され、占有されていたメモリは解放され、他の操作によって上書きされます。
  • line割り当て時に null バイトに設定されていない場合strcat、ガベージ値を文字として扱い、終了後に書き込みを試みる可能性があります。
  • cに char* が必要なため、1 バイトのバッファー ( ) を割り当てているのではないかと思いますread。これは不要です (以下のコードを参照)。さらに悪いことに、終了する前に割り当てを解除しないreadlineため、メモリ リークが発生します。
  • ループはwhile(1)ファイルを再読み取りし、最後まで出力 fifo に再出力します。
  • いくつかの「重砲」、つまりstrcatメモリ割り当てを使用していますが、より簡単なアプローチがあります。
  • 最後に、一部の C 標準バージョンでは、変数を使用する前にすべての変数を宣言する必要がある場合があります。この質問を参照してください。

そして、これが私があなたのコードをどのように変更したかです。2 行目が 50 文字を超える場合、このコードも適切に動作しない可能性があることに注意してください。バッファ制限に関するテクニックはいくつかありますが、この例では使用しません。

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

char *readline(int fd, char * buffer);

int main(int  argc, char** argv) {
    int in = open(argv[1], O_RDONLY);
    int out;
    int n;
    int i;
    char line[50];

    memset(line, 0, 50);
    mkfifo(argv[2], 0666);
    out = open(argv[2] ,O_WRONLY);

    sscanf(readline(in, line), "%d", &n);
    strcpy(line, readline(in, line));

    for (i = 0; i < n; i++) {
        write(out, line, strlen(line));
        write(out, "\n", 1);
    }

    close(in);
    close(out);
    return 0;
}

char *readline(int fd, char * buffer) {
    char c;
    int counter = 0;
    while (read(fd, &c, 1) != 0) {
        if (c == '\n') {
            break;
        }
        buffer[counter++] = c;
    }
    return buffer;
}

あなたが説明したように、これは私のボックスで機能します。GCC 4.8.2 でコンパイルされています。

于 2013-11-09T18:33:32.063 に答える