アプリ版:「スタンプのみでお礼する」機能のリリースについて

下記のプログラムですがまず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);
}

A 回答 (7件)

scanfにて%cを指定したとき、この現象は発生します。


最初のscanf("%c",&xx)で何か値を入力した後エンターキーを押しますよね。そのエンターキーの情報が入力バッファに残っているため、次のscanfにて、エンターキーの文字コードを読んでしまうのです。
対策としては、scanf の前に  fflash(stdin) を入れるのが確実です。
また、scanf(" %c",&xx)  というように%cの前にスペースを入れることでも解決できますが、あまりお勧めはしません。
「scanf」「バッファ」でぐぐれば、この件に対するサイトを見つけることができます。

scanf関数は非常に便利に見えて、色々使いにくいところがあります。
ある程度慣れてきたら、一行(あるいは1文字)ずつ読み込んで、自分のプログラム内で解析する方法も勉強したほうが良いと思います。
    • good
    • 0

fflush(stdin); について



「未定義」という話と、
「処理系に依存した動きをする」「環境によっては動作しない」という話は全く別です。

環境によらず未定義ですから、何が起きるかわかりません。
fflush(stdin);
と「書いてはいけない」のです。
    • good
    • 0
この回答へのお礼

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

お礼日時:2009/11/03 00:18

asuncionさんが指摘されたように fflush(stdin); だと環境によっては動作しない場合もあるようです。



自分の環境で動いたので勘違いしていました。
scanf("%c%c",&kotae,&dummy); は大丈夫です。
    • good
    • 0
この回答へのお礼

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

お礼日時:2009/11/03 00:04

先ほどfflash(stdin)とすれば確実と言いましたが、fflashはにstdinを指定した場合の処理は処理系に依存します。

すみませんでした。
そこで、getchar() を使うのはいかがでしょうか?
    • good
    • 0
この回答へのお礼

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

お礼日時:2009/11/03 00:00

>fflush(stdin); が正しいのではないでしょうか?



正しくありません。
標準入力に対するfflushは未定義の動作です。

なお、これは、質問者さんのプログラムで
fflush(stdout);
が必要かどうか、という話とは別です。
    • good
    • 0

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
    • good
    • 0

>fflush(stdout);


の意味を理解していますか?
    • good
    • 0

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


このQ&Aを見た人がよく見るQ&A