scanf()は、改行文字をバッファに残します


87

私は次のプログラムを持っています:

int main(int argc, char *argv[])
{
  int a, b;
  char c1, c2;
  printf("Enter something: ");
  scanf("%d",&a); // line 1
  printf("Enter other something: ");
  scanf("%d", &b); // line 2

  printf("Enter a char: ");
  scanf("%c",&c1); // line 3
  printf("Enter another char: ");
  scanf("%c", &c2); // line 4

  printf("Done"); // line 5

  system("PAUSE");

  return 0;
}

私がCの本を読んだとき、著者はscanf()バッファに改行文字を残したと言っています。したがって、プログラムはユーザーがデータを入力するために4行目で停止するのではなく、c2に改行文字を格納してに移動します。 5行目。

そうですか?

ただし、これはcharデータ型でのみ発生しますか?int1、2、3行目のようなデータ型ではこの問題は見られなかったので、正しいですか?


単一の文字をfflush(stdin)呼び出す前に使用できることが提案される場合がありscanf()ます。その方法の長所と短所および代替方法(Windowsでは多かれ少なかれ機能し、他のほとんどの場所では機能しない)の説明については、「使用法fflush(stdin)」をお読みください。
ジョナサンレフラー2018

参照している本を教えてください。
スーリヤキラン

回答:


78

このscanf()関数は、文字以外の変換を解析しようとする前に、先頭の空白を自動的にスキップします。文字形式(主に%c;スキャンセット%[…]—および%n)は例外です。空白をスキップしません。

" %c"オプションの空白をスキップするには、先頭の空白とともに使用します。scanf()フォーマット文字列で末尾の空白を使用しないでください。

これでも、入力ストリームに残っている末尾の空白は、行の終わりまでも消費されないことに注意してください。同じ入力ストリームを使用している場合、getchar()またはfgets()同じ入力ストリーム上にある場合は、注意してください。他の文字以外の変換の場合と同様に、scanfが変換前に空白をスキップするようになってい%dます。


のリテラルテキストのように、変換以外の非空白の「ディレクティブ」(POSIX scanf用語を使用するため)もscanf("order = %d", &order);空白をスキップしないことに注意してください。リテラルorderは、読み取られる次の文字と一致する必要があります。

したがって" order = %d"、前の行から改行をスキップしたいが、この質問のように固定文字列でリテラル一致が必要な場合は、おそらくそこが必要です。


7
%c%n%[]先頭の空白を消費しない3つの指定された期待があります。
chux -復活モニカ

@chuxそれで、他の場合には、scanfはバッファ内の前にすべての空白をクリアするか、入力のためにそれらを無視しますが、それらはまだそこにありますか?
Suraj Jain

はい@SurajJain、
chux -復活モニカ

3
参照してくださいに空白を末尾のscanf()フォーマット文字列scanf()私はそれが一度だけ頼むことを期待しながら、入力のために二度尋ねるフォーマット文字列に後続の空白をの議論のために。それらは悪い考えです—人間の相互作用を期待するなら驚くほど悪いですし、プログラムの相互作用には悪いです。
ジョナサンレフラー2017年

31

を使用しscanf(" %c", &c2);ます。これはあなたの問題を解決します。


7

別のオプション(ここから取得)は、assignment-supressionオプションを使用して改行を読み取って破棄することです。これを行うには、私達はちょうど間にアスタリスクを持つ文字を読むためのフォーマットを置く%c

scanf("%d%*c",&a); // line 1
scanf("%c%*c",&c1); // line 3

scanf 次に、次の文字(つまり、改行)を読み取りますが、ポインターには割り当てません。

ただし、最終的には、FAQの最後のオプションを2番目にします

または、要件によっては、scanf()/ getchar()を忘れて、fgets()を使用してユーザーからテキスト行を取得し、自分で解析することもできます。


2
この手法の問題点は、ユーザーがaスペースを入力してから改行を入力すると、抑制された文字変換がスペースを読み取り、改行を残すことです。ユーザーsupercalifragilisticexpialidociousが期待どおりに入力した場合、a処理する余分な文字がたくさんあります。末尾の抑制された変換が成功したかどうかもわかりません—からのリターンにはカウントされませんscanf()
ジョナサンレフラー

3

getchar()2番目を呼び出す前に使用しscanf()ます。

scanf("%c", &c1);
getchar();  // <== remove newline
scanf("%c", &c2);

1
これは、ユーザーが他に何も入力しなかった場合に機能します。たとえば、末尾の空白などです。しかし、次の改行にスキャンするループほど良くはありません:(int c; while ((c = getchar()) != EOF && c != '\n') ;コメントにない場合は3行に渡って書かれます)。多くの場合、それで十分です。それは絶対確実ではありません(そして、愚か者は物事をクラッシュさせることについて非常に賢いことを覚えておく必要があります)。
ジョナサンレフラー2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.