パイプから読み込まれたchar *内のcharのすべてのインスタンスを置換しようとしています

私は宿題のための関数を実装しています。関数の定義は次のとおりです。

int processchar(int fdin, int fdout, char inchar, char *outstr);

processchar関数は、ファイルの終わりまでファイル記述子fdinを読み込み、ファイルに書き込みます   記述子fdoutは、文字インチの出現を文字列outstrに変換します。   うまくいかなかった場合、processcharは-1を返し、errnoを設定します。

私の現在のコードは次のとおりです:

#define CHUNK 256
int processchar(int fdin, int fdout, char inchar, char *outstr){
  int j = 0, n = CHUNK, np = CHUNK, r;
  char *buf, *tmp_buf, *fin_buf, *k, *rbuf, *rrbuf;

  if((buf = malloc(sizeof(char) * n )) == NULL)
    return 1;
  while((r = read(fdin, buf, CHUNK))){
    if( r == -1 )
      return -1;
    n += r;
    if(np - n < CHUNK) {
      np *= 2;
      rbuf = malloc(np * sizeof(char));
      memcpy(rbuf, buf, n * sizeof(char));
      free(buf);
      buf = rbuf;
    }
  }
  fprintf(stderr, "buf is %s\n",
  for(tmp_buf = buf; tmp_buf < buf + n; tmp_buf++){
    if(*tmp_buf == inchar)
      j++;
  }
  if((fin_buf = malloc((sizeof(char) * n) + (sizeof(char) * j * strlen(outstr) + 1)) == NULL))
    return 1;
  rrbuf = fin_buf;
  for(tmp_buf = buf; tmp_buf < buf + n; tmp_buf++){
    if(*tmp_buf == inchar){
      fprintf(stderr, "got another j\n");
      k = outstr;
      while(*fin_buf++ = *k++);
    } else {
      fprintf(stderr, "swing n a miss\n");
      *fin_buf++ = *tmp_buf;
    }
  }
  write(fdout, rrbuf, strlen(rrbuf));
  return 0;
}

私がやったテストから、それはセクションのように思える:

tmp_buf < buf + n

forループの定義には意図した結果がありません。この関数はプロセスの呼び出しによって呼び出され、それぞれstdoutを次のstdoutに渡します(使用例では fdinSTDIN_FILENO および fdout < code>は STDOUT_FILENO です)。具体的には、2番目のforループのfprintf文は、期待した回数だけ印刷されません(私の期待は、 fprintfbuf コード>)。

私は長い間この機能を凝視してきましたが、あなたが提供できるすべての方向性や意見を感謝しています。以前このサイトでいくつかのスレッドを利用していましたが、実際には this one と入力します。

:このassignemntは、Unixシステムプログラミングの本にリングを実装する方法を学ぶことを除いています)

1
strlen を持つ malloc は、より良い機能である strdup で冗長です。
追加された 著者 Zan Lynx,
Cファイルやコマンドラインで使用されているときには、 'tr'関数を見たいかもしれません。これは、入力ストリームの指定されたcharを出力ストリームの新しいcharに変更し、他のすべての文字は変更しません。
追加された 著者 user3629249,
標準IOライブラリを使用することは許可されていますか? getc(3)putc(3)を使用して FILE * を取得するには fdopen(3) >、 fputs(3)を使用して、今すぐ取得したバッファリングコードを大幅に簡素化できます。
追加された 著者 sarnold,
ちなみに、 strlen(3)を使ってサイズを計算すると、最後に近い mrloc(3) は、end-of-string NUL バイトに必要なスペースを返しません。 +1 なしで malloc(... strlen(foo))を見ると、ほとんどのバグです。
追加された 著者 sarnold,
@ザンは完全に合意した。しかし、この特定の場合、 strlen(3)は割り当てられている空間の1つのコンポーネントに過ぎません。
追加された 著者 sarnold,
私はIOのread(2)とwrite(2)の呼び出しを使用することを意図していると思います。明示的な制限はありませんが、各課題はそれ以前のものに基づいて構築されていますが、このテキストではまだこれらの関数に導入されていません。
追加された 著者 user1043711,
mallocに追加のcharスペースを残さずに、送信されたテキストの監視が行われました。私はその提出を編集してその結論を出しました。
追加された 著者 user1043711,

1 答え

私はあなたがこれを思慮深く考えているかもしれないと思います。割り当てを満たす必要のある簡単な実装は次のとおりです。

#define CHUNK 256
int processchar ( int fdin, int fdout, char inchar, char *outstr ) {
    char buf[CHUNK];
    int r, outlen = strlen( outstr );

    while ( (r = read( fdin, buf, CHUNK )) > 0 ) {
        int i;
        for ( i = 0; i < r; i++ ) {
            if ( buf[i] == inchar ) {
                if ( write( fdout, outstr, outlen ) < 0 ) return -1;
            } else {
                if ( write( fdout, &buf[i], 1 ) < 0 ) return -1;
            }
        }
    }
    return r;
}

連続して一致しない文字を収集し、それらを単一の write()呼び出しで書くことによって、それをわずかに最適化することができます。私はそれを運動として残します。

(また、私は部分的な書き込みや EINTR のチェックもしていません)一般に、これは read()および write ()であり、上位レベルの呼び出しコードではありません)。

2
追加された
素晴らしい、それを完全に考える時間をとってくれてありがとう。 :)
追加された 著者 sarnold,
ワオ。私は本当にそれを思っていた。何らかの理由で、私は私の書き込みをバッファリングする必要があるという印象を受けました。このソリューションは、私がそうすることなく定義を達成できることを非常に明確に示しています。ありがとうございました!
追加された 著者 user1043711,