getchar関数の挙動を調べていて「はて?」と思うことがあったので、メモしておきます。
前回の記事に書いたことをきちんと理解していれば気づけたはずですが、気づかなかったのは私がぬるいせいです・・・orz。
環境
Microsoft Visual Studio Community 2019 Version 16.6.5 Windows 10 Pro Version 1903
使用したコード
#include <stdio.h> #include <conio.h> /* getche()に必要 */ int main(void) { char ch; do { printf("A、B、Cのどれかを入力してちょ: "); ch = getchar(); /* ch = getche(); */ printf("\n"); } while (ch != 'A' && ch != 'B' && ch != 'C'); if (ch == 'A') printf("Aアルよ"); else if (ch == 'B') printf("Bアルよ"); else printf("Cアルよ"); return 0; }
このコードを実行した際に、わざとA、B、C以外の文字を入力して、どのように動くのか調べました(以下の例では F を入力しています)。
getchar関数を使用した時の挙動
A、B、Cのどれかを入力してちょ: F A、B、Cのどれかを入力してちょ: A、B、Cのどれかを入力してちょ:
「A、B、Cのどれかを入力してちょ:」が、なぜか2回表示されました。
getche関数を使用した時の挙動
A、B、Cのどれかを入力してちょ: F A、B、Cのどれかを入力してちょ:
getche関数を使ったコードでは1回だけ表示されました。
疑問点
getchar関数を使用した場合に、なぜ「A、B、Cのどれかを入力してちょ:」が2回表示されるのか分かりませんでした。
最初は(失礼ながら)Visual Studio がおかしいのかなと思い、Ubuntuを起動して gccでコンパイルしてみましたが、同じ結果になりました。
そこで、ネット検索をしたところ、以下の記事がありました。
ネットに載っていた質問と回答
参考URL https://oshiete.goo.ne.jp/qa/5918988.html
<質問文>
変な現象に遭遇しました。1文字入力して「入力した文字は~です。」と x が入力されるまで繰り返してくださいというプログラムを書きました↓
#include <stdio.h> main() { char a; do { a = getchar(); printf("入力した文字は%cです。",a); } while(a != 'x'); }
ところが実行して、たとえばキーボードのaを押してenterキーを押すと
入力した文字はaです。入力した文字は です。
と表示されるのです!!「入力した文字はaです。」だけでいいのに1つ多く出力されます。このソースは間違ってますか?
<回答>
getcharは入力した文字をそのまま返します。
> キーボードのaを押してenterキーを押すと
aの後でenterキーを押しているのだから、enterも入力されます。
すなわち'\n'が入力されているので、printf文でも'\n'(改行)が出力されます。
getcharの入力の終りはscanf等のようなenterではなくて、ctrl+Zです。
(備考)
引用した記事にはgetchar関数の入力終了にCtrl + Z を使うと書かれていますが、私の環境で実験したところ、うまく行きませんでした。
思ったこと
前回の記事に書いたように、getchar関数はEnterが押されるまで次の処理に進みません。(復帰しない、と言った方がいいのかもしれませんが。)
必ずEnterを押すとなると、この記事に載せた状況に陥ると思うので、他の方法を使った方が良さそうです。getche関数を使う方法以外にもやり方はあると思うのですが、それをやるにはもう少し私自身が学習する必要があるので、この件はいずれまた。