- ベストアンサー
C言語の非標準コンソール関数getch()について
こんにちは。 あるプログラムを作っていると、次のような問題が起きてしまいました。 簡単なプログラムを例にして、説明したいと思います。 #include<stdio.h> #include<conio.h> #include<ctype.h> void main(void) { char ch; int i; do{ ch=getch(); putchar(toupper(ch)); }while(ch!='q'); printf("\n"); scanf("%d",&i); } これはgetch()関数を使い入力された文字を大文字にして画面上に出力するものです。(qが入力されるまで) その後に、意味はありませんが変数iに整数を入力して終了する。 ここで、問題になってくるのがこのプログラムを実行して、abcdefqと入力していくと、画面上にはABCDEFQと表示されます。そして、qが入力されたことでdo文が終了して改行が行われます。次にscanfによりいったん入力待ちになります。 この時、まだ、なにも入力していないにも関わらず、最後にgetchにより入力したqが表示されてしまいます。 qを消してscanfの入力をすればいいのですが、この問題を何とか解決したと思い質問しました。 scanfの後にgetchar()を使うときはscanf入力時の'\n'に注意が必要だということはわかるのですが、上に述べたような問題はこれに似ているのでしょうか? 参考書をみたり自分でもいろいろ試してみたのですがどうもうまくいきません。 どなたか、解決策を知っていたら是非教えて下さい。 できれば、getch()とscanfがどのように作用してこのようなことが起きてしまっているのか説明して頂けたら幸いです。 お手数ですが、みなさま、よろしくお願いいたします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
何か問題が正確に伝わっていなかったりするみたいですね(苦笑) 環境は Windows9X 系でしょうか。 この環境下では、getch と scanf を近いところで使うと問題が起きるんですよ。 OS が呼び出す ReadFile() が、getch() が拾ったはずのキーのキーアップイベントを、もう1度押されたと誤認するようです。 (NT系では正常に動作するそうです) この問題は、scanf の代わりに cscanf を使うか、scanf を使う前に __flush_win95_keyup_events() を呼び出すことで回避できます。 1度試してみて下さい。
その他の回答 (4)
- itohh
- ベストアンサー率45% (210/459)
こんにちは。itohhといいます。 leaz024さん、こんにちは。 初めて知りました!わたしの環境がWinNT&2000なのでそういうことは気がつきませんでした。 もちろん、WinNT&2000で確認してみたところ、leon-10さんが言われている現象は出ないんですよ。 わたしも勉強になりました。ありがとうございます。
お礼
2度目のご回答有難う御座います。 わたしの方が、OSによる問題があるとはわからなかったもので、色々説明不足になってしまい申し訳ありませんでした。
- itohh
- ベストアンサー率45% (210/459)
こんにちは。itohhといいます。 解決策としては、ほかの方がアドバイスしているので。 >できれば、getch()とscanfがどのように作用してこのようなことが >起きてしまっているのか説明して頂けたら幸いです。 これは、「getch()とscanf」の関係で起こっているわけではありません。 do whileループでは、ループの最後で次のループを行うかを判定します。 そのため、getch関数で「q」が入力された後にputcharで出力され、その後、 ループの終了条件を判定します。 >do{ > ch=getch(); <-「q」を入力する。 > putchar(toupper(ch)); <-「Q」を出力する。 >}while(ch!='q'); <-ループ終了条件の判定。 回答者No.1の方の方法で行うのが、スマートな方法だと思いますよ。
お礼
ご回答有難う御座いました。 まず始めに、質問が悪くてすいません。 回答して頂いたことは、理解できます。もう一度説明しますと、 doループでは後判定なので、仮にabcqと入力すると、getch()では入力した文字が画面に出力されない為、画面にはABCQと表示されてscanfの入力待ちになります。ここで、画面にQ大文字のQが表示されてしまうのは構いません。しかし、この大文字のQ以外に小文字のqが表示されてしまうのです。 この小文字のqが表示されてしまうのが気になるのです。バックスペースでこのqを消してから希望の入力値を入れることはできるのですが、できればこのqを表示したくありません。何とかならないでしょうか? あまりうまく説明できていないかもしれません。 お手数ですが、短いプログラムなので、試していただけると幸いです。どのようなことが起こってしまか分かっていただけると思います。 申し訳ありません。 また、アドバイスがありましたら、宜しくお願い致します。
- brogie
- ベストアンサー率33% (131/392)
入力バッファーをクリアーするためなら、つぎの文をscanfの前に入れるとよいでしょう。 fflush(stdin); または rewind(stdin) 先頭に#include <stdio.h>があれば結構です。 以上。
お礼
ご回答有難う御座います。 scanfのあとにgetchar()関数を使う時には、入力バッファをクリアーする為に('\n'をクリアーする)rewind(stdin)やfflush(stdin)を使うのは分かります。 この場合はその方法用いても解決できませんでした。 すいません。なにか分かりましたら、また、宜しくお願い致します。
- ---
- ベストアンサー率50% (7/14)
void main(void) { char ch; int i; ch=getch(); while(ch!='q') { putchar(toupper(ch)); ch=getch(); } printf("\n") scanf("%d",&i); } とすればよいのでは?
お礼
ご回答ありがとうございました。 上のプログラムはqが入力された時は大文字のQが出力されないでscanf文に行くだけになってしまい。scanfで入力する前にqは画面に出力されてしまうのです。 すいません。
お礼
ご回答有難う御座います。 はい、環境はWindows98です。OSの問題があったのですね!! 勉強になりました。早速試してみたいと思います。 勉強中なもので、また、みかけたらご指導の程宜しくお願い致します。 また、回答してくださったみなさま、質問の際、環境について説明を書き落としてしまい申し訳ありませんでした。