C言語関係掲示板

過去ログ

No.1190 scanf()とfgets()が混在してあるプログラムについて 

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

scanf()とfgets()が混在してあるプログラムについて
投稿者---kamina(2004/07/15 17:07:30)


はじめまして、kaminaと申します。よろしくお願いします。

ここの標準入出力関数(1)のscanf()の部分について読んでいて、プログラムを作ったのですが、うまくいかないときがあります。
たとえば・・・

void main()
{
int a;
char b[10];

printf("数字いれて");
scanf("%d", a);
printf("文字入れて");
fgets(b, sizeof b, stdin);
sscanf(b,"%s",&b);
}
というような形でつくり、コンパイル後、実行しても文字が入りません。
scanf()後に\n が必ず入力されるということはわかったのですが、
この場合fgets()を使った場合は\nを飛ばして入力できると思いましたが、
文字が入力できませんでした。
fgets()について自分の認識不足もあると思いますが、解決できずにいます。scanf()のあとに、fgets()を入れてはいけないのでしょうか?
※本には、あまりscanf()を多用するな的なことが書いてありましたので・・
また、解決法があるとすれば、どのようにすればいいのでしょうか?

申し訳ありませんが、どなたかご教授していただければ幸いです。


No.15552

Re:scanf()とfgets()が混在してあるプログラムについて
投稿者---あかま(2004/07/15 18:10:19)


http://www9.plala.or.jp/sgwr-t/c/sec05.html#s5-4
↑ここは読みました?

>scanf()後に\n が必ず入力されるということはわかったのですが、
後ではなく、scanfの入力時ですね。そのときの'\n'が残ります。

>この場合fgets()を使った場合は\nを飛ばして入力できると思いましたが、
>文字が入力できませんでした。
fgetsは'\n'を読み込みます。読み込んだら読み込みを打ち切ります。
ですのでscanfの後だと入力できません。

>scanf()のあとに、fgets()を入れてはいけないのでしょうか?
入れる前に読み捨てをすればいいでしょう。
fgetsを2回にするとか。
fgetsしてからsscanfで分けるとか。

>※本には、あまりscanf()を多用するな的なことが書いてありましたので・・
セキュリティホール云々でそう書かれることが多いですが、そんなことないですよ。
便利なものは使ったほうがいいです。
ただ、scanfは間違った入力の時に問題があって、

#include <stdio.h>

int main(){
    int i=1;
    while(i){//0の入力で終了
        scanf("%d",&i);
        printf("%d",i);
    }
}

こんなプログラムを書いたときに、数字以外の入力をすると
バッファに文字が残り続けるために無限ループします。

#include <stdio.h>

int main(){
    int i=1;
    char str[256];
    while(i){
        fgets(str,256,stdin);
        sscanf(str,"%d",&i);
        printf("%d",i);
    }
}

なので、fgetsとsscanfを組み合わせるとよりよいかと思います。



No.15553

Re:scanf()とfgets()が混在してあるプログラムについて
投稿者---NykR(2004/07/15 18:17:31)


>というような形でつくり、コンパイル後、実行しても文字が入りません。
>scanf()後に\n が必ず入力されるということはわかったのですが、
>この場合fgets()を使った場合は\nを飛ばして入力できると思いましたが、

scanfの%dは、次の非空白類文字から、整数に変換できない文字の直前までを読み込みます。
ですから、「\nが入力される」と言うよりは、入力された\nが取り残されるわけですね。

fgetsは、直前の入力終わりの次の文字から改行文字までを読み込みます。
ですから、いきなり改行文字があれば、改行文字だけを読むことになります。
「\nを *飛ばして* 入力」なんて器用なことはできません。

# scanfの%sならできますが。


>fgets()について自分の認識不足もあると思いますが、解決できずにいます。scanf()のあとに、fgets()を入れてはいけないのでしょうか?

いけないことはないですが、それで得をするようなことも滅多にありません。scanfを使うなら、scanfだけを使い続けた方がいいです。
# 改行をとばせるから

>※本には、あまりscanf()を多用するな的なことが書いてありましたので・・

scanfは、改行文字とそのほかの空白類文字を区別できないので、1行入力を受け付けるのには向きません。fgetsを使う方がいいです。

逆に、行を認識しなくていいような入力で、字句解析を行うようなものを書くときは、scanfを使わないとやってられません。

行を認識しなくていいような入力で、あまり大袈裟なことをやらない場合はgetcharを使うといいでしょう。

# 行を認識しなければならないような入力で、字句解析を行うようなものを書くとき、(strtokじゃ間に合わない場合)はどうするんでしょう。fgetsとsscanfの%n?


>また、解決法があるとすれば、どのようにすればいいのでしょうか?

・scanf("%*[\n]");をfgetsの前に入れる。
・fgetsの代わりにscanfの%sを使う。
・最初の入力は scanfで入力受付と解析を一度にやるようになっているが、これを、fgetsで入力を受け付けてからsscanfで解析するように変更する。

普通は3つ目の方法を使うと思います。