プロが教えるわが家の防犯対策術!

趣味でプログラミングをしております。
環境は、以下です。
Windows10
Mingw-w64
gcc version 5.2.0 (Rev4, Built by MSYS2 project)

https://oshiete.goo.ne.jp/qa/9287118.htmlの回答2にて、
3つの数字を入力し、数字でない場合は再入力を促すプログラムを提示しました。
これについて、他の回答者様より「fflush(stdin); は一般にはやっていけない操作」との回答をいただきました。

私の環境では、fflush(stdin)を使用しないと以下の様に1回目に誤ったデータを入力すると、再入力時のメッセージが2回繰り返し表示されます。
(推測ですが、windowsで改行コードが2Byteであることから発生しているのではと考えています)

fflush(stdin)を使用しないで、この問題を回避する適切な方法がありましたらご教示ください。

よろしくお願いします。


----------実行結果(fflush(stdin)を使用しない場合)
$ ./a.exe
重複しない3つの数字:abc
重複しない3つの数字:重複しない3つの数字:abc
重複しない3つの数字:重複しない3つの数字:
----------


----------ソース
#include <ctype.h>

#define BUF_SIZE 3 // 3文字

int main(void){
char buf[BUF_SIZE + 1];
int user;

while(1){
fflush(stdin);
printf("重複しない3つの数字:");
fflush(stdout);

fgets(buf, BUF_SIZE + 1, stdin);
if(!isdigit(buf[0])) continue; // 1文字目が数字かチェック
if(!isdigit(buf[1])) continue; // 2文字目が数字かチェック
if(!isdigit(buf[2])) continue; // 3文字目が数字かチェック
break;
}
user = atoi(buf);
printf("number : %d", user);

return 0;
}
----------

A 回答 (1件)

>他の回答者様より「fflush(stdin); は一般にはやっていけない操作」との回答をいただきました。



規格にstdinに対して実施した場合の動作が明記されていないから。
だったかと。
実装依存する。ということです。


>推測ですが、windowsで改行コードが2Byteであることから発生しているのではと考えています

ライブラリー依存でしょうかね。
¥rと¥nの両方をfgets()が改行として処理したのかも知れません。
gccだし。

>fflush(stdin)を使用しないで、この問題を回避する適切な方法がありましたらご教示ください。

読み込み用のバッファをもう少し大きく用意する。でしょうか。

1回目、"abc"を読み込みます。
第2引数で指定した3バイトに達したため。
stdinのバッファには¥rと¥nが残ってます。

2回目、¥rを読み込みます。
fgets()の仕様により改行コードに到達したため。

1回目の読み込みで残るのに注意です。
# 2回目で¥rだけなのか¥r¥nなのか、はたまた¥r¥nが¥nに変換されるのか…はfgets()の後で内容確認してください。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございました。

> 読み込み用のバッファをもう少し大きく用意する。でしょうか。

BUF_SIZEを3から4以上に変更することで発生しなくなりました。


fgetsの直後に配列bufの内容を表示させていたところ以下の様になりました。
----------
fgets(buf, BUF_SIZE + 1, stdin);
for(i = 0; i < BUF_SIZE + 1; i++) printf("%d : %02x\n", i, buf[i]);
----------

\r(0x0a)が入力バッファに残っていたことが原因だった様です。
\r\nが併せて配列buf上の\0になると思っていたのですが、\rは単独で配列に読み込まれてしまうのですね、勉強になりました。


実行結果
----------BUF_SIZE 3(問題発生)
$ ./a.exe
重複しない3つの数字:abc
0 : 61
1 : 62
2 : 63
3 : 00
重複しない3つの数字:0 : 0a
1 : 00
2 : 63
3 : 00
----------

----------BUF_SIZE 4(正常)
$ ./a.exe
重複しない3つの数字:abc
0 : 61
1 : 62
2 : 63
3 : 0a
4 : 00
重複しない3つの数字:
----------

----------BUF_SIZE 5(正常)
$ ./a.exe
重複しない3つの数字:abc
0 : 61
1 : 62
2 : 63
3 : 0a
4 : 00
5 : 00
重複しない3つの数字:
----------

お礼日時:2016/05/25 08:24

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!