126

C: ユーザーから char を取得しようとしていますがscanf、それを実行すると、プログラムはユーザーが何かを入力するのを待ちません...

これはコードです:

char ch;
printf("Enter one char");
scanf("%c", &ch);
printf("%c\n",ch);

なぜ機能しないのですか?

4

11 に答える 11

283

変換指定子は%c先頭の空白を自動的にスキップしないため、入力ストリームに (たとえば、前のエントリからの) 迷子の改行がある場合、scanf呼び出しはすぐにそれを消費します。

この問題を回避する 1 つの方法は、フォーマット文字列の変換指定子の前に空白を入れることです。

scanf(" %c", &c);

書式文字列の空白は、scanf先頭の空白をスキップするように指示し、空白以外の最初の文字が%c変換指定子で読み取られます。

于 2012-11-24T16:31:02.577 に答える
31

まずは避けることscanf()。それを使用することは、苦痛に値するものではありません。

参照:誰もが scanf を使用しないように言うのはなぜですか? 代わりに何を使用すればよいですか?

で空白文字を使用するscanf()と、入力ストリームに残っている空白文字がいくつでも無視されます。さらに入力を読み取る必要がある場合はどうすればよいでしょうか? 検討:

#include <stdio.h>

int main(void)
{
   char ch1, ch2;

   scanf("%c", &ch1);  /* Leaves the newline in the input */
   scanf(" %c", &ch2); /* The leading whitespace ensures it's the
                          previous newline is ignored */
   printf("ch1: %c, ch2: %c\n", ch1, ch2);

   /* All good so far */

   char ch3;
   scanf("%c", &ch3); /* Doesn't read input due to the same problem */
   printf("ch3: %c\n", ch3);

   return 0;
}

3 番目の scanf() は先頭の空白を使用して同じ方法で修正できますが、常に上記のように単純になるとは限りません。もう 1 つの大きな問題は、scanf()フォーマットに一致しない場合、入力ストリーム内の入力を破棄しないことです。たとえば、次のように入力するabcと、読み取りと破棄が必要になります。検討:intscanf("%d", &int_var);abc

#include <stdio.h>

int main(void)
{
    int i;

    while(1) {
        if (scanf("%d", &i) != 1) { /* Input "abc" */
            printf("Invalid input. Try again\n");
        } else {
            break;
        }
    }

    printf("Int read: %d\n", i);
    return 0;
}

もう 1 つの一般的な問題は、scanf()との混合fgets()です。検討:

#include <stdio.h>

int main(void)
{
    int age;
    char name[256];
    printf("Input your age:");
    scanf("%d", &age); /* Input 10 */
    printf("Input your full name [firstname lastname]");
    fgets(name, sizeof name, stdin); /* Doesn't read! */
    return 0;
}

fgets()前の scanf() 呼び出しによって残された改行が読み取られ、 fgets() が改行に遭遇すると入力の読み取りを終了するため、への呼び出しは入力を待機しません。

に関連する他の多くの同様の問題がありますscanf()。そのため、一般的には避けることをお勧めします。

それで、代替案は何ですか?代わりに次のように関数を使用fgets()して、単一の文字を読み取ります。

#include <stdio.h>

int main(void)
{
    char line[256];
    char ch;

    if (fgets(line, sizeof line, stdin) == NULL) {
        printf("Input error.\n");
        exit(1);
    }

    ch = line[0];
    printf("Character read: %c\n", ch);
    return 0;
}

fgets()inut バッファに十分なスペースがある場合、改行文字を読み込む際に注意すべき点が 1 つあります。望ましくない場合は、削除できます。

char line[256];

if (fgets(line, sizeof line, stdin) == NULL) {
    printf("Input error.\n");
    exit(1);
}

line[strcpsn(line, "\n")] = 0; /* removes the trailing newline, if present */
于 2016-12-03T15:02:48.383 に答える
5

ここに私が共有したい同様のことがあります、

Visual Studio で作業しているときに、次のようなエラーが発生する可能性があります。

'scanf': 関数または変数が安全でない可能性があります。scanf_s代わりに使用することを検討してください。非推奨を無効にするには、使用します_CRT_SECURE_NO_WARNINGS

これを防ぐには、次の形式で記述します。

1 つの文字は、次のように読み取ることができます。

char c;
scanf_s("%c", &c, 1);

NULL で終了しない文字列の複数の文字が読み取られる場合、幅の指定とバッファー サイズとして整数が使用されます。

char c[4];
scanf_s("%4c", &c, _countof(c));
于 2015-01-13T08:46:28.143 に答える
-2

char likeの代わりに string を使用する

char c[10];
scanf ("%s", c);

私はそれがうまくいくと信じています。

于 2016-06-22T16:47:21.253 に答える
-3

有効な変数を使用する必要があります。chこのプログラムの有効な変数ではありません。使用しchar Aaaます。

char aaa;
scanf("%c",&Aaa);

テスト済みで動作します。

于 2018-12-17T01:01:41.860 に答える
-3

コンパイラが空白を無視するように、%c 変換指定子の前にスペースを提供します。プログラムは次のように記述できます。

#include <stdio.h>
#include <stdlib.h>
int main()
{
    char ch;
    printf("Enter one char");
    scanf(" %c", &ch); /*Space is given before %c*/
    printf("%c\n",ch);
return 0;
}
于 2014-10-11T15:03:02.633 に答える