• ベストアンサー

fgetsとsscanf

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を混同して使用すると、どこかの入力時に改行がバッファに残ってしまい、入力処理が飛ばされてしまいますか? 以上、よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

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 系ならバッファサイズも指定できるんじゃなかったっけ....

ya-cha
質問者

お礼

例を取り入れてくださり、初心者の私にもとても分かりやすい説明です。 本当にありがとうございます。 回答者様にはいつも助けられてばかりで感謝感謝です。

その他の回答 (4)

  • Yanch
  • ベストアンサー率50% (114/225)
回答No.5

●回答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()が有効です。

ya-cha
質問者

お礼

メリットなどを含め、とても丁寧なご回答ありがとうございます。 リファレンスというか、参考書に書いてある内容は読んだんですが、外国の本が訳してあるので、日本語が分かりづらく書いてあり、苦戦しております・・・。 ネットで見るようにいたします。 何日か考えた結果、キーボードからの入力には基本的に 「fgets」+「sscanf」の組み合わせでプログラミングしていきたいと思います。 本当にありがとうございました。

  • php504
  • ベストアンサー率42% (926/2160)
回答No.3

fgets(data, sizeof(data), stdin); には改行だけじゃなくスペースやタブ等の文字も入りますね。

  • php504
  • ベストアンサー率42% (926/2160)
回答No.2

fgets(buf,sizeof(buf),stdin); sscanf(data, "%s", buf); dataには改行が含まれない fgets(data, sizeof(buf), stdin); は fgets(data, sizeof(data), stdin); の間違いですよね 入力がsizeof(data)以内の場合dataに改行が含まれる

ya-cha
質問者

お礼

シンプルで分かりやすいご説明ありがとうございます。 参考にさせていただきます。

  • eroermine
  • ベストアンサー率18% (83/444)
回答No.1

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.

ya-cha
質問者

お礼

ご回答ありがとうございます。 最後の英文3行は何のことかちんぷんかんぷんですorz

関連するQ&A