🌕
fgetsとsscanfを使って、1ケタの数字を標準入力から受け取る方法
サンプルコード
1から9までの整数を受け取りたい場合のコードを考えていく。
#include <stdio.h>
int main(void)
{
int number;
char str[5];
str[0] = '\0';
str[1] = '\0';
str[2] = '\0';
str[3] = '\0';
str[4] = '\0';
while (1)
{
fgets(str, sizeof(str), stdin);
sscanf(str, "%d", &number);
printf("str[0]: %c\n", str[0]); //それぞれ何が含まれているかを確認するためにstrの中身を出力
printf("str[1]: %c\n", str[1]);
printf("str[2]: %c\n", str[2]);
printf("str[3]: %c\n", str[3]);
printf("str[4]: %c\n", str[4]);
if (1 <= number && number <= 9)
{
printf("Input number is: %d\n", number);
return (number);
}
printf("Wrong input. Please enter a number. (1 ~ 9)\n");
}
}
サンプルコードの問題点
・標準入力がstrの長さを超える場合(今回の例の場合だと2文字以上)、格納されなかった余りの文字は次のループ時に自動的に格納され、Wrong input. Please enter a number.
が複数回表示されてしまう。
このサンプルコードでわかること
・ str[4]
には常に'\0'が格納される。
・ 入力がstrの長さを超える場合、格納されなかった余りの文字は次のループ時に自動的にstrに格納される。
実行結果
正常:「2」を入力した場合。
$ ./a.out
2 //標準入力
str[0]: 2
str[1]:
str[2]:
str[3]:
str[4]:
Input number is: 2
正常:「111」を入力した場合
$ ./a.out
111 //標準入力
str[0]: 1
str[1]: 1
str[2]: 1
str[3]:
str[4]:
Wrong input. Please enter a number. (1 ~ 9)
問題の挙動:「1111」を入力した場合
$ ./a.out
1111 //標準入力
str[0]: 1
str[1]: 1
str[2]: 1
str[3]: 1
str[4]: //文字列の最終尾のため、常に'\0'が入力されている
Wrong input. Please enter a number. (1 ~ 9)
str[0]: //`1111`を入力したあとの'\n'(改行、Enter)が、5文字として`str[0]`に格納される。
str[1]: //`1111`は文字列として認識されるので、`1111\n\0` と最後の'\0'がここに格納。
str[2]: 1 //最初に格納されたものが残っている
str[3]: 1 //最初に格納されたものが残っている
str[4]:
Wrong input. Please enter a number. (1 ~ 9) //この部分が問題で、2度目の表示がされる。直前に何も入力していないが、最初の標準入力で余った文字分(`\n`と`\0`)への処理。
解決策
・標準入力がstrの長さを超える場合(今回の例の場合だと2文字以上)、格納されなかった余りの文字は次のループ時に自動的に格納されるので、 余計なループを減らすには\n
がstrのいずれにもない場合にfgets関数を呼び出し、余分な標準入力を処理する。
#include <stdio.h>
int main(void)
{
int number;
char str[5];
str[0] = '\0';
str[1] = '\0';
str[2] = '\0';
str[3] = '\0';
str[4] = '\0';
while (1)
{
fgets(str, sizeof(str), stdin);
sscanf(str, "%d", &number);
printf("str[0]: %c\n", str[0]);
printf("str[1]: %c\n", str[1]);
printf("str[2]: %c\n", str[2]);
printf("str[3]: %c\n", str[3]);
printf("str[4]: %c\n", str[4]);
if (1 <= number && number <= 9)
{
printf("Input number is: %d\n", number);
return (number);
}
printf("Wrong input. Please enter a number. (1 ~ 9)\n");
while (str[1] != '\n' && str[2] != '\n' && str[3] != '\n')
fgets(str, sizeof(str), stdin);
}
}
実行結果
「1111」を入力した場合。
$ ./a.out
1111 //標準入力
str[0]: 1
str[1]: 1
str[2]: 1
str[3]: 1
str[4]:
Wrong input. Please enter a number. (1 ~ 9)
//2度目の「Wrong input. 〜」は表示されず、標準入力が求められる。
Discussion