c言語scanfバッファ問題


今日scanf関数を再帰的に呼び出して入力した文字を取得したときに発見されたこの問題は、前にも遭遇したことがあるので、記録しておきます.
テスト例は次のとおりです.
#include <stdlib.h>
#include <stdio.h>

int main()
{
    int n = 5;
    char c[n];
    for(int i = 0; i < n; ++i) {
        scanf("%c", &c[i]);
    }

    printf("-----------
"); printf("%s", c); return 0; }

このプログラムを書く前に、c[n]文字配列にabcdeを格納できることを期待していました.そこで、a、リターンを順次入力し、b、リターンを入力します.cを入力すると、プログラムが文字配列cの内容を印刷し、実行が完了し、gdbデバッグツールで単一ステップで実行すると、a、リターンを入力した後、c[0]の値がaであることがわかります.その後++iは、scanf("%c",&c[i])言語を実行し続けますが、プログラムは文字の再入力を促すことはありません.この場合、c[1]の文字が'、つまり、入力したリターン記号はバッファに保存され、scanf関数は直接この値を読み取ります.
ソリューションでは、scanf文の後にfpurge(stdin)文を追加します.以下に示します.
#include <stdlib.h>
#include <stdio.h>

int main()
{
    int n = 5;
    char c[n];
    for(int i = 0; i < n; ++i) {
        scanf("%c", &c[i]);
        fpurge(stdin);
    }

    printf("-----------
"); printf("%s", c); return 0; }

man fpurgeのドキュメントを表示するには、次の手順に従います.
int fpurge(FILE *stream);

The function fpurge() erases any input or output buffered in the given stream. For output streams this discards any unwritten output. For input streams this discards any input read from the underlying object but not yet obtained via getc(3); this includes any text pushed back via ungetc(3).
すなわち、fpurge関数は、現在のバッファ内のコンテンツを直接削除します.
ある学生はfflush関数を使いたいかもしれませんが、これはだめです.fflushの関数の説明は以下の通りです.
int fflush(FILE *stream);

The function fflush() forces a write of all buffered data for the given output or update stream via the stream's underlying write function. The open status of the stream is unaffected.
If the stream argument is NULL, fflush() flushes all open output streams.
以上の説明から、fflushはバッファ内のデータを所定の出力に強制的に出力することであり、上記の例では、scanf関数の後にfflush関数を呼び出すのは何の役にも立たない.この場合、後続の「文字」に出力が指定されていないためである.
私の微博:http://weibo.com/caryaliu