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を見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
数字以外が入力されたらエラー...
-
*をユーザーが入力した数字の数...
-
Eclipseコンソール表示を、リセ...
-
プログラミング初心者です。 Py...
-
正負を反転させて出力するプロ...
-
C言語について
-
プログラミングC言語について
-
cout関数を使っているのですが...
-
C言語でつるかめ算をするにはど...
-
switch文 defaultについて
-
至急教えてください!プログラ...
-
java初心者です。入力されたの...
-
Userformの入力順序をタブオー...
-
WindowsでEOF
-
C言語
-
MinGWのC言語でCTRL+Zで処理が...
-
C言語scanf_sで何故か2回入力に...
-
C++のcinの動作
-
プログラムの進行が一時ストッ...
-
漢字のソートについて
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
*をユーザーが入力した数字の数...
-
正負を反転させて出力するプロ...
-
数字以外が入力されたらエラー...
-
プログラミング初心者です。 Py...
-
double型が正常に認識されてい...
-
java初心者です。入力されたの...
-
Eclipseコンソール表示を、リセ...
-
scanfが2回使えない・・・?;
-
C言語scanf_sで何故か2回入力に...
-
if文の条件にscanf関数を使うと…?
-
プログラミングの問題です 「金...
-
Linuxで入力待ちなしkeyread関...
-
ワードで文字を入力する時の変...
-
cout関数を使っているのですが...
-
batプログラム上で文字列を入力...
-
Userformの入力順序をタブオー...
-
scanf が無視されます
-
C言語 逆ピラミッドの作り方
-
gets_sがうまく動かない
-
Excel VBAで、Application.Inpu...
おすすめ情報