2012-06-21 2 views
5

私は入力が何であるかをチェックしたいときにこの問題に遭遇しました。 scanf関数は、数値の入力に成功すると1を返します。それにABCDのようなI入力物事は、ループは永遠に行くと、プロンプトのために停止しないだろうというとき12ab to scanf( "%d"、&argu)のようなものを入力するとどうなりますか?

int argu; 
while(scanf("%d",&argu)!=1){ 
    printf("Please input a number!\n"); 
} 

をしかし:だから、ここで私が書いたものです。

オンラインで調べたところ、キャッシュと何か関係があり、scanfが新しいデータを取得できるように、キャッシュを消去する必要があることがわかりました。だから私はfflushを試みたが、うまくいかなかった。 「ABCD」のようなI入力の事は、それがうまく働いていた、それは私の入力を求められたら、次に

int argu,j; 
while(scanf("%d",&argu)!=1){ 
    printf("Please input a number!\n"); 
    while((j=getchar())!='\n' && j != '\n'); 
} 

は、その後、私はこれを見ました。しかし、「12ab」のようなものを入力すると、もう一度動作しません。

scanf( "%d"、& argu)の入力を確認できる方法は実際には数字で、入力されていない場合はプロンプトが表示されますか?

EDIT

私は答えを見て、while(*eptr != '\n')を使用して私の問題を解決しました。

fgets関数は実際には配列に '\ n'を読み取り、fgetは読み取らないことに注意してください。ので注意してください。

答えて

4

fgets()を使用して完全な行を読み取ってから、入力ストリームから「オンザフライ」で解析するのではなく、検査することをお勧めします。

無効な入力を無視する方が簡単です。

fgets()を使用し、次にstrtol()を使用して数値に変換すると、その数値の後に後続のデータがあるかどうかがわかりやすくなります。例えば

char line[128]; 

while(fgets(line, sizeof line, stdin) != NULL) 
{ 
    char *eptr = NULL; 
    long v = strtol(line, &eptr, 10); 
    if(eptr == NULL || !isspace(*eptr)) 
    { 
    printf("Invalid input: %s", line); 
    continue; 
    } 
    /* Put desired processing code here. */ 
} 
+0

fgets(s、10、stdin)のようなコードを使用しますか? – Gnijuohz

+0

ありがとう!私はstrtolを知らなかった。多くを学んだ! – Gnijuohz

+0

申し訳ありませんが、 'if(eptr == NULL ||!isspace(* eptr))'を説明できますか?あなたが与えたコードを使うとき、'12 34 'のような入力は受け入れられますが、そうではありません。 eptrが指し示す「1234」と「12ab」と「12 34」を入力するとどうなりますか? – Gnijuohz

1

私は、文字列として入力を取得し、その中に数字以外の文字をチェックすることをお勧めします。入力が有効な場合はsscanf(str,"%d",&i);によって文字列をintに変換するか、そうでなければエラーを表示します。

1

ループ内でscanf( "%* [^ \ n] \ n")を呼び出すだけで、 "キャッシュ"は破棄されます。

+0

私はそれを試みました。それはうまくいかなかった。 – Gnijuohz

+0

これは、 'fflush'の動作が入力ストリームに対して定義されていないためです。 [C言語標準](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf)、セクション7.19.5.2、パラグラフ2を参照してください。 –

+0

どちらも正しいです。しかし、編集がうまくいきました(標準に基づいて)。 – Spidey

2

しかし、abcdのようなものを入力すると、ループは永遠に進み、プロンプトで停止しません。

scanfは、変換指定子と一致しない文字を検出すると、それが入力ストリームに残るからです。基本的には、scanfは入力ストリームからaという文字を読み取り、%d変換指定子の有効な一致ではないと判断し、入力ストリームに戻します。次回はループを通って同じことをします。そしてまた。そしてまた。そしてまた。

fflushは、入力ストリームで機能するように定義されていないため、良い解決策ではありません。

入力"12ab"の場合、scanf"12"を読み取り、変換します。入力ストリームには"ab"が残っています。

あなたの入力をすべてテキストとして読み取ってから、strtol(整数値の場合)およびstrtod(実際の値の場合)を使用して数値タイプに変換することをお勧めします。例えば、10進数字でない入力ストリームの最初の文字に

char input[SIZE]; // assume SIZE is big enough for whatever input we get 
int value; 

if (fgets(input, sizeof input, stdin) != NULL) 
{ 
    char *chk; 
    int tmp = (int) strtol(input, &chk, 10); 
    if (isspace(*chk) || *chk == 0) 
    value = tmp; 
    else 
    printf("%s is not a valid integer string\n", input); 
} 

chkポイント。この文字が空白文字または0ターミネータでない場合、入力文字列は有効な整数ではありません。これにより、"12ab""abcd"などの入力が検出され、拒否されます。

scanfあなたの入力が常に適切に形成され、正常に動作することがわかっている場合は、良い解決策です。 の入力がでない場合は、fgetsを使用して必要に応じて変換してください。

0

ループ内にscanf("%*[^\n]\n")を呼び出します。これは、キャッシュに関連するものをすべて破棄するのに十分なはずです。

関連する問題