プロが教えるわが家の防犯対策術!

C言語の勉強をしております。

初歩的な質問なのかもしれないですが、

char buf[80];
char data[32];

fgets(buf,sizeof(buf),stdin);
sscanf(data, "%s", buf);

と、

fgets(data, sizeof(buf), stdin);

は何が違うのでしょう?
他の質問内容やネットで探してみたんですが、基本的には組み合わせて使用されているみたいなんですが、必要性がわかりません・・・。

例えば、fgetsで構造体のメンバ(文字配列)へキーボードからデータを入力したい場合は、どちらで行うのが良いのでしょう?

また、入力データが未入力かどうか判断させるには、

fgets(buf,sizeof(buf),stdin);
if(buffer[0] == '\n'){
  /* ループを抜ける */
  break;
}

で良いですよね?
※関連している質問
http://oshiete1.goo.ne.jp/qa4438371.html

あと、同じ処理内で、getsやscanfを混同して使用すると、どこかの入力時に改行がバッファに残ってしまい、入力処理が飛ばされてしまいますか?


以上、よろしくお願いいたします。

A 回答 (5件)

scanf 系の %s 変換は, 「先頭の空白文字を無視する」&「それ以外の最初の空白文字までを取り出す」という仕様です. だから, 直接 fgets するのとは意味が異なります. 例えば


[SP][SP][SP]abcd[SP]efg[CR]
という行 ([SP] は空白を, [CR] は改行をあらわす)
があると, fgets+sscanf では「abcd」が得られるはずです (fgets では行頭の空白文字も含めて入力されるので違う結果になります).
で, scanf 系で %s 変換すると「得られた文字列の後ろにある空白文字」はそのまま残ります (上の行を scanf なり fscanf なりで取り込むと, d のあとの空白文字以降がストリームに残ったままになります). なので, scanf してから fgets するとこの空白文字が邪魔をすることがあります. つまり
abcd[CR]
という行を scanf で取り込むと, 行末の改行文字がストリームに残るので直後の fgets ではこの改行文字を取り込むことになります. これが嫌な時は, scanf の書式文字列を工夫するのが本手でしょう.
でも, gets はともかく scanf 系ならバッファサイズも指定できるんじゃなかったっけ....
    • good
    • 0
この回答へのお礼

例を取り入れてくださり、初心者の私にもとても分かりやすい説明です。

本当にありがとうございます。
回答者様にはいつも助けられてばかりで感謝感謝です。

お礼日時:2008/10/30 17:33

●回答1


> char buf[80];
> char data[32];

> fgets(buf,sizeof(buf),stdin);
> sscanf(data, "%s", buf);

> と、


> fgets(data, sizeof(buf), stdin);
の違いを答えたいと思いますが、
その前に、

> fgets(buf,sizeof(buf),stdin);
> sscanf(data, "%s", buf);
これは、
fgets(buf,sizeof(buf),stdin);
sscanf(buf, "%s", data);
の間違いじゃないかな。

と言う事で、
fgets()関数にの内容は、リファレンスを参照すればわかると思いますが、
一行のデータを読み込む処理ですね。入力データに改行が含まれていれば、
bufの末尾に改行コードが付きます。
# リファレンス読んで見ましたか?

sscanf()を使って、改行コードを除去してる所ですね。

●回答2
fgets()+sscanf()を組み合わせる事のメリットですが、
行末の改行を除去するだけの処理でしたら、他にも実装方法はありそうですが、
sscanfを使う事によって、%dとか%xとかを使った入力にも応用が利きます。

●回答3
> あと、同じ処理内で、getsやscanfを混同して使用すると、どこかの入力時に改行がバッファに残ってしまい、入力処理が飛ばされてしまいますか?
気をつけてプログラミングすれば改行バッファに残る事はありませんが、
場合によっては、読みにくいコードになってしまうかもしれません。
注意です。
改行がバッファに残ってしまい、入力処理が飛ばされるような状況におちいった場合は、
変数のダンプ、トレースなどして、みると原因を見つけるのに役立つと思います。

●おまけ
gets()の代わりにfgets()を使うのは、人それぞれだと思います。
たぶん好みの違いだと思います。
が、
fgets()ではなく、gets()を使った場合、バッファサイズを指定できないので、
バッファあふれになる危険性があります。
C言語でバッファオーバーした場合、どのような動作になるかは予想が付きませんので、
回避策の1つとして、fgets()が有効です。
    • good
    • 0
この回答へのお礼

メリットなどを含め、とても丁寧なご回答ありがとうございます。

リファレンスというか、参考書に書いてある内容は読んだんですが、外国の本が訳してあるので、日本語が分かりづらく書いてあり、苦戦しております・・・。
ネットで見るようにいたします。

何日か考えた結果、キーボードからの入力には基本的に
「fgets」+「sscanf」の組み合わせでプログラミングしていきたいと思います。

本当にありがとうございました。

お礼日時:2008/10/30 17:36

fgets(data, sizeof(data), stdin);


には改行だけじゃなくスペースやタブ等の文字も入りますね。
    • good
    • 0

fgets(buf,sizeof(buf),stdin);


sscanf(data, "%s", buf);
dataには改行が含まれない

fgets(data, sizeof(buf), stdin);

fgets(data, sizeof(data), stdin);
の間違いですよね
入力がsizeof(data)以内の場合dataに改行が含まれる
    • good
    • 0
この回答へのお礼

シンプルで分かりやすいご説明ありがとうございます。

参考にさせていただきます。

お礼日時:2008/10/30 17:30

sscanf, gets はバッファサイズが指定できないので


大サイズの入力があるとシステムを破壊してしまいます。
恐ろしいですね。
ウィルス騒動の原因もここらへんにあったり。

>あと、同じ処理内で、getsやscanfを混同して使用すると、どこかの入力時に改行がバッファに残ってしまい、入力処理が飛ばさ

エラーで終わって クリア処理してないのでは。
void
clearerr(FILE *stream);The function clearerr() clears the end-of-file and error indicators for
the stream pointed to by stream.
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

最後の英文3行は何のことかちんぷんかんぷんですorz

お礼日時:2008/10/30 17:29

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!