2017-01-28 7 views
3

私は、C言語でプログラムを書いた期待される結果がどうあるべき文字列をリセットしません:私をtempWord [0] = ' 0' 何とか

$ ./censor Ophelia < poem.txt 

Said Hamlet tomlet CENSORED, 
I'lllia drawlia arawlia sketcha ofetcha theecha, 
Whatcha kindcha ofndcha pencila shallla Ihallla usellla? 
2Bsellla orellla notllla 2Botllla? 

$ cat poem.txt 

Said Hamlet to Ophelia, 
I'll draw a sketch of thee, 
What kind of pencil shall I use? 
2B or not 2B? 

$ ./censor Ophelia < poem.txt 

Said Hamlet to CENSORED, 
I'll draw a sketch of thee, 
What kind of pencil shall I use? 
2B or not 2B? 

しかし、私はこれを得ましたtempWordを使用してすべての単語を保存し、それを打ち切る必要がある単語と比較します。次に、別の比較を行うために、tempWord[0]='\0'を使用して一時文字列をリセットします。しかし、それは動作していないようです。誰も助けることができますか?

# include <stdio.h> 
# include <string.h> 

int compareWord(char *list1, char *list2); 
int printWord(char *list); 

int main(int argc, char *argv[]) { 

    int character = 0; 

    char tempWord[128]; 
    int count = 0; 

    while (character != EOF) { 
     character = getchar(); 

     if ((character <= 'z' && character >= 'a') || 
      (character <= 'Z' && character >= 'A') || 
      character == 39) {    
      tempWord[count] = character; 
      count++; 
     } else { 
      if (count != 0 && compareWord(tempWord, argv[1])) { 
       printf("CENSORED"); 
       count = 0; 
       tempWord[0] = '\0'; 
      } 

      if (count != 0 && !compareWord(tempWord, argv[1])) { 
       printWord(tempWord); 
       count = 0; 
       tempWord[0] = '\0'; 
      } 

      if (count == 0) { 
       printf("%c", character); 
      } 
     } 
    } 
    return 0; 
} 

int printWord(char *list) { 

    // print function 
} 

int compareWord(char *list1, char *list2) { 
     // compareWord function 
} 
+0

あなたはラインによってあなたのプログラム行の実行をトレースするために、デバッガを使用して提案します。 – kaylum

+0

'strlen()'はC- "文字列"とみなされます。つまり、*任意の*場合は、 'char'配列が' 0'に渡されたことを意味します。 – alk

+0

@alk:正しいです。 memsetを使用してすべての位置をnullに設定した場合。その後、この問題も解決されます。 – sureshkumar

答えて

3

は、あなたのコード内の複数の問題があります。

  • あなたは正しい場所にファイルの終わりをテストしていない:getc()戻りEOFは、あなたがすぐに代わりに処理EOFと出て行くのループを終了する必要がある場合次の反復で。これを行うには、古典的なCのイディオムは次のとおりです。

    while ((character = getchar()) != EOF) { 
        ... 
    
  • 移植性と可読性のために、あなたはバイトが文字であるかどうかを確認し、39としてアポストロフィの値の値をハードコーディングを避けるために<ctype.h>からisalpha()を使用する必要があり、代わりに'\''を使用してください。

  • tempWordアレイにバイトを格納すると、バッファオーバーフローが発生する可能性があります。オフセットとバッファサイズを比較する必要があります。

  • tempWordをnullで終了しないため、compareWord()関数は最初の文字列の長さを判別できません。この動作は未定義です。

  • コマンドライン引数が指定されているかどうかはチェックしません。

  • 2番目のテストは冗長です。else句を使用することができます。

  • ヌル終了がないため、tempWord[]の内容を印刷すると、未定義の動作が発生します。これは予想外の動作を説明しますが、さらに悪い結果をもたらす可能性があります。

  • printWordは、単にC文字列を出力します。fputs()を使用してください。

  • compWordの機能は、実質的にstrcmp(a, b) == 0と同じです。あまりにある

    • 言葉:

      #include <ctype.h> 
      #include <stdio.h> 
      #include <string.h> 
      
      int main(int argc, char *argv[]) { 
          char tempWord[128]; 
          size_t count = 0; 
          int c; 
      
          while ((c = getchar()) != EOF) { 
           if (isalpha(c) || c == '\'') { 
            if (count < sizeof(tempWord) - 1) { 
             tempWord[count++] = c; 
            } 
           } else { 
            tempWord[count] = '\0'; 
            if (argc > 1 && strcmp(tempWord, argv[1]) == 0) { 
             printf("CENSORED"); 
            } else { 
             fputs(tempWord, stdout); 
            } 
            count = 0; 
            putchar(c); 
           } 
          } 
          return 0; 
      } 
      

      EDIT:合法的に上記のコードは2特殊なケースを処理しないとコメントし chuxここ

    は簡略化し、修正版ですlongは出力で切り捨てられます。

  • 最後の単語は、ファイルの最後に正確に含まれる場合は省略されます。

また、プログラムがコマンドラインで渡された長い単語の大文字小文字を処理しないこともわかりました。ここで

は、これらの欠点を修正することなく、バッファ異なるアプローチである:

#include <ctype.h> 
#include <stdio.h> 

int main(int argc, char *argv[]) { 
    const char *word = (argc > 1) ? argv[1] : ""; 
    int count = 0; 
    int c; 

    for (;;) { 
     c = getchar(); 
     if (isalpha(c) || c == '\'') { 
      if (count >= 0 && (unsigned char)word[count] == c) { 
       count++; 
      } else { 
       if (count > 0) { 
        printf("%.*s", count, word); 
       } 
       count = -1; 
       putchar(c); 
      } 
     } else { 
      if (count > 0) { 
       if (word[count] == '\0') { 
        printf("CENSORED"); 
       } else { 
        printf("%.*s", count, word); 
       } 
      } 
      if (c == EOF) 
       break; 
      count = 0; 
      putchar(c); 
     } 
    } 
    return 0; 
} 
+0

今、すべてははるかに明確です。提案に感謝します。 –

+0

非常にいいですが、_last_単語は印刷されないかもしれないと思います.128サイズの文字列に制限されています。まだOPの問題をよく説明している。 – chux

+1

@chux:残っている2つの欠陥を指摘していただきありがとうございます。私は2番目のことを意識していましたが、改行されていないファイルの最後の単語が抜けている可能性を見落としました。私は答えを修正しました。 – chqrlie

1
tempWord[0] = '\0'; 

これは、変数がnullにリセットされません。最初の位置に '\ 0'を代入するだけです。しかし、割り当てられた値はまだメモリ内にしかありません。 '\ 0'には最初の位置のみが割り当てられます。ですから、文字配列をリセットするには以下のようにしてください。

memset(tempWord, 0, 128); 

tempWord[0] = '\0'の代わりに上記の行を追加してください。

また、これにより、各単語の末尾に '\ 0'を追加する必要がなくなります。これは動作します。しかし、初めて同じmemset関数を使って文字配列をリセットする必要があります。ループに入る前に、memset関数を使用してtempWordをnullに設定する必要があります。

+0

それは私の問題をmemsetを使用して解決しました。 –

1

tempWord [0] = '\ 0'を使用すると、配列全体がリセットされず、最初の要素だけがリセットされます。あなたのコードを見ると、あなたはどちらか、前に進むmemsetを使用して配列全体をリセットすることができ、2つの方法があります:

memset(tempWord, 0, sizeof tempWord); 

または

が は
memset(tempWord, 0, 128); 

(またはあなただけの最後のサイズによって、それをクリアすることができますあなたが既に含まれているstring.hも必要です)、

または、現在の単語の長さの後に要素を設定して '\ 0'にすることができます(例えば、現在の単語がtheならばtempWord[3]='\0'、以降チェックこれらの2つのIFSの前に配置することができますのチェックのみヌル文字までの文字列)ループは次のようになりますしながら、文字列が等しいかどうか、あなたの新しいしている場合:

{ 
     character = getchar(); 

     if((character<='z' && character>='a')||(character<='Z' && character>='A')||character == 39) 
     {    
      tempWord[count]=character; 
      count++; 

     }else { 
      tempWord[count]='\0'; 

      if(count!=0 && compareWord(tempWord, argv[1])) 
      { 

       printf("CENSORED"); 
       count=0; 


      } 

      if(count!=0 && !compareWord(tempWord, argv[1])) 
      { 

       printWord(tempWord); 
       count=0; 

      } 

      if (count==0) 
      { 
       printf("%c", character); 
      } 
     } 
    } 

(それが動作する、テスト)

+0

@sureshkumar私はmemsetの使用を必要としない2番目の部分をタイプしていました。私は値を置く場所を集めていましたので、投稿する時間がかかりました... – iamnotgoogle

関連する問題