• ベストアンサー

C言語でscanfが認識されません

下記のプログラムですがまずc言語でlevel個の文字列を記憶させます。その後その文字列を0.5秒ほど表示して消し、コンピュータによって指示された番号の文字を当てることを複数回繰り返すプログラムです。 たとえば問題としてABCDEFがでて、その後3が指定されるとCと答えるようにしたいのです。 しかしループの奇数回目の時にscanfが認識がされていない(?)ようで答えを打ち込むことができず勝手に不正解になってしまい自分でプログラムを見直しても間違っている場所が分かりませんでした。 回答よろしくお願いします。 #include<stdio.h> #include<time.h> #include<stdlib.h> #define MAX_STAGE 10 #define MAX_LEVEL 10 #define MIN_LEVEL 3 int sleep(unsigned long x){ /*時間をxミリ秒潰す*/ clock_t c1 = clock(),c2; do{ if((c2=clock()) == (clock_t)-1) return(0); }while(1000.0 * (c2 -c1) / CLOCKS_PER_SEC < x); return(1); } int main(void){ int stage; int success = 0; int level; clock_t start,end; srand(time(NULL)); printf("いくつかの文字を記憶しましょう\n");/*レベルの設定*/ do{ printf("レベルを%d以上%d以下で入力してください\nLEVEL:",MIN_LEVEL,MAX_LEVEL); scanf("%d",&level); }while(level >MAX_LEVEL || level<MIN_LEVEL); start = clock(); /*本体スタート*/ for(stage = 0;stage < MAX_STAGE;stage++){ char *no; int i,j,k; char alpha[] = "abcdef"; int ans; char kotae; no = calloc(level+1,sizeof(char)); /*答えが含まれる文字列の領域を確保*/ for(i=0;i<level;i++) /*記憶する文字列の作成*/ no[i] = alpha[rand() % 6]; no[i] = '\0'; printf("%s",no); /*答えが含まれる文字列を表示*/ fflush(stdout); sleep(500); ans = rand() % level; /*答える文字を決定*/ printf("\r%d番目の文字を答えよ:",ans + 1); scanf("%c",&kotae); if(no[ans] != kotae) printf("不正解です\n"); else{ printf("正解です\n"); success++; } } end = clock(); printf("%d回中%d回成功しました。\n",MAX_STAGE,success); printf("%.1f秒でした。\n",(double)(end - start) / CLOCKS_PER_SEC); return(0); }

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

  • ベストアンサー
回答No.4

scanfにて%cを指定したとき、この現象は発生します。 最初のscanf("%c",&xx)で何か値を入力した後エンターキーを押しますよね。そのエンターキーの情報が入力バッファに残っているため、次のscanfにて、エンターキーの文字コードを読んでしまうのです。 対策としては、scanf の前に  fflash(stdin) を入れるのが確実です。 また、scanf(" %c",&xx)  というように%cの前にスペースを入れることでも解決できますが、あまりお勧めはしません。 「scanf」「バッファ」でぐぐれば、この件に対するサイトを見つけることができます。 scanf関数は非常に便利に見えて、色々使いにくいところがあります。 ある程度慣れてきたら、一行(あるいは1文字)ずつ読み込んで、自分のプログラム内で解析する方法も勉強したほうが良いと思います。

その他の回答 (6)

  • asuncion
  • ベストアンサー率33% (2127/6290)
回答No.7

fflush(stdin); について 「未定義」という話と、 「処理系に依存した動きをする」「環境によっては動作しない」という話は全く別です。 環境によらず未定義ですから、何が起きるかわかりません。 fflush(stdin); と「書いてはいけない」のです。

mohumoso
質問者

お礼

本に書いていないことなのでとても参考になります。 以後使わないように気をつけたいと思います。 回答ありがとうございました。

回答No.6

asuncionさんが指摘されたように fflush(stdin); だと環境によっては動作しない場合もあるようです。 自分の環境で動いたので勘違いしていました。 scanf("%c%c",&kotae,&dummy); は大丈夫です。

mohumoso
質問者

お礼

自分の所では動いたのですが環境次第ということはあまり使わないほうがよさそうですね。; 早速教えてもらった方法で作ってみます。 回答ありがとうございました。

回答No.5

先ほどfflash(stdin)とすれば確実と言いましたが、fflashはにstdinを指定した場合の処理は処理系に依存します。すみませんでした。 そこで、getchar() を使うのはいかがでしょうか?

mohumoso
質問者

お礼

cyacya2000さんが仰っているscanfによってバッファに\nが残る ということは初めて知ったことでした。 早速教えていただいた方法でプログラムしてみます。 検索するキーワードも教えていただいたので後ほどぐぐって調べさせてもらおうと思います。 回答ありがとうございました。

  • asuncion
  • ベストアンサー率33% (2127/6290)
回答No.3

>fflush(stdin); が正しいのではないでしょうか? 正しくありません。 標準入力に対するfflushは未定義の動作です。 なお、これは、質問者さんのプログラムで fflush(stdout); が必要かどうか、という話とは別です。

回答No.2

fflush(stdout); は出力(print)のバッファだと思います。 この場合は入力(scanf)のバッファを消したいので、 fflush(stdin); が正しいのではないでしょうか? もしくは scanf("%c",&kotae); 部分に scanf("%c%c",&kotae,&dummy); のような改行文字用のダミーを追加するのが有効だと思います。

参考URL:
http://www9.plala.or.jp/sgwr-t/lib/fflush.html
回答No.1

>fflush(stdout); の意味を理解していますか?

関連するQ&A