web-dev-qa-db-ja.com

Cで1文字のscanfを実行する方法

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

これはコードです:

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

なぜうまくいかないのですか?

78
Yuval

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

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

scanf(" %c", &c);

フォーマット文字列の空白は、先頭の空白をスキップするようにscanfに指示し、最初の空白以外の文字は%c変換指定子で読み込まれます。

197
John Bode

まず第一に、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()がフォーマットと一致しない場合、入力ストリーム内の入力を破棄しないことです。たとえば、scanf("%d", &int_var);のようにabcintを入力した場合、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;
}

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

scanf()に関連する他の多くの同様の問題があります。それはそれを避けることが一般的に推奨される理由です。

だから、代替は何ですか?単一文字を読み取るには、代わりに fgets() functionを次のように使用します。

#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()を使用する際に注意すべき1つの詳細は、inutバッファーに十分なスペースがある場合、改行文字で読み込まれます。それが望ましくないなら、あなたはそれを削除することができます:

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 */
14
P.P.

fgetsもgetcharも、この問題を解決するためには機能しません。唯一の回避策は、scanf scanf( "%c"、ch)を使用している間、%cの前にスペースを空けることです。 //動作します

次のような喧嘩でも動作しません..

char line[256];
char ch;
int i;

printf("Enter a num : ");
scanf("%d",&i);
printf("Enter a char : ");

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

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

これは私のためにうまくいく

int main(){
char c;
scanf(" %c",&c);
printf("%c",c);
return 0;
}
1
Praveen samuel

Scanfの前にfflush(stdin);をバッファをクリアするために置きます。

1

これは私が共有したいと思う似たようなことです、

visual Studioで作業している間、次のようなエラーが発生する可能性があります。代わりにscanf_sを使用することを検討してください。廃止予定を無効にするには、_CRT_SECURE_NO_WARNINGSを使用します。

これを防ぐには、次の形式で書く必要があります。

単一文字は次のように読むことができます。

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

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

char c[4];
scanf_s("%4c", &c, _countof(c));

よろしく、

1
Sanberk

getchar()を使ってみてください。代わりに

構文:

void main() {
    char ch;
    ch = getchar();
}
0
kesarling

有効な変数を使用する必要があります。 chは、このプログラムには無効な変数です。 char Aaaを使用してください。

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

テストしてそれが機能します。

0
AL Maruf

コンパイラが空白を無視するように、%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;
}
0
Shahid Nawaz