scanf()関数でのエラー対応方法を教えてください

このQ&Aのポイント
  • scanf()関数を使用して、文字ではなく数字を入力した場合にエラー(無限ループ)になる問題について、対応方法を教えてください。
  • 質問者が示したコードでは、入力される値が1から100の範囲内かどうかチェックし、範囲外の場合に再入力を促しています。
  • scanf()関数を使用したまま、再入力を促す方法をご教示いただけますでしょうか。
回答を見る
  • ベストアンサー

scanf()で、エラー対応

scanf()を使用して、入力で例えば「5462fa」数字ではなく文字を入力してしまった場合エラー(無限ループ)になりますが、 これをscanf()を使用したまま再入力を促すことが可能でしょうか?よろしくお願いします。 #include <stdio.h> int main(){   int a , kazu;   for(a=0;a<1;){     printf("値入力せよー>");       scanf ("%d", &kazu);         if( kazu >= 1 && kazu <=100 ){           a = a + 1 ;         }else{           printf("1から100で入力せよ\n");         }   }   printf ("kazu = %d", kazu);   return 0; }

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

  • ベストアンサー
  • galluda
  • ベストアンサー率35% (440/1242)
回答No.6

がるです。なるほど、独学でなさっているのですね。 scanfの経緯は…もう一つ不明ですが。前述したとおり、C言語の関数には「使ってはいけない」ものが色々と転がっております(苦笑 scanfは「意図しない文字列によって容易に暴走する」「バッファにデータを残しっぱなしにすることがある」など、問題児として筆頭に上げられてしまうような関数です。 あと、入力周りでNGなのがgetsという関数。これは、引数のバッファサイズ指定が無いために、容易にバッファオーバフロウを引き起こします。 多少手間でも、fgetsを用いるべきです。 こういった関数の見分け方としては ・異常な入力に対してどのような挙動をしめすか が第一点(scanfはここでNG)。 もう一つは ・引数で渡したポインタにデータを格納する場合、そのバッファサイズが引数として付随しているか が第二点目になります(getsはここでNG)。 大変だと思うのですが、頑張ってください。

shutoko-
質問者

お礼

回答ありがとうございます。 丁寧に解説していただき、助かりました。

その他の回答 (6)

noname#102413
noname#102413
回答No.7

do { }while() のようなdo文で意図する数値が入力されるまで「1から100で入力せよ」と警告を出すプログラムにすればいいのではないでしょうか?

shutoko-
質問者

お礼

回答ありがとうございました。

  • galluda
  • ベストアンサー率35% (440/1242)
回答No.5

がると申します。 ・scanfの類は一切使わない これに尽きます。 少なくとも、業務ないしそれに近しいところでscanf使ってたら問答無用で雷落とします。 っつか、何ゆえにあんな物騒な関数つかうのでしょう? # 「課題で使えと書いてある」とか言われると言い返せないのですが。…無論「そんな戯けた問題だす教師」には限りなく疑問です。 C言語にはscanf以外にも「絶対に使ってはいけない」関数が複数あります。 そういった部分について学ばれることを強くお勧めいたします。

shutoko-
質問者

お礼

ご指導ありがとうございます。 業務では使わないのですか、学校レベルの勉強用関数ってところですかね。 独学で勉強中なので、結構つらいです。また、こちらで質問させていただきます。ありがとうございました

  • mac_res
  • ベストアンサー率36% (568/1571)
回答No.4

scanf(3)は、対話入力に不適当な関数です。 想定外の入力に対する挙動が、人間にはとても理解しにくい仕様になっています。 sscanf(3)で書き換えたほうがよいです。 -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- #include <stdio.h> int main() { char buf[BUFSIZ], moji[BUFSIZ]; int n, kazu; while (1) { printf("値入力せよー> "); fgets(buf, BUFSIZ, stdin); n = sscanf(buf, "%d%s", &kazu, moji); if (kazu >= 1 && kazu <= 100 && n == 1) { break; } else { printf("1から100で入力せよ\n"); } } printf("kazu = %d\n", kazu); return 0; }

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

>printf("1から100で入力せよ\n"); の前後あたりに fflush(stdin); をいれてやるとか

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.2

まず第1に、scanfの返り値がvoidでなくintになってる理由を考えてみましょう。 第2に、scanfの返り値が「想定外」だった時の処理も含めてループの終了条件を考えましょう。 第3に、scanfは「書式に合わない入力があると、スキャンをその時点で中断し、ストリームに入力を残す」と言う特性があるので、ストリームに入力を残さない方法を考えましょう。 なお「正しい値が来るまで繰り返し」と言う処理は   for (;;) {     入力を促す画面出力     入力処理     if文で入力処理が行われたか判定 {       異常入力の警告出力       異常入力を除去するなどのエラー後処理       continue;     }     if文で入力値の範囲の判定 {       範囲外入力の警告出力       continue;     }     if文でその他の再入力の判定1 {       再入力の警告出力1       continue;     }     if文でその他の再入力の判定2 {       再入力の警告出力2       continue;     }     break; /* 正常ならループ脱出 */   } のように書きます。 こうすれば「再入力の判定」は幾つでも書く事が出来ます。 どの再入力判定にも引っ掛からなかった場合のみ正常に入力されたと考え、ループの最終位置で無条件にbreak文でループを抜けます。 また、質問文にあるような「終了フラグを判定するループ文」だと ・終了フラグを初期化する必要がある ・ループ終了の為の判定を行い、終了フラグを立てる ・ループ終了フラグを判定してループを繰り返すか決める と言うように、1つの条件に対してif文とfor文の2ヶ所で判定が行われ、二度手間を行っていて処理が無駄です。 こういう場合は ・終了フラグは使わない ・判定式の無い無限ループを使う ・ループ終了と判定したら、そのif文の中で(後処理をしてから)break文を使ってループを終らせる ・ループ再開(やり直し)が必要と判定したら、そのif文の中で(後処理をしてから)continue文を使ってループの最初に戻る と言う書き方をしましょう。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

どうしたいのかにもよりますけど, scanf("%*[^\n]"); とかでごまかせない? あと, scanf の返り値はチェックすること.

shutoko-
質問者

補足

回答ありがとうございます。 返り値のチェックはどのようにするのですか?

関連するQ&A

  • scanf関数について

    scanfで数字を入力し「CTRL+D」で入力終了となるプログラムを考えています. 調べてみると以下の様なプログラムでは入力終了となります. #include <stdio.h> int main(void) { int a[256]; int i = 0; while(1) { printf("Input%d = ", i); if ( scanf("%d", &a[i]) == EOF || i > 255) { break; } i++; } return 0; } しかし,次の様にすると「CTRL+D」では終了しません. #include <stdio.h> int main(void) { int a[256]; int i = 0; while(1) { printf("Input%d = ", i);   scanf("%d", &a[i]); <-----追加 if ( a[i] == EOF || i > 255) {   <-----変更 break; } i++; } return 0; } この場合は,環境がUNIXのため「-1」と入力すると終了します. 2種類の違いが分かりません. 教えてもらえないでしょうか?

  • C言語でscanf()が先に実行されるのはなぜですか?

    C言語でscanf()が先に実行されるのはなぜですか? #include <stdio.h> int main(void){ int intNum; printf("整数を入力してください:\n"); scanf("%d", &intNum); printf("入力値は:%d\n",intNum); return(0); }

  • scanf関数の戻り値について

    --------------------------------------- #include<stdio.h> int main(void) { int dt; while(scanf("%d",&dt)==1){ if(dt==0){ printf("0は入力しないでください\n"); puts(""); } else if(dt<0){ dt=-dt; printf("入力値の絶対値は「%d」です\n",dt); puts(""); } else{ printf("入力値の絶対値は「%d」です\n",dt); puts(""); } } return 0; } --------------------------------------- 以上のプログラムについて疑問があります。 scanf関数の戻り値が1の間、繰り返すというもので、入力の時に整数入力ですが、あえて実数である1.1を入れたとします。 scanfの戻り値は1で、dtには整数部の1だけ設定されていたので、これでもうまくいくのかと思ったのですが、次の入力はscanfの戻り値が0になっていて出来ませんでした。 何故0になっているのかわかりません。 入力バッファに何か残ってしまっているということなのでしょうか? 以上教えていただけると嬉しいです。

  • 長方形、円、三角形の計算するプログラムでエラーがでます

    タイトルの通りなんですがエラーがでます>< コンパイラはできたのですが、実行して二つ目の入力するとこで、入力したあと止まります。 どこがおかしいのでしょうか? #include <stdio.h> int sikaku(void); int en(void); int main(void) { char ch; int a,b; printf("円(A) 長方形(B) 三角形(C)\n"); printf("入力してください:"); ch = getche(); if(ch == 'C'){ printf("\n底辺を入力してください:"); scanf("%d ",a); printf("高さを入力してください:\n"); scanf("%d",b); printf("%dです",a * b); } else if(ch == 'B') sikaku(); else if(ch == 'A') en(); return 0; } int en(void) { int a; float f; printf("\n半径を入力してください:"); scanf("%d",a); printf("円周率を入力してください:"); scanf("%f",f); printf("%fです",a * a * f); return 0; } int sikaku(void) { int a,b; printf("\n縦を入力してください:"); scanf("%d",a); printf("横を入力してくさい:\n"); scanf("%d",b); printf("dです",a * b); return 0; }

  • 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を使用しております。

  • scanfの後のfgetsについて

    #include <stdio.h> int main(void) { char name[10]; int no; printf("ナンバーを入力してください: "); scanf("%d",&no); /* 35を入力 */ printf("文字列を入力してください: "); fgets(name,10,stdin); /*入力できない*/ return 0; } この例文だと、fgets関数が改行コードを読み取って、終了してしまい文字列入力が出来ないみたいなんですが、scanfの後にfgetsを使うような(scanfとfgetsの間にscanfの残した?改行コードを取り除く方法)処理はどのような方法があるのでしょうか? 試しにfgets文を2度書いたら思っていた動作をしてくれたのですが、はたしてfgets文を2度書くというような事をしていいものなのでしょうか?見た目もなんだか変な感じですし。。↓ #include <stdio.h> int main(void) { char name[10]; int no; printf("ナンバーを入力してください: "); scanf("%d",&no); /* 35を入力 */ printf("文字列を入力してください: "); fgets(name,10,stdin); fgets(name,10,stdin);  /*入力できる*/ return 0; }

  • 整数と文字を同時に扱う

    数字を入力して,正ならplusを負ならminusを、 0ならzeroを表示し、ピリオド「.」が入力されたとき プログラムを終了するプログラムを作らなければならないのですが、 整数と文字を同時に扱うのって可能ですか?? 一応、 #include<stdio.h> int main(void){ int a; while (a!='.'){ printf("変数aに数字を入力してください\n"); printf("a="); scanf("%d",&a); if(a>0){ printf("%d is plus\n",a); }else if(a==0){ printf("%d is zero\n",a); }else{ printf("%d is minus\n",a); } } return(0); } で作ったのですが、数字以外を入力すると無限ループします。

  • scanfに文字が入力されたときにエラー表示させる

    こんばんは.C言語勉強中です. 以下にsizeofを用いて各データタイプのサイズを表示させるプログラムを作りました.プログラム全文は下に貼付けました.これは,1-7までのいずれかの数字を入力すると,それに対応したサイズが表示されます.1-7以外の数字が入力されると,Type 1 - 7, please,と表示され,再び数字を入力出来ます.このプログラムは数字を入力している間はうまく機能していると思います. ただ,文字を入力すると無限ループに陥ってしまいます.僕は以下の scanf("%d",&typed); で10進数で読み込んで, if(typed<1 || typed >7) とすれば,文字も含めて全ての入力に対して排除できるかと思ったのですが,これではダメなようです. こういう場合,どうやって文字の入力に対するエラーを表示させるのが一般的なのでしょうか? 素人質問ですみません.よろしくお願いします. #include <stdio.h> #include <stdint.h> #include <Windows.h> int8_t main() { int typed; while(1) { while(1) { printf("Type the data type you wanna know the size of\n"); printf("char 1, short 2, int 3, long 4, long long 5, float 6, double 7: "); scanf("%d",&typed); printf("What you typed is %d\n",typed); if(typed<1 || typed >7) { printf("Type 1 - 7, please\n"); Sleep(1000); continue; } else { break; } } printf("Data size is "); switch(typed){ case 1: printf("%d\n",sizeof(char)); break; case 2: printf("%d\n",sizeof(short)); break; case 3: printf("%d\n",sizeof(int)); break; case 4: printf("%d\n",sizeof(long int)); break; case 5: printf("%d\n",sizeof(long long)); break; case 6: printf("%d\n",sizeof(float)); break; case 7: printf("%d\n",sizeof(double)); break; default: printf("Unexpected Value!\n"); break; } Sleep(2000); } return(0); }

  • scanf文がうまくいかないのですが・・・

    下のようなプログラムを実行するとうまくいかないのですが、何故なのでしょう。 どうかお教えください。 #include<stdio.h> int main(void) { int i; char n; for(i = 0; i < 10; i++) { printf("nを入力してください>>>"); scanf("%c",&n); printf("%c\n",n); } return 0; }

  • 簡単なscanf文が、わかりません。

    #include <stdio.h> int main(void) { int data; scanf("%d",&data); /*入力部分*/ printf("%d\n",data); return 0; } 参考書には、キーで入力、enterキー押すと、はじめて文字が画面に表示されるとなってましたが。 実際は、enter押さずに、キーボードでキー入力した時点で文字が表示されますが、 どこが間違っているんでしょうか? コンパイラは、 Borland C++ Compiler です。 お願いします。