
Cプログラム初心者です。
例えば、floatの名前をlengthとして、scanfでユーザーに入力させるとします。その時ユーザが間違えて数字ではなく文字を入力した場合、その後のprintfの内容がループしてしまいます。どうしたら、ユーザーが間違えて入力したときに、入力ミスを伝え、もう一回入力をしてもらうことができるプログラムが作れるでしょうか。
以下がエラー処理をする前のプログラムの一部なのですが、、、。
float length;
printf("Enter length of the room in metre and press enter.\n");
scanf("%f", &length);
while (length>300)
{
printf("This programme only caluculate length under 300m.\n");
printf("Please re-enter the length in metre and press enter.\n");
scanf("%f", &length);
}/*End of while (length)*/
No.4ベストアンサー
- 回答日時:
どのレベルまでのエラーチェックが必要かが不明ですが…
私ならfgets()->strtod()という手順を踏みます。
・scanf()は入力を消費しない
scanf()はエラーを返したときに入力内容を消去しません。
結果、いとも簡単に無限ループに陥ります。
エラー派生時には入力バッファのフラッシュをする必要があります。
・gets()は入力文字数を制限できない
gets()は文字列入力関数ですが、入力文字数を制限する機能がありません。
結果、想定しない文字数を入力される可能性があります。
これは、scanf()で%sを使ったときも同じです。
(sanf()の場合は回避法アリ)
・atof()は変換不能文字を報告しない
atof()はエラーを報告する手段をもちません。
入力 出力
0.0 0.0
abc 0,0
1.0 1.0
1.b 1.0
abcや1.bという数値はありません。これらはエラーのはずですが、atof()にエラー報告の機能が無いために「変換可能だった文字だけを変換した結果(1.b→1.0)または、0.0(abc→0.0)」が返されます。
char *fgets()は入力文字の最大数を制限できます。
fgets(char *入力文字列用の配列,int 入力可能文字数+1,stdin);
入力可能文字数+1なので単純に配列のよう素数を指定すればオッケーです。
(入力文字の最後に'\0'が付加されるため「入力可能文字数+1」を指定します)
キーボード入力を受け取る場合最後の引数をstdinとします。
strtod()は変換不能文字を発見したときに、その文字のアドレスを報告します。
結果、1.bやabcなどという「数字として認識不能な並び」を発見できます。
double strtod(char *変換する文字列,char **変換不能文字のアドレス);
キーボード入力の場合の例)
double len ;
char str[10], *trm ;
if (fgets(str, sizeof(str), stdin) == NULL){
/* 9文字以内の文字列をキーボードから入力 */
/* fgets()がNULLを返したときは"入力無し”かエラー */
エラー処理
}
len = strtod(str, &trm) ; /* 文字列→浮動小数点変換 */
if (trm != NULL && (*trm != '\0' || *trm != '\n')) {
/* 変換不能文字が'\0'か改行なら入力は数値、それ以外なら数値以外の入力 */
printf("数値以外が入力された:%s", str) ;
エラー処理
}
/* lenに入力を浮動小数点変換したものが設定されている */
アドバイスありがとうございます。大変複雑な内容をわかりやすく、砕いて説明していただいて感謝しております。まだ始めたばかりですが、ひとつ、ひとつの関数が持つ利点、マイナス点を理解しながら勉強を続けたいと思います。
ありがとうございました。
No.3
- 回答日時:
scanf系の関数は想定外の入力に弱いので、
こういうエラー処理を考えるならまず使わないですね。
getsとatofがいいでしょう。
scanfの戻り値でもある程度はわかりますが、
多少厳密さに欠けます。
例えば,"123ABC"と入力した場合、エラーとするか、
123が入力されたとするかという違いです。
あとgetsよりもfgetsの方がバッファオーバーフローがおきなくて本当はいいのですが・・・
早速アドバイス頂きありがとうございます。初心者だと、どうしてもscanfを最初に習うので、数字=scanfなんて思ってしまいがちなんですが、実際には文字入力というのが入力エラーを抑える働きとなるんですね。初心者だと考え付かない、発想です。勉強になりました。ありがとうございました。
No.2
- 回答日時:
scanf()の戻り値を使えば良いんでは?
scanf()系の関数は代入に成功した変数の
数を返します。ですから、
float length;
do{
printf("Enter length of the room in metre (<= 300m) and press enter.\n");
} while( scanf("%f", &length) < 1 || length > 300.0f || length < 0.0f);
面倒臭がりなのでwhileの中の条件式で全部判定させましたが、
見易いように分けた方がいいかも知れません。
No.1
- 回答日時:
scanf()は演習用にはよいですが、アプリには使いません。
scanf()は最悪の関数ですから。
文字列として入力させ、入力された文字列が正しいか、チェックして、それを実数に変換します。
文字列入力:gets()
チェックには:isdigita()
などを使うようです。
早速アドバイス頂きありがとうございます。scanfは使わないほうがいいんですね。数字が入力できるから、、という単純な理由でscanfを使ってたんですが。エラーの時に大きな落とし穴と変わるんですね。貴重なアドバイスありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 英語 Length stoppers are provided in the kit and their 4 2022/04/22 00:51
- 英語 An increase in implant length (7.5 mm) did not exh 1 2022/07/20 13:43
- 英語 No significant differences between the studied gro 1 2022/10/26 01:26
- 英語 No significant differences between the studied gro 5 2022/10/25 22:53
- C言語・C++・C# C言語(構造体) 3 2022/07/05 20:08
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# 至急教えてください!プログラミングの問題です。 割られる整数と割る整数を受け取って、商と余りを出力す 3 2022/07/05 10:23
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# C言語 3 2022/10/04 15:07
- C言語・C++・C# C言語 プログラミング 4 2022/05/22 11:53
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・「それ、メッセージ花火でわざわざ伝えること?」
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・【お題】甲子園での思い出の残し方
- ・【お題】動物のキャッチフレーズ
- ・人生で一番思い出に残ってる靴
- ・これ何て呼びますか Part2
- ・スタッフと宿泊客が全員斜め上を行くホテルのレビュー
- ・あなたが好きな本屋さんを教えてください
- ・かっこよく答えてください!!
- ・一回も披露したことのない豆知識
- ・ショボ短歌会
- ・いちばん失敗した人決定戦
- ・性格悪い人が優勝
- ・最速怪談選手権
- ・限定しりとり
- ・性格いい人が優勝
- ・これ何て呼びますか
- ・チョコミントアイス
- ・単二電池
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・ゴリラ向け動画サイト「ウホウホ動画」にありがちなこと
- ・泣きながら食べたご飯の思い出
- ・一番好きなみそ汁の具材は?
- ・人生で一番お金がなかったとき
- ・カラオケの鉄板ソング
- ・自分用のお土産
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
UWSCで変数をキー入力
-
Excel VBAで、Application.Inpu...
-
Eclipseコンソール表示を、リセ...
-
EDITコントロールで入力できる...
-
数字以外が入力されたらエラー...
-
入力候補を表示させるには・・・?
-
プログラミング初心者です。 Py...
-
コンボボックスで日本語入力を...
-
scanf("%s", buf);でスペースを...
-
配列にデータを10個読み込み、...
-
IF文で戻ることはできますか?...
-
batプログラム上で文字列を入力...
-
*をユーザーが入力した数字の数...
-
C言語でgetchar();が上手く使え...
-
Excel VBA Interior.Color
-
至急教えてください。プログラ...
-
漢字のソートについて
-
3秒後に文字を消すには?
-
VB.NETで16進数+16進数や16進...
-
2進数の1の数を数える問題
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
プログラミング初心者です。 Py...
-
正負を反転させて出力するプロ...
-
Excel VBAで、Application.Inpu...
-
*をユーザーが入力した数字の数...
-
数字以外が入力されたらエラー...
-
java初心者です。入力されたの...
-
EDITコントロールで入力できる...
-
コマンドプロンプトからのEOFの...
-
小数か整数かを判定する方法
-
Eclipseコンソール表示を、リセ...
-
Linuxプログラミングで、キーボ...
-
ワードで文字を入力する時の変...
-
batプログラム上で文字列を入力...
-
入力候補を表示させるには・・・?
-
"scanf"でエンターで改行させな...
-
VB.NETで16進数+16進数や16進...
-
最大公約数と最小公倍数を求め...
-
UWSCで変数をキー入力
-
漢字のソートについて
-
cout関数を使っているのですが...
おすすめ情報