2

私の質問は、単純に「10 行目と 11 行目のコードが正しく機能しないのはなぜですか?」ということです。私のコードの意図した目的は、元の K&R コードが意図したとおりに実行することですが、(getchar() == '\n') いつでも nc をカウントしないようにすることです。

わずかに変更された K&R コード:

/** K&R - 1.5.2 Character Counting **/
#include <stdio.h>

/* count characters in input; 1st version */
main(){
  long nc;

  nc = 0;
  while (getchar() != EOF){
    if (getchar() != '\n'){
      ++nc;
    }
  }
  printf("%ld\n", nc);
}

64 ビット Windows 7、CodeBlocks10.05、GNU GCC コンパイラを使用しています。

私の現在の進捗状況と理解:

サンプルの実行では、単語twoを入力して Enter キーを押します。これは 4 つの入力に相当します。その後、ctrl+Z を押して、^Zまたは EOF 文字を入力します。次に、プログラムは を出力し1ます。私はそれが印刷されることを期待していました3。唯一の論理的な説明は、私が意図したこととは正反対のことをしているということだと思います(改行文字だけを数えますか?)。結局のところ、単語twoを入力してEnterキーを押すと、たとえば4回と表示され4ます. 入力された改行文字ごとにカウントされているようですがnc、Enterキーを単独で(この場合は4回)押してからEOFを押すと、常に出力されます0. さらに実験を重ねた結果、目に見えない 4 はおそらくこのプログラムにとって魔法の数であることがわかりました。起動してEnterキーを正確に(4で割り切れる数)押すと、EOFが出力され0ます。^Zただし、Enter キーを何度か押した場合、EOF は何もしません。whileループを正しく終了するには、2 行ずつ入力する必要があり、出力され1ます。これは私の心を揺さぶっています!

4

3 に答える 3

6

問題は、カウントをインクリメントするたびに2文字を読み取るため、値を–からgetchar()–に保存する必要があることです。intそれらの1つはEOFテストにあります。2番目は改行テストです。

int c;

while ((c = getchar()) != EOF)
{
    if (c != '\n')
        ++nc;
}

の結果をaではなくgetchar()anに格納する必要がある理由は、可能なすべての値と、個別の値EOFを返すことができるためです。を使用しない場合(に直接保存する場合)、次の2つのいずれかが発生します。intcharcharintchar

  1. が符号付きタイプの場合char、正当な文字(多くの場合、y-umlaut、ÿ、分音付きのラテン文字Y、U + 00FF —少なくともラテン1またはISO 8859-1から派生したコードセット)は、EOFと同等であると解釈されます。プログラムは途中で終了します。
  2. が符号なしタイプの場合char、EOFに相当する文字はないため、プログラムがループを停止することはありません。

これらの状況はどちらも望ましくありません。の戻り値をgetchar()に格納するとint、両方の問題を防ぐことができます。それは「唯一の」(または少なくとも最も単純な)正しい方法です。

于 2012-08-24T21:32:10.530 に答える
5

簡単に言えば、getchar()2回呼び出しているので、各反復で2文字を消費しています。

getchar()呼び出しは入力ストリームから文字を読み取ることを理解する必要があります。改行をテストする場合は、その文字を変数に格納してから、その変数をテストする必要があります。

于 2012-08-24T21:31:36.537 に答える
3
int c;

[...]

while ((c = getchar()) != EOF) {
    if (c != '\n') {
      ++nc;
    }
}

電話をかけるgetchar()たびに、からのキャラクターを消費していますstdin

于 2012-08-24T21:30:56.520 に答える