【C言語】文字を入力してもscanfが終わらない原因と対処法

C言語でプログラムを作成していると、scanf関数を使って入力を受け取る際に、プログラムがうまく動かないことがあります。

特に、文字を入力してもscanfが終わらないという問題は初心者にとってよくあるトラブルです。

目次から探す

scanfが終わらない原因

C言語でプログラムを作成していると、scanf関数を使って入力を受け取る際に、プログラムが期待通りに動作しないことがあります。

特に、文字を入力してもscanfが終わらないという問題は初心者にとってよくあるトラブルです。

ここでは、その原因と具体的な対処法について詳しく解説します。

バッファに残る改行文字

改行文字の影響

scanf関数は標準入力からデータを読み取る際に、入力バッファに残っている改行文字(\n)を無視しません。

これが原因で、次の入力を待つ状態になり、プログラムが停止しているように見えることがあります。

改行文字が残る具体例

例えば、以下のコードを見てください。

#include <stdio.h>
int main() {
    char c;
    int num;
    printf("整数を入力してください: ");
    scanf("%d", &num);
    printf("文字を入力してください: ");
    scanf("%c", &c);
    printf("入力された文字: %c\n", c);
    return 0;
}

このプログラムでは、整数を入力した後に文字を入力するように求めています。

しかし、実行してみると、文字の入力を待たずにプログラムが終了してしまうことがあります。

これは、最初のscanfで入力された整数の後に残った改行文字が次のscanfで読み取られてしまうためです。

フォーマット指定子の誤り

%dと%cの違い

scanf関数では、入力の形式を指定するためにフォーマット指定子を使用します。

例えば、%dは整数を読み取るための指定子であり、%cは文字を読み取るための指定子です。

これらの指定子を正しく使わないと、意図しない動作を引き起こすことがあります。

フォーマット指定子のミスマッチ

例えば、以下のコードを見てください。

#include <stdio.h>
int main() {
    char c;
    int num;
    printf("整数を入力してください: ");
    scanf("%d", &num);
    printf("文字を入力してください: ");
    scanf("%d", &c);  // フォーマット指定子のミスマッチ
    printf("入力された文字: %c\n", c);
    return 0;
}

このプログラムでは、文字を入力するために%dを使用していますが、これは誤りです。

%dは整数を読み取るための指定子であり、文字を読み取るためには%cを使用する必要があります。

このようなフォーマット指定子のミスマッチが原因で、scanfが正しく動作しないことがあります。

入力バッファの問題

バッファの仕組み

C言語の標準入力はバッファリングされています。

つまり、入力されたデータは一時的にメモリ上のバッファに保存され、scanfなどの関数がそのバッファからデータを読み取ります。

このバッファに残ったデータが次の入力に影響を与えることがあります。

バッファがクリアされない場合

例えば、以下のコードを見てください。

#include <stdio.h>
int main() {
    char c;
    int num;
    printf("整数を入力してください: ");
    scanf("%d", &num);
    // バッファに残った改行文字を取り除く
    while (getchar() != '\n');
    printf("文字を入力してください: ");
    scanf("%c", &c);
    printf("入力された文字: %c\n", c);
    return 0;
}

このプログラムでは、scanfで整数を読み取った後に、getcharを使ってバッファに残った改行文字を取り除いています。

これにより、次のscanfで正しく文字を読み取ることができます。

以上のように、scanfが終わらない原因には、バッファに残る改行文字、フォーマット指定子の誤り、入力バッファの問題などが考えられます。

次のセクションでは、これらの問題に対する具体的な対処法について解説します。

scanfが終わらない場合の対処法

改行文字を取り除く

getchar関数の利用

scanfが終わらない原因の一つに、入力バッファに残る改行文字があります。

この改行文字を取り除くために、getchar関数を利用する方法があります。

getchar関数は標準入力から1文字を読み取る関数で、これを使って改行文字を消去します。

以下に具体的な例を示します。

#include <stdio.h>
int main() {
    char c;
    printf("文字を入力してください: ");
    scanf("%c", &c);
    getchar(); // 改行文字を取り除く
    printf("入力された文字: %c\n", c);
    return 0;
}

このコードでは、scanfで文字を読み取った後にgetcharを呼び出して、改行文字を取り除いています。

fflush関数の利用

もう一つの方法として、fflush関数を利用する方法があります。

fflush関数は出力バッファをクリアするための関数ですが、標準入力に対しても使用できます。

ただし、これは標準Cでは未定義の動作であり、環境によっては動作しないことがあります。

以下に例を示します。

#include <stdio.h>
int main() {
    char c;
    printf("文字を入力してください: ");
    scanf("%c", &c);
    fflush(stdin); // 入力バッファをクリア
    printf("入力された文字: %c\n", c);
    return 0;
}

このコードでは、scanfで文字を読み取った後にfflushを呼び出して、入力バッファをクリアしています。

フォーマット指定子の見直し

正しいフォーマット指定子の選び方

scanfを使用する際には、正しいフォーマット指定子を選ぶことが重要です。

例えば、整数を読み取る場合は%d、文字を読み取る場合は%cを使用します。

フォーマット指定子が間違っていると、scanfが正しく動作しないことがあります。

以下に例を示します。

#include <stdio.h>
int main() {
    int num;
    printf("整数を入力してください: ");
    scanf("%d", &num); // 正しいフォーマット指定子
    printf("入力された整数: %d\n", num);
    return 0;
}

このコードでは、整数を読み取るために%dを使用しています。

複数の入力を扱う場合の注意点

複数の入力を扱う場合、各入力に対して適切なフォーマット指定子を使用する必要があります。

また、入力バッファに残る改行文字にも注意が必要です。

以下に例を示します。

#include <stdio.h>
int main() {
    int num;
    char c;
    printf("整数を入力してください: ");
    scanf("%d", &num);
    getchar(); // 改行文字を取り除く
    printf("文字を入力してください: ");
    scanf("%c", &c);
    printf("入力された整数: %d\n", num);
    printf("入力された文字: %c\n", c);
    return 0;
}

このコードでは、整数を読み取った後にgetcharを呼び出して改行文字を取り除き、次に文字を読み取っています。

入力バッファのクリア

バッファをクリアする方法

入力バッファをクリアする方法として、getchar関数をループで使用する方法があります。

これにより、バッファに残っているすべての文字を取り除くことができます。

以下に例を示します。

#include <stdio.h>
void clear_input_buffer() {
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
}
int main() {
    int num;
    printf("整数を入力してください: ");
    scanf("%d", &num);
    clear_input_buffer(); // 入力バッファをクリア
    printf("入力された整数: %d\n", num);
    return 0;
}

このコードでは、clear_input_buffer関数を使用して入力バッファをクリアしています。

バッファクリアのタイミング

入力バッファをクリアするタイミングも重要です。

通常、scanfで入力を読み取った直後にバッファをクリアするのが良いでしょう。

これにより、次の入力が正しく処理されるようになります。

以下に例を示します。

#include <stdio.h>
void clear_input_buffer() {
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
}
int main() {
    int num;
    char c;
    printf("整数を入力してください: ");
    scanf("%d", &num);
    clear_input_buffer(); // 入力バッファをクリア
    printf("文字を入力してください: ");
    scanf("%c", &c);
    printf("入力された整数: %d\n", num);
    printf("入力された文字: %c\n", c);
    return 0;
}

このコードでは、整数を読み取った後に入力バッファをクリアし、次に文字を読み取っています。

これにより、入力が正しく処理されるようになります。

目次から探す