5

入力したものが数字であることを確認したいときに、この問題に遭遇しました。数値の入力に成功すると、scanf関数は 1 を返します。だからここに私が書いたものがあります:

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

しかし、そのようなものを入力するabcdと、ループが永遠に続き、プロンプトが表示されなくなります。

オンラインで調べたところ、キャッシュと関係があることがわかりましたscanf。新しいデータを取得できるように、キャッシュをクリーンアップする必要があります。それでやってみfflushましたがダメでした。

それから私はこれを見ました:

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

次に、「abcd」などを入力すると、うまく機能し、入力を求められました。しかし、「12ab」などを入力すると、再び機能しなくなりました。

入力が実際に数字であることを確認し、scanf("%d", &argu)そうでない場合は別の入力を求める方法はありますか?

編集

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

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

4

5 に答える 5

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. */
}
于 2012-06-21T13:21:34.057 に答える
2

しかし、abcdのようなものを入力すると、ループが永遠に続き、プロンプトが表示されなくなります。

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

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

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

strtol最善の解決策は、すべての入力をテキストとして読み取り、 (整数値の場合) とstrtod(実数値の場合)を使用して数値型に変換することです。例えば:

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);
}

chk10 進数ではない入力ストリームの最初の文字を指します。この文字が空白または 0 ターミネータでない場合、入力文字列は有効な整数ではありません。これにより、 や などの入力が検出され、拒否"12ab"され"abcd"ます。

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

于 2012-06-21T14:29:02.443 に答える
1

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

于 2012-06-21T13:24:21.733 に答える
0

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

于 2012-06-21T13:57:55.633 に答える
-1

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

于 2012-06-24T08:26:50.763 に答える