--------------------------------------------------------
#include<stdio.h>
int main(void)
{
double sum=0.0;
double dt,x
int ret,n;
char ss[80];
ret=scanf("%lf",&dt);
while(1){
if(ret==1){
x=sum;
sum+=dt;
n=getchar();
if(n=='\n'){
printf("入力された数値=%f\n");
puts("");
sum=sum;
}
else{
printf("正しく入力してください\n");
puts("");
gets(ss);
sum=x;
dt=0.0;
}
}
else if(ret!=0){
gets(ss);
dt=0.0;
printf("正しく入力してください\n");
puts("");
}
else if(ret==EOF){
break;
}
ret=scanf("%lf",&dt);
}
printf("合計=%f\n",sum2);
return 0;
}
--------------------------------------------------------
前回、「scanfの入力をgets関数で読み捨てることについて」というタイトルで数値連続加算のプログラムを作り、皆様からいろいろとアドバイスを受けた者です。
いろいろとプログラムを改良し、「Ctrl+Z」の入力でプログラムを終了しようとし、後、前のプログラムでは「10abc」などと打ち込んでも「10」は読み込んでしまうので、「10abc」などと打ち込んだ時点で、エラー表示をさせるようにしました。
ここで疑問なのですが、例えば、
-------
enter
enter
abc
-------
と入力した場合、改行文字が配列ssに格納され、いろいろと複雑になってしまうのかと思ったのですが、ssにはしっかり「abc」だけが格納されていました。
以上のプログラムに不備がないかも含めて、何故そうなるのか教えていただけると嬉しいです。
No.2ベストアンサー
- 回答日時:
>ここで疑問なのですが、例えば、
「scanfは、先頭にある空白や改行を読み飛ばしてから、指定の数値を読もうとする」ので
enter
enter
で入れられた改行2つは、scanfが読み飛ばします。
で、scanfが最初の改行を読み飛ばした後で「a」を見付けるので、その「a」は「まだ読んで無い事にして」から、0を返します。
入力バッファには「abc」+「改行」が残っています。
次に「getsは改行まで読み込んで、読み込んだ改行を文字列の終端記号の'\0'に書き替えてから戻って来る」ので「abc\n」を読み込み、\nを\0に書き替えて「abc\0」がssの中に入ります。
ここで問題になるのが「scanfは、先頭にある空白や改行を読み飛ばしてから、指定の数値を読もうとする」と言う部分。
なのでscanfを使う限り「enterだけの入力」で「正しく入力してください」とエラー表示する事は出来ません。
その部分を修正したのが、以下のプログラムです。
#include <stdio.h>
int main(void)
{
char ss[256];
double sum=0.0,dt;
int ret;
char c;
char *p;
for (;;) {
// scanfは使わないで、とにかく1行全部をssに入力する
p = gets(ss);
// Ctrl+Zが入力されたらgetsはNULLを返すので終了する
if (p == NULL) break;
// 入力したssから、数値と、数値の直後の文字を取り出す。
ret = sscanf(ss,"%lf%c",&dt,&c);
// 改行のみの入力なら「ssが空っぽ」なのでretはEOFになる。
// 数値だけの入力なら、後ろの%cが入力されないのでretは1になる。
// 数値以外の入力なら、retは0になる。
// 数値の後ろに何か余計な物があったらretは2になる。
// 数値だけ入力したかどうか調べる。
if (ret == 1) {
// 数値だけ入力した。
printf("入力された数値=%f\n",dt);
// 数値だけ正しく入力したので、sumにdtを足す。
sum += dt;
} else {
// 何も入力せずにEnterだけ押したか、数値以外を入力したか、余計な物を入力した。
// エラー表示する。
printf("正しく入力してください\n");
}
}
printf("合計=%f\n",sum);
return 0;
}
で、これでOKかと言うと、そうじゃない。
この「修正版プログラム」で、以下のように入力してみよう。
1a
1b
1c
1d
1e
1f
Ctrl+Z
結果は
1a
正しく入力してください
1b
正しく入力してください
1c
正しく入力してください
1d
正しく入力してください
1e
入力された数値=1.000000
1f
正しく入力してください
^Z
合計=1.000000
となる。なぜか「1e」だけ「1」として入力され「正しい入力」と判断されてる。
実は、scanfの%lfは「仮数部+e+指数部」と言う入力を許しているのだ。
例えば「120」は「1.2×10の2乗」なので、入力時に「1.2e2」と入力しても良い。
上記の「1e」は「1×10の0乗で、eの後ろの0が省略されてて、1e0と入力した」と認識されてしまう。
「10の0乗」は「1」なので「1×10の0乗」は「1×1」なので、結局は「1」になってしまう。
こういう「意図しない入力を除外したい場合」は「scanfする前に、自前で、入力した文字列が正当か調べる必要」がある。
ご回答ありがとうございます。
>改行2つは、scanfが読み飛ばします。
>入力バッファには「abc」+「改行」が残っています。
>「getsは改行まで読み込んで、読み込んだ改行を文字列の終端記号の'\0'
>に書き替えてから戻って来る」ので「abc\n」を読み込み、\nを\0に書き
>替えて「abc\0」がssの中に入ります。
上記の内容、scanfは改行を読み飛ばすという事やgetsの仕様が理解できました!
修正していただいたプログラムも、ステップオーバー実行して理解できました! 簡潔なプログラムになって、とてもわかりやすっかたです。
>scanfの%lfは「仮数部+e+指数部」と言う入力を許しているのだ。
>「意図しない入力を除外したい場合」は「scanfする前に、自前で、入力
>した文字列が正当か調べる必要」がある。
以上のご回答にあるような入力を回避出来るようなプログラム作成、努力してみます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
正負を反転させて出力するプロ...
-
Eclipseコンソール表示を、リセ...
-
C++ scanfで止まらない
-
Linuxで入力待ちなしkeyread関...
-
WindowsでEOF
-
C言語のプログラム作成の課題...
-
プログラミング初心者です。 Py...
-
java初心者です。入力されたの...
-
VisualStudio2019のコードアナ...
-
コマンドプロンプトからのEOFの...
-
C言語・YesNo入力のループで解...
-
Linuxプログラミングで、キーボ...
-
コマンドラインから引数を渡し...
-
入力候補を表示させるには・・・?
-
至急教えてください。プログラ...
-
scanfについて
-
ヒントをください!
-
scanf関数について
-
小数か整数かを判定する方法
-
C言語の勉強しています。すみま...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
正負を反転させて出力するプロ...
-
プログラミング初心者です。 Py...
-
数字以外が入力されたらエラー...
-
Eclipseコンソール表示を、リセ...
-
Excel VBAで、Application.Inpu...
-
*をユーザーが入力した数字の数...
-
java初心者です。入力されたの...
-
Linuxで入力待ちなしkeyread関...
-
batプログラム上で文字列を入力...
-
WindowsでEOF
-
Userformの入力順序をタブオー...
-
コマンドプロンプトからのEOFの...
-
EDITコントロールで入力できる...
-
VisualStudio2019のコードアナ...
-
電卓の小数点
-
Eclipseでコマンドラインを入力...
-
小数か整数かを判定する方法
-
cout関数を使っているのですが...
-
UWSCで変数をキー入力
-
ワードで文字を入力する時の変...
おすすめ情報