
C言語初心者です。よろしくお願いします。
早速質問なのですが、while文を使ったscanf()関数による数値連続入力で、
◎1----------------------------------------------
#include<stdio.h>
int main(void)
{
double dt,sum=0.0;
while(scanf("%lf",&dt) !=EOF){
sum=sum+dt;
}
printf("合計=%f\n",sum);
return 0;
}
----------------------------------------------
◎1のようにすれば、Ctrl+ZでEOFが返されたら終了とわかるのですが、今度は「0」が入力されたら処理を終了するというプログラムで、
◎2----------------------------------------------
#include<stdio.h>
int main(void)
{
double dt,sum=0.0;
while(scanf("%lf",&dt) !=0.0){
sum=sum+dt;
}
printf("合計=%f\n",sum);
return 0;
}
----------------------------------------------
◎2のようにすると「0」が入力されても、終了せず、以下に示す◎3のように、しないと終了出来ません。
◎3----------------------------------------------
#include<stdio.h>
int main(void)
{
double dt,sum=0.0;
scanf("%lf",&dt);
while(dt!=0.0){
sum=sum+dt;
scanf("%lf",&dt);
}
printf("合計=%f\n",sum);
return 0;
}
----------------------------------------------
◎2で何故、◎1のように出来ず、◎3のようなscanf()を1回目、2回目と判定を入れなければならないか教えて下さい。
No.4ベストアンサー
- 回答日時:
◎1の書き方では、無限ループする場合があります。
scanfは「正しく変換を行った回数、または、入力が尽きた場合にEOF」を返します。
例えば
1.2[Enter]
3.5[Enter]
kkk[Enter]
と入力すると、kkkを入力してEnterを押した瞬間、無限ループします。
scanfは「kkkは%lfに合わないので、0個を変換しました」と0を返し、入力バッファにkkkを残したままにします。
0はEOFとは違うので、そのままループを繰り返します。
入力バッファにはkkkが残ったまま消費されないので、次の回も、次の次の回も、scanfは永久に0を返し続けます。
そして、プログラムを止める事が出来なくなります。
◎2の書き方でも、やはり無限ループする場合があります。
今度は「kkk」とか「@@@」とか「abcdefgh」とか、実数に変換できない物を入力する事で止まります。
しかし「Ctrl+Z」などを打ち込み「入力が尽きた状態」にすると、scanfはEOFを返します。
0はEOFとは違うので、そのままループを繰り返します。
キーボード入力は「入力が尽きた状態」のままなので、次の回も、次の次の回も、scanfは永久にEOFを返し続けます。
そして、プログラムを止める事が出来なくなります。
◎3の書き方でも、やはり無限ループする場合があります。
今度は「0」を入力する事で止まります。
しかし「Ctrl+Z」などを打ち込み「入力が尽きた状態」にすると、scanfはEOFを返します。
この時、dtはscanfによって値を変更されませんから、dtは前回入力したままの「0以外の値」になっています。
dtが0以外では、ループを終了しません。そのままループを繰り返します。
キーボード入力は「入力が尽きた状態」のままなので、次の回も、次の次の回も、scanfは永久にEOFを返し続けます。
そして、プログラムを止める事が出来なくなります。
そう言った訳で、質問者さんの書いた3つのプログラムはどれも「無限ループする、大変に危険なプログラム」です。
下記のようなプログラムが「無限ループしない、安全なプログラム」です。
#include<stdio.h>
int main(void)
{
double dt,sum=0.0;
while(scanf("%lf",&dt) != 1){ // EOFや0を返したらやめる
if (dt == 0.0) // 正しい入力でも、入力が「0」ならやめる
sum=sum+dt;
}
printf("合計=%f\n",sum);
return 0;
}
もちろん、scanfは1個しかありません。
どれも無限ループが発生してしまうとは、まだ勉強が足りないみたいです。。安全なプログラムまで教えていただいて、ありがとうございます。
返り値などその辺りの知識を身に付け、chie65535さんの回答を参考に完璧に理解していこうと思います。
No.5
- 回答日時:
お礼を頂いてからミスに気付きました。
if (dt == 0.0) // 正しい入力でも、入力が「0」ならやめる
は
if (dt == 0.0) break;// 正しい入力でも、入力が「0」ならやめる
のミスです。「ループを抜けるbreak文」が抜けてました。
No.3
- 回答日時:
◎1 は、Ctrl+Z という特殊な操作によって、scanf が異常終了したため返却値に EOF が戻された
から、式が成立してます。
一方、◎2は、0 を入力した場合の scanf は正常に終了したため、&dtに 0 が入り、戻り値には
入力要素の個数が返却されているはずです。
よって、返却値が 0 と一致しないため、終了しません。
返却値が一致しないという考えは理解できました。
戻り値などの関数はこれから学んでいくので、その後、yuu_yuuさんの回答をもう一度見てみれば、完全に理解が出来ると思います。
もっと関数について理解し努力していきます。
ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
プロが教える店舗&オフィスのセキュリティ対策術
中・小規模の店舗やオフィスのセキュリティセキュリティ対策について、プロにどう対策すべきか 何を注意すべきかを教えていただきました!
-
C言語 数値の連続入力について
C言語・C++・C#
-
Enterキーを押されたら次の処理に移るという事をしたい。
C言語・C++・C#
-
特定の文字が入力されるまで・・・
C言語・C++・C#
-
4
C言語 配列の長さの上限
C言語・C++・C#
-
5
C言語・標準入力でquitを入力で終わるプログラム
C言語・C++・C#
-
6
CTRL+Dでループを抜けるには
C言語・C++・C#
-
7
終了条件Ctrl+zについて,結果表示ついて(C言語)
C言語・C++・C#
-
8
10個出力で改行したいのですが・・・
C言語・C++・C#
-
9
getcの改行判定
C言語・C++・C#
-
10
関数から配列を返すには?
C言語・C++・C#
-
11
MinGWのC言語でCTRL+Zで処理が終了しない
C言語・C++・C#
-
12
サイト名ってなんですか?
その他(暮らし・生活・行事)
-
13
C言語のプログラムの質問です
工学
-
14
C言語の入力した文字を反転させるプログラミングの仕方が分かりません。
Ruby
-
15
C言語において、 配列要素をひとつずつ前にずらすコード
C言語・C++・C#
-
16
C言語で、メモリを解放しないで終わるプログラム
C言語・C++・C#
-
17
if文の条件にscanf関数を使うと…?
C言語・C++・C#
-
18
C言語 exitの使い方
C言語・C++・C#
-
19
scanfが2回使えない・・・?;
C言語・C++・C#
-
20
for文
C言語・C++・C#
関連するカテゴリからQ&Aを探す
このQ&Aを見た人がよく見るQ&A
人気Q&Aランキング
-
4
漢字のソートについて
-
5
4桁の数字以外を入力したらエラ...
-
6
【再々投稿】VBAのプログラムで...
-
7
C言語 逆ピラミッドの作り方
-
8
C言語scanf_sで何故か2回入力に...
-
9
コマンドプロンプトからのEOFの...
-
10
意味のよく分らないソース
-
11
Userformの入力順序をタブオー...
-
12
C言語の非標準コンソール関数ge...
-
13
正負を反転させて出力するプロ...
-
14
数値の連続入力終了条件について
-
15
数字以外が入力されたらエラー...
-
16
Eclipseコンソール表示を、リセ...
-
17
c言語のプログラムで行列の積を...
-
18
if文の条件にscanf関数を使うと…?
-
19
cout関数を使っているのですが...
-
20
標準入力の際に、、、fgets
おすすめ情報
公式facebook
公式twitter