C言語関係掲示板

過去ログ

No.377.scanf書式中のスペース

[戻る] [ホームページ]
No.2510

whileループの中でscanfを使用するとき
投稿者---しょうじ(2002/08/27 10:49:37)


現在MicrosoftVC++5.0を使用しています。
質問なのですが、下のプログラムは構造体 nyuryokuの
メンバの name, sintai[0], sintai[1]を入力し、ctrl + z
が押下されるまで"aiueo"が出力されるプログラムです。

while((scanf("%s %d %d ",nyuryoku.name,
&nyuryoku.sintai[0],&nyuryoku.sintai[1])) != EOF)
{
printf("aiueo\n");
}

このプログラムでは1回目の入力では"aiueo"が出力されず、
2回目の入力から出力できるようになります。
1回目の入力から"aiueo"を出力する方法を教えて下さい。
お願いします。

No.2514

Re:whileループの中でscanfを使用するとき
投稿者---TDa(2002/08/27 11:29:49)


こんにちは。

while((scanf("%s %d %d ",nyuryoku.name,&nyuryoku.sintai[0],&nyuryoku.sintai[1])) != EOF)

scanf()の引数の

scanf("%s %d %d□ ", 省略)
このスペースが余計です。わかりやすいように'□'で書きました。
これを消せば思った通りに動くはず。


No.2517

Re:whileループの中でscanfを使用するとき
投稿者---しょうじ(2002/08/27 13:42:25)


ご返答有難うございました。
アドバイスの通りに行った結果うまく実行できました。
しかし、scanf("%d %d□",省略)
の□(空白)を取り除いただけでなぜ正常に実行できたの
でしょうか?
教えて下さい。お願いします。

No.2530

Re:whileループの中でscanfを使用するとき
投稿者---かずま(2002/08/28 19:35:38)


> しかし、scanf("%d %d□",省略)の□(空白)を取り除いただけで
> なぜ正常に実行できたのでしょうか?

scanf の書式で、空白(スペース、タブ、改行など)には、0 個以上連続する入
力の空白を読み飛ばすという機能があります。空白を読み飛ばすということは、
空白を読んでは捨て、読んでは捨てを繰り返し、空白でない文字が読めたとこ
ろで、その文字を入力に押し戻すということです。

ここでいう入力とは標準入力ストリームのことで、これはキーボードやファイ
ルと、ユーザプログラムとの間にあるバッファのことだと考えてください。

さて、"%s %d %d " という書式に対して、

abc 123 45
def 67 890

という入力を与えると、書式の最後の空白は、入力の 45 の次の「改行」を読み
飛ばしますが、それに続く d を読み込んで、その d を入力に押し戻すまでは、
自分の役目を終えることができないのです。だから、次の行が入力されるまでは、
scanf が終了せず、あとの処理が実行されないのです。

では、d の 1文字をキー入力したところで、scanf が終了するのかというと、
そんなことはありません。キー入力は OS が管理し、1行の入力が完了したところで、
標準入力ストリームのバッファに行全体が送り込まれます。

余談ですが、書式の最後の "%d" は、何を読み込むかわかりますか。45 を読んだ後、
次の「改行」を読み込んで、これが数字でないのを確かめてから、その「改行」文字
を入力に押し戻します。

では、2回目の scanf がどう動くかというと、書式の最初の "%s" は、まず入力の
先頭にある「改行」(すなわち、45 の次の「改行」)を読み捨てます。それから def
を読み込み、さらに次のスペースを読み込んで、それを入力に押し戻しているのです。