• ベストアンサー

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% (2126/6286)
回答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% (2126/6286)
回答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

  • c言語 scanf

    下のソースを実行したらおかしなことになったんですがなんででしょうか?? #include<stdio.h> int main(void){ int i; char c[1000]; for(i=0;;i++){ printf("文字>>>>"); scanf("%c",&c[i]); printf("result = %c \n",c[i]); } } ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓実行↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 文字>>>>a result = a 文字>>>>result = 文字>>>>b result = b 文字>>>>result = 文字>>>>c result = c 文字>>>>result = 文字>>>>d result = d 文字>>>>result = 文字>>>>^C

  • scanf()関数の使い方について

    はじめまして。 質問があります。 まずは、以下のコードを見てください。 ---------------------------------------------------------------- #include<stdio.h> int main(void) { char c; int i; printf("0を入力すると終了します。\n"); while(1) { printf("文字を入力してください=>"); scanf("%c",&c); printf("入力した文字は %c です。\n",c); printf("数字を入力してください=>"); scanf("%d",&i); if(i==0) { break; } printf("入力した数字は %d です。\n",i); } return 0; } ---------------------------------------------------------------- 上のコードを実行すると、初回はscanf()はcharとintの両方とも 入力待ちになってくれるのですが、2回目以降はcharは入力待ちに なってくれません。これは、なぜなのでしょうか? ご教授お願いします。 現在VC++6.0を使用しております。

  • C言語 無効な例外ハンドラー ルーチン

    失礼します現在C言語を書籍にて勉強しておりますが、エラーが出てしまいすすめません正誤表などがなくこまっています現在のソースは #include <stdio.h> int str_char(const char str[], int c) { int i; for (i = 0; str[i] != '\0'; i++) if (str[i] == c) return (i); return(-1); } int main(void) { int no; char ch[10]; printf("英文字を入力してください"); scanf_s("%s", ch); no = str_char("ABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwxyz", ch[0]); if (no >= 0 && no <= 25) printf("それは英大文字の%dです\n", no + 1); else if (no >= 26 && no <= 51) printf("それは英小文字の%dです\n", no - 25); else printf("それは英文字ではありません\n"); return(0); } で、出てくるエラーメッセージは ハンドルされない例外が 0xFEFEFEFE (helloworld.exe) で発生しました: 0xC00001A5: 無効な例外ハンドラー ルーチンが検出されました。 (パラメーター: 0x00000003)。 です。 よろしくお願いします

  • scanf C言語

    現在取得したデータを多次元配列いれたいのですが、カンマまでの文字列を入れる方法がわかりません。例で言いますと jgasogasog,dklafh343,fdjalsjfd,kldjfas5 dfasfdas6ff ,fsadfa6sg,dgas6dsa,fsdafa もカンマまでの文字列array[0][0] = jgasogasog array[0][1] = dklafh34 といった形で入れていきたいです。 ご迷惑おかけしますが何卒よろしくお願いします。 途中まで作ったソースをのせます。 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include<string.h> #define piyo 2 #define hoge 1400 int main(void) { FILE *fp; char test[10][500]; int n = 0; if ((fp = fopen("testfile.csv", "r")) == NULL) { printf("\aファイルをオープンできません\n"); return(0); } int i, j; int k = 0; //ファイルfpの終端指示子をチェックします。 while (!feof(fp) && k < 500) { //%cは一文字出力をしてくれる使用データ型はchar型 //fscanf関数は書式指定をしてファイルから値を読み込み、バッファに格納します。 for (i = 0; i < 10; i++) { for (j = 0; j < 500; j++) { fscanf(fp, "%[^,],%d", &test[i][j]); k++; } } } for (i = 0; i < 10; i++) { for (j = 0; j < 500; j++) { printf("test[%d][%d]=%d\n", i,j,test[i][j]); } } fclose(fp); return(0); } 似たような質問をしてすいません。

  • C言語のエラー処理について

    下記のコードを作成したのですが、入力エラーの際に出力される表示が意図した input error の出力と違う形で表示されてしまい、修正方法が分からず、どなたか教えて頂けないでしょうか? ・『あ』等の整数以外の文字が入力された時 input errorinput errorinput error ・/0が入力された時 input error input error input error 「ソースコード」 #include <stdio.h> #include <time.h> #include <string.h> #include <stdlib.h> #define CALC (3) #define FROM_YEAR (1900) #define MAX_LINE (1000) #define MAX_ROW (1000) float calc_proc(int* n1, char op, int n2, float* ans) { switch (op) { case '+': *ans = (float)*n1 + n2; break; case '-': *ans = (float)*n1 - n2; break; case '*': *ans = (float)*n1 * n2; break; case '/': if (n2 == 0) { puts("input error"); return 1; } *ans = (float)(float)*n1 / n2; break; default: printf("input error"); return 1; break; } return 0; } int cmp_u(const void* a, const void* d) { return strcmp((char*)a, (char*)d); } int cmp_d(const void* a, const void* d) { return strcmp((char*)d, (char*)a); } int main() { int num1, num2; char op; float answer; int i; FILE* fp; char e[11]; char sin[MAX_LINE][MAX_ROW]; char ad[8]; fp = fopen("log.txt", "a+"); if (fp == NULL) { printf("ファイルオープン失敗\n"); return -1; } while (1) { scanf("%d%c%d", &num1, &op, &num2); calc_proc(&num1, op, num2, &answer); if (calc_proc(&num1, op, num2, &answer) != 0) { puts("input error"); return 1; } time_t t = time(NULL); struct tm* tm = localtime(&t); printf("%d/%02d/%02d ", tm->tm_year + FROM_YEAR, tm->tm_mon + 1, tm->tm_mday); printf("%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); printf("%d%c%d,%f\n", num1, op, num2, answer); fprintf(fp, "%d/%02d/%02d ", tm->tm_year + FROM_YEAR, tm->tm_mon + 1, tm->tm_mday); fprintf(fp, "%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); fprintf(fp, "%d%c%d,%f\n", num1, op, num2, answer); printf("計算を続けますか?"); scanf("%s", e); if (strcmp(e, "no") == 0) { break ; } } fclose(fp); fp = fopen("log.txt", "r"); if (fp == NULL) { printf("ファイルオープン失敗\n"); return -1; } int cnt = 0; for (i = 0;i < MAX_LINE;i = i + 1) { if (fgets(sin[i], sizeof(sin[0]), fp)) ++cnt; else break; } fclose(fp); printf("ASC or DESC: "); scanf("%s", ad); if (strcmp(ad, "ASC") == 0) { qsort(sin, cnt, sizeof(sin[0]), cmp_u); } else { qsort(sin, cnt, sizeof(sin[0]), cmp_d); } for (i = 0;i < cnt;i = i + 1) { printf("%s", sin[i]); } return 0; }

  • C言語のscanf文について

    C++言語の勉強中で、ビット演算子のところで質問です。 動作は、キーボードから16進データを入力して、そのデータの3,4ビット目を0にした時のデータを算出するというものです。 ここでProgram中の scanf 文にてエラーが出てしまいます。 ①%X(16進数)の型がintに対して、ope変数がcharとなっている。  ⇒ここの整合を取るためにはどういう方法がありますでしょうか? 以下がProgramです。 /*************************************************************/ /* プログラム:ビット演算子 */ /* 動作内容 :ビット演算子によりビット操作する */ /* 入力データの3,4ビット目を0にした値を算出する */ /**************************************************************/ #include<stdio.h> int main(void) { unsigned char ope; unsigned char ans; printf(" Hex-Data : "); scanf("%X", &ope); printf(" ope : 0x%02X\n", ope); ans = ope & 0xe7; /* 3,4ビット目:0 */ printf(" ope & 0xe7 = 0x%02x\n", ans); getchar(); getchar(); return(0); }

  • 私はC言語を習い始めて5日の初心者です。

    私はC言語を習い始めて5日の初心者です。 下記のプログラムが動かないので優しく教えてください。 どうかお願いします。 #include <stdio.h> int main() { int ans1,ans; int total printf("コンビニ行くときは(1:車で 2:自転車で 3:歩いて)行く\n"); scanf("%d",&ans1); printf("1:汗かいた記憶がない 2:たまに汗かく 3:よく汗をかく\n"); scanf("%d",&ans2); total=ans1+ans2; if (total<4) { printf("運動不足です\n"); }else { printf("良く運動していますね\n"); } return(0); }

  • C言語

    #include <stdio.h> int main(void) { int a=0,ans1,ans2,ans3,ans4; printf("整数を入力してください。\n"); scanf("%d",a); ans1 = a+7; ans2 = a*;8 ans3 = a%3; ans4 = a*(-1); printf("%d\n",ans1); printf("%d\n",ans2); printf("%d\n",ans3); if(a==15){ prntf("true\n",a); } else{ printf("false\n",a); } if(a != 8){ printf("true\n",a); } else{ printf("false\n",a); } if(a <= 3){ printf("true\n",a); } else{ printf("false\n",a); } printf("%d\n",ans4); if(a<2||7<a){ printf("true\n",a); } else{ printf("false\n",a); } return 0; } これを実行しようとしてもexeファイルになりません。 教えていただけませんか?

  • c言語についての質問です。

    #include<stdio.h> int main(void){ int a; printf("1文字たいぷしてください。\n"); scanf("%d",&a); if(a>=65 && a<=90){ printf("大文字です。\n"); } else if(a>=97 && a<=122){ printf("小文字です。\n"); } else{ printf("大文字でも小文字でもありません\n"); } return 0; } このプログラムは正しくなくて、 intをchar %dを%cにかえなければなりません。 なぜintはダメなんでしょうか? できれば丁寧に教えてください。 お願いします。

  • C言語の添削

    「C言語基礎課題1」 #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <tchar.h> #include <ctype.h>                                       #include <string.h> #define MAX 100 /*点数*/ int flag; double avg(double t[],int n); int str_check(char s[]);                                        int main() { int number; //人数 double score[MAX]; //点数 char temp[MAX]; char str[MAX]; //名前 double ans; //平均成績 int i=0; //カウンタ変数 //人数の決める printf("人数を入力して下さい。\n"); scanf("%d",&number); //名前の入力 for(i=0;i<number;i++) { printf("%d番様の名前を入力して下さい。\n",i+1); scanf("%s",&str[i]); } //点数の入力 for(i=0;i<number;i++) { printf("%d番様の点数を入力して下さい。\n",i+1); scanf("%s",&temp); str_check(temp); if(flag==1) { score[i]=atoi(temp); //点数入力で有効範囲をチェック if(score[i]<0 || score[i]>100) { printf("0-100点の範囲を入力して下さい。\n"); i--; } } if(flag==0) { printf("点数を数字で入力して下さい。\n"); i--; } } ans =avg(score,number); printf("\n=====入力内容一覧と成績平均値======\n"); for(i=0;i<number;i++) { printf("%d番の点数は%3.2lfです。\n",i+1,score[i]); } printf("平均点は%3.2lfです。\n",ans); printf("=====================================\n"); getch(); return 0; } /*avg関数の定義*/ double avg(double t[],int n) { int i; double sum; sum = 0.0; for(i=0;i<n;i++) { sum += t[i]; } return sum/n; } /*点数入力で文字か数字かチェック*/ int str_check(char s[]) { int i=0,n; //カウンタ変数 n=strlen(s); while(s!='\0') { if(s[i]>='0'&&s[i]<='9'||s[i]=='.') { i++; } else { break; } } if(i==n) { flag=1; } else { flag=0; } return flag; } [最初に組んだソースプログラム] #include<stdio.h> #include<stdio.h> #define NUM 3 /*点数*/ #define Name 3 /*人数*/ #include<conio.h> double avg(int t[]); struct stList{ char str[Name][100]; int score[NUM]; int i,j; }; int main(void) { int score[NUM]; //char str[Name]; char str[100]; int i,j; double ans; printf("名前を入力して下さい。\n",Name); for(i=0;i<Name;i++){ scanf("%s",&str[Name]); } // if(score[NUM]=0 || score[NUM]<=100) //{ // printf("点数を入力して下さい。\n",NUM); //} printf("点数を入力して下さい。\n",NUM); for(i=0;i<NUM;i++) { scanf("%d",&score[i]); if(score[i]<0 || score[i]>100) { printf("0-100点の範囲を入力して下さい。\n"); i--; } } for(j=0;j<NUM;j++){ printf("%d番目の人の点数は%dです。\n",j+1,score[j]); } ans =avg(score); printf("平均点は%3.2lfです。\n",ans); getch(); return 0; } /* avg関数の定義 */ double avg(int t[]) { int i; double sum; sum = 0.0; for(i=0;i<3;i++){ sum += t[i]; } return sum/Name; } 「一人分のデータを保持する構造体(文字列と整数の変数をメンバに持つ)を用意し、3人分の名前と成績 (最大値100、最小値0)を入力でき、入力が終了したら、入力内容一覧と成績の平均値を表示する プログラムを作成せよ。 ※考えうる限りの異常系処理の導入、関数化を行うこと。」 研修で以下の指摘を受けました。 (1)compare関数が使われていない。 (2)名前入れる変数が3つ不明 (3)カウンタ変数がi,j,s,tになっている理由は? (4)名前を入力しなかった時の処理 (5)点数を処理しなかった時の処理 (6)定数NUMで人数3を指定できるようにしているのにプログラムはそれを利用仕切れていない(名前入力が固定3人)ので無意味 (7)if(tmp=0 || tmp<=100)←これなんでしょうか? (8)平均点表示の少数点以下有効桁数はどうなっているのか? (9)点数入力で文字を入れたときの処理 (10)点数入力で有効範囲外の数字を入れた時の処理 ちなみに最大値、最小値はdefineして欲しいです。理由は(2)に読めば分かる (11)変数名が謎なのが多い 課題のキーワードのどこにも出て来ないですし言葉だから 後、添付ファイルを添付します。 最初のソースプログラム名「最初に組んだもの」修正したものが「C言語基礎課題1」と名付けています。 いづれのソースプログラムも構造体を用意出来てないように思うのですがいかかですか?