• ベストアンサー

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がどのように作用してこのようなことが起きてしまっているのか説明して頂けたら幸いです。 お手数ですが、みなさま、よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • leaz024
  • ベストアンサー率75% (398/526)
回答No.4

何か問題が正確に伝わっていなかったりするみたいですね(苦笑) 環境は Windows9X 系でしょうか。 この環境下では、getch と scanf を近いところで使うと問題が起きるんですよ。 OS が呼び出す ReadFile() が、getch() が拾ったはずのキーのキーアップイベントを、もう1度押されたと誤認するようです。 (NT系では正常に動作するそうです) この問題は、scanf の代わりに cscanf を使うか、scanf を使う前に __flush_win95_keyup_events() を呼び出すことで回避できます。 1度試してみて下さい。

leon-10
質問者

お礼

ご回答有難う御座います。 はい、環境はWindows98です。OSの問題があったのですね!! 勉強になりました。早速試してみたいと思います。 勉強中なもので、また、みかけたらご指導の程宜しくお願い致します。 また、回答してくださったみなさま、質問の際、環境について説明を書き落としてしまい申し訳ありませんでした。

その他の回答 (4)

  • itohh
  • ベストアンサー率45% (210/459)
回答No.5

こんにちは。itohhといいます。 leaz024さん、こんにちは。 初めて知りました!わたしの環境がWinNT&2000なのでそういうことは気がつきませんでした。 もちろん、WinNT&2000で確認してみたところ、leon-10さんが言われている現象は出ないんですよ。 わたしも勉強になりました。ありがとうございます。

leon-10
質問者

お礼

2度目のご回答有難う御座います。 わたしの方が、OSによる問題があるとはわからなかったもので、色々説明不足になってしまい申し訳ありませんでした。

  • itohh
  • ベストアンサー率45% (210/459)
回答No.3

こんにちは。itohhといいます。 解決策としては、ほかの方がアドバイスしているので。 >できれば、getch()とscanfがどのように作用してこのようなことが >起きてしまっているのか説明して頂けたら幸いです。 これは、「getch()とscanf」の関係で起こっているわけではありません。 do whileループでは、ループの最後で次のループを行うかを判定します。 そのため、getch関数で「q」が入力された後にputcharで出力され、その後、 ループの終了条件を判定します。 >do{ >  ch=getch();       <-「q」を入力する。 >  putchar(toupper(ch));  <-「Q」を出力する。 >}while(ch!='q');       <-ループ終了条件の判定。 回答者No.1の方の方法で行うのが、スマートな方法だと思いますよ。

leon-10
質問者

お礼

ご回答有難う御座いました。 まず始めに、質問が悪くてすいません。 回答して頂いたことは、理解できます。もう一度説明しますと、 doループでは後判定なので、仮にabcqと入力すると、getch()では入力した文字が画面に出力されない為、画面にはABCQと表示されてscanfの入力待ちになります。ここで、画面にQ大文字のQが表示されてしまうのは構いません。しかし、この大文字のQ以外に小文字のqが表示されてしまうのです。 この小文字のqが表示されてしまうのが気になるのです。バックスペースでこのqを消してから希望の入力値を入れることはできるのですが、できればこのqを表示したくありません。何とかならないでしょうか? あまりうまく説明できていないかもしれません。 お手数ですが、短いプログラムなので、試していただけると幸いです。どのようなことが起こってしまか分かっていただけると思います。 申し訳ありません。 また、アドバイスがありましたら、宜しくお願い致します。

  • brogie
  • ベストアンサー率33% (131/392)
回答No.2

入力バッファーをクリアーするためなら、つぎの文をscanfの前に入れるとよいでしょう。 fflush(stdin); または rewind(stdin) 先頭に#include <stdio.h>があれば結構です。 以上。

leon-10
質問者

お礼

ご回答有難う御座います。 scanfのあとにgetchar()関数を使う時には、入力バッファをクリアーする為に('\n'をクリアーする)rewind(stdin)やfflush(stdin)を使うのは分かります。 この場合はその方法用いても解決できませんでした。 すいません。なにか分かりましたら、また、宜しくお願い致します。

  • ---
  • ベストアンサー率50% (7/14)
回答No.1

void main(void) { char ch; int i; ch=getch(); while(ch!='q') { putchar(toupper(ch)); ch=getch(); } printf("\n") scanf("%d",&i); } とすればよいのでは?

leon-10
質問者

お礼

ご回答ありがとうございました。 上のプログラムはqが入力された時は大文字のQが出力されないでscanf文に行くだけになってしまい。scanfで入力する前にqは画面に出力されてしまうのです。 すいません。

関連するQ&A

  • C言語プログラム

    したのプログラムでgetch()の代わりにscanf()を使って、入力した数が負なら終了、正なら"次の数を入力してください"と表示してループを続けるプログラムを作りたいのですが、どこを変えればよいのですか? #include<stdio.h> #include<conio.h> void main() { int i=1,sum=0; char c='m'; while(c!='e')//eでない限りwhileループを実行する { sum=sum+i; printf("\n1 kara %d madewo tasuto %d desu.\n",i,sum); i++; printf("nanikakeywo oshitekudasai.owaru tokiha 'e'\n"); c=getch(); } printf("loopwo nukemashita\n"); getch(); }

  • C言語(while構文)

    #include<stdio.h> #include<conio.h> void main() { int i=1,sum=0; char c='m'; while(c!='e')//eでない限りwhileループを実行する { sum=sum+i; printf("\n1 kara %d madewo tasuto %d desu.\n",i,sum); i++; printf("nanikakeywo oshitekudasai.owaru tokiha 'e'\n"); c=getch(); } printf("loopwo nukemashita\n"); getch(); } getch()の代わりに、scanf()を使って整数値を入力させ、負の数が入力されたら終了するプログラム(正を入力したら「次の数値を入力せよ」とだして、繰り返す。)を造りたいのですが、どこを変えればよいか教えてください。

  • C言語でタイミングを合わせるゲームを作っているのですが・・・。【getch()】

    C言語で壁に向かって衝突していくボールをタイミングよくスペースキーを押すことで打ち返すプログラムを作っています(多分実行しないと分かりにくいかも)。 そこでキーの入力にgetch()関数を使っていますが、これだと何かキーが入力されるまで永遠と待ち続けてしまうので、タイミングが100%合ってしまいます。 そこで指定された秒数だけキーの入力を受け付けるような方法を探しているのですが、そのようなものはあるのでしょうか? #include <stdio.h> #include <stdlib.h> #include <time.h> #include <conio.h> #include <windows.h> int main(void){ int key=0,ballichi=0,i,i2; system("cls");//画面の初期化 for(i=0;i<10;i++){ for(i2=0;i2<10;i2++){ if(ballichi==i2){printf(" o"); }else{printf(" ");} } printf("|壁"); if(i==9){ key = getch(); //キーから一文字入力 switch (key) { /* キー入力チェック */ case ' ': printf("スペースキーが押されました"); break; } } Sleep(500); ballichi++; system("cls"); } return 0; }

  • C言語プログラム

    2つの整数を入力させ、それらが等しい場合hitoshii、異なる場合にはhitoshikunaiと出力するプログラムを作りたいのですが、うまくいきません。間違っているところを教えてください。 #include<stdio.h> #include<conio.h> void main() { printf("整数を入力してください:"); int number1; scanf("%d",number1); printf("整数を入力してください:"); int number2; scanf("%d",number2); if(number1==number2) { printf("hitoshii"); } else { printf("hitoshikunai"); } getch(); }

  • C言語プログラミング

    台形の面積を求めるプログラムを作りたいのですが、最後のmensekiの出力の仕方がわかりません。printf以降のプログラムを教えてください。 #include<stdio.h> #include<conio.h> void main() { int number1,number2,number3,menseki; printf("上底を入力してください:"); scanf("%d",&number1); printf("下底を入力してください:"); scanf("%d",&number2); printf("高さを入力してください:"); scanf("%d",&number3); menseki=(number1+number2)*number3/2; printf( ここがわかりません getch(); }

  • c言語

    #include<stdio.h> #include<conio.h> void main() { int i=1,sum=0; char c=\'m\'; while(c!=\'e\')//eでない限りwhileループを実行する { sum=sum+i; printf(\"\\n1 kara %d madewo tasuto %d desu.\\n\",i,sum); i++; printf(\"nanikakeywo oshitekudasai.owaru tokiha \'e\'\\n\"); c=getch(); } printf(\"loopwo nukemashita\\n\"); getch(); } while(c!=\'e\')をwhile(c>0)にして実行したい場合はcharをintにかえて、scanfを使わなければならないのはわかりますが、どこを変えればよいか分かりません。ちなみに、while(c>0)に変えた場合に、正の数を入力した後に、「次の数を入力してください」という文を表示してからくりかえす方法をおしえてください。

  • C言語に詳しい方・得意な方!!!

    #include<stdio.h> #include<conio.h> void main() { int i=1,sum=0; char c='m'; while(c!='e') { sum=sum+i; printf("\n1 kara %d madewo tasuto %d desu.\n",i,sum); i++; printf("nanikakeywo oshitekudasai.owaru tokiha'e'\n"); c=getch(); } printf("loopwo nukemashita\n"); getch(); } C++はわかるのですが、Cは全くわけがわかりません!!上のプログラムまでは何とか実行してうまくできたのですが、下の問題はさっぱりわけがわかりません。教えてください? *1 うえのプログラムで使用しているgetch()の代わりにscanf()を使って整数値を入力させる。負の値を入力されたら終了。それ以外の数値が入力されたときは、「tsugino suuchiwo nyuryokuseyo」とメッセージをだして、また次の数値の入力を要求し、負の数が入力されるまで終わらないプログラム。 *2 *1のプログラムに、入力された正の数値をすべて加算していき、ループ終了後にその合計を出力するプログラム。 *3 *2のプログラムで、101以上の数値は加算しないようにするプログラム。 *4 *3のプログラムでいくつ数値が入力されたかをループ終了後に表示するプログラム。 *5 あるクラスのテストの点数(0から100点)の平均をだすプログラム。

  • linux上でgetchを使いたい

    linux上でgetch()を使おうと思い、<conio.h>をインクルードしたのですが、未定義のエラーが出てしまいます。どうやら、linuxでは、<conio.h>が無い?みたいなのですが、どうやったら、getch()を使用できるようになるのでしょうか??

  • C言語について。

    今、C言語に関する問題をやっているんですが、いまいちわかりません。 その問題というのは↓ ≪問題5 (繰り返し) 例題をもとに、次のような九九の表を出力するプログラムを作成しなさい。  1 2 3 4  5  6  7  8  9  2 4 6 8 10 12 14 16 18  ~(略)                                               ≫ という問題です。それで、その例題というのは↓ ≪例題4 (for文、do while文)  次のプログラムは、入力された整数を一辺とする正方形を出力するプログラムである。動作確認をしなさい。  4       (←入力)  ****  (←出力)  ****  ****  **** /* 正方形 */ #include <stdio.h> void main() {     int hen, i, j;     do{        printf("数字(2~9)を入力してください : ");        scanf("%d", &hen);        if( hen < 2 || hen > 9 )           printf("入力エラーです!\n");     }while( hen < 2 || hen > 9);     for( i = 1 ; i <= hen ; i++)     {         for( j = 1 ; j <= hen ; j++)           printf("*");         putchar('\n');    } }  ≫ ≪例題5 (for文、do while文) 次のプログラムは、入力された整数を一辺とする二等辺三角形を出力するプログラムである。動作確認しなさい。  4      (←入力)  *     (←出力)  **  ***  **** /* 二等辺三角形 */ #include <stdio.h> void main() {     int hen, i, j;     do{        printf("数字(2~9)を入力してください : ");        scanf("%d", &hen);        if( hen < 2 || hen > 9 )           printf("入力エラーです!\n");     }while( hen < 2 || hen > 9 );     for( i = 1 ; i <= hen ; i++ )     {            for( j = 1 ; j <= i ; j++ )              printf("*");          putchar('\n');     } }  ≫ 以上の二つが例題です。 わかりづらかったらすみませんm(_ _)m わかる方(問題5を)教えてくださるとありがたいです。

  • C言語で数当てゲーム

    私は最近5月からCのプログラミングを学び始めた中3なんですが じゃんけんゲームと丁半ゲームを今までに作りました で今回数当てゲームを作ってみたのですが何回作り直しても エラーが出ます(コンパイラのエラーではなくWindows?のエラーのようなもの) じゃんけんゲームなどと同じように作ったつもりなのですが・・・・ どうなっているのでしょうか? ソースは↓です #include <stdio.h> #include <time.h> #include <stdlib.h> #include <conio.h> int main() { int kazu,i,x; printf("数当てゲーム!!\n"); srand(time(NULL)); x=0; i=0; do { kazu=rand()%9+1; printf("数を入力してください(1~9)\n"); scanf("%d",i); if(i<10){ if(i==kazu) { printf("当たり!!\n続けるなら0やめるなら0以外を入力"); scanf("%d",x); } else {printf("残念・・・はずれ\n続けるなら0やめるなら0以外を入力"); scanf("%d",x);} } else {printf("入力ミスです\n続けるなら0やめるなら0以外を入力"); getch();} }while(x==0); return 0; } 一応コンパイラのエラーは出ていないのですが・・・ 初心者なのでわかりません。 どこが原因なのか詳しくおしえてください