質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

terminal

Terminalは、Apple社のmacOSに標準で付属しているUNIX端末エミュレータ。UNIXコマンドによってMacの操作および設定を行うことができます。

Q&A

解決済

3回答

972閲覧

sscanf が1つしか読み取ってくれない

yonitugu

総合スコア1

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

terminal

Terminalは、Apple社のmacOSに標準で付属しているUNIX端末エミュレータ。UNIXコマンドによってMacの操作および設定を行うことができます。

0グッド

0クリップ

投稿2022/01/04 02:56

c言語の sscanf について質問させてください。
マックのterminalです。
int main(){
char linebuf[256];
int parcel[256][2];
int i=0;

while(fgets(linebuf, 256, stdin)!=NULL){
printf("linebuf[0]=%c \n", linebuf[0]);
printf("linebuf[1]=%c \n", linebuf[1]);
printf("linebuf[2]=%c \n", linebuf[2]);
printf("linebuf[3]=%c \n", linebuf[3]);
printf("linebuf[4]=%c \n", linebuf[4]);

sscanf(linebuf, "%d, %d", &parcel[i][0], &parcel[i][1]); printf("parcel[%d][0]=%d ", i, parcel[i][0]); printf("parcel[%d][1]=%d \n", i, parcel[i][1]); ++i;

}
return 0;
}

これを./a.out で実行し、標準入力で 12 25 を入れると、
./a.out
12 25
linebuf[0]=1
linebuf[1]=2
linebuf[2]=
linebuf[3]=2
linebuf[4]=5
parcel[0][0]=12 parcel[0][1]=0
となって、linebuf にはちゃんと入ってるのですが、
25が入ってて欲しい parcel[0][1]
には何も入らず。
ネットで色々調べましたがうまく行かず、こちらで似た質問があって、それでもうまく行かなかったので、質問させていただきました。よろしくお願いします!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2022/01/05 01:31

ご質問として解決されましたら、ベストアンサーを選んで解決済みとしてください。
yonitugu

2022/01/05 01:45

すいません。初めてなもので、あまりよくわかっておりませんで。 いただいたご回答、どれも素晴らしく、そのままにしておいたのですが、それだと解決済みにならないのですね。了解しました。ご教示ありがとうございます。
guest

回答3

0

sscanfで"%d, %d"としてカンマの入力を期待しているけど実際の入力にカンマが無いからでは。

投稿2022/01/04 03:08

itagagaki

総合スコア8402

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yonitugu

2022/01/04 05:54

ありがとうございます。よく理解できました。
yonitugu

2022/01/04 06:14

Sscanfの側でカンマを入れたら、入力でも入れないといけなくて、カンマを入れないなら入れないで、入力の方で入れない、というわけですね。理解が深まりました!感謝です。
guest

0

ネットで色々調べました

「頑張ったんだもん」の主張のためではないのですから、調べて得た情報が何で、そこから解決に至らないまでもどういう考えを経たかを書かないと、「色々調べた」こと自体に意味がなくなってしまいます。(宿題ができなかった言い訳なら「頑張った」事実は重要かもしれませんが、問題の解決には全く寄与しません)

さて。
(scanf系の話はときどき書くんだけど、どっかいっちゃうんだよなぁ...)
scanf(以下sscanfを含めscanfで代表とします)は、初心者向けみたいな扱いになっていますが、「定番」から一歩踏み出すと、ちゃんとした知識がないと結構痛い目を見るかもしれません。
scanfは、「書式指定文字列にマッチするデータ(文字列)を取り込んで、そこから指定されたデータを取り出す」機能を持っています。

"%d"は、「読み込み位置から、0個以上の空白文字(スペース、改行、タブ文字等)を読み飛ばした後に整数として解釈できる数字の並びがあればデータとして取り出す(解釈できない文字が出てくるまで取り込む)」という指示です。

では、"%d, %d"とは?
「0個以上の空白文字を読み飛ばした後に整数として解釈できる数字の並びがあって(ここまで先の%d)、','があり、0個以上の空白を読み飛ばし(これは' 'の働き)、0個以上の空白文字を読み飛ばした後に整数として解釈できる数字の並びがある(後の%d)」ものにマッチします。
例を挙げるなら、
"123,456"、" 123, 456"、"123, [改行]456"等はOK。しかし、"123 456"はマッチしません。最初の%dまでは一致するのでデータを取りますが、そこまで。ついでに言えば"123 , 456"も駄目ですね。
入力が書式指定文字にマッチしない場合は、scanfはデータの取り込みを諦めて先に進みます。"123,456"みたいなデータ形式に対してのみマッチするのに、そういうデータを与えなければデータの取得は失敗します。

そうでない入力を与えたいのなら、それに合った(一致する)書式指定をしてやらなければいけません。
"123 456"を受け取りたいのなら、「0個以上の空白文字を読み飛ばした後に整数として解釈できる数字の並びがあって(ここまで先の%d)、0個以上の空白文字を読み飛ばした後に整数として解釈できる数字の並びがある(ここまで後の%d)」つまり"%d%d"。あるいは、「見た目」のままに間に空白を挟んで"%d %d"でも特に問題はないです。書式指定中の空白は、「0個以上の空白を読み飛ばす」ので、「(%dのあと)、0個以上の空白を読み飛ばして(' ')、0個以上の空白を読みどばした後の整数を取得(後の%d)」としても書式が一致/データが取得できることになります。


初心者的ミスのあるあるの一例にscanf("%d\n",&val);というのがあります。これがどういう入力をうけつけることになるか、考えてわかるようならscanfに引っかかることはもうないんじゃないかしら。

投稿2022/01/04 04:55

thkana

総合スコア7629

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yonitugu

2022/01/04 05:57

ありがとうございます。じっくり読ませていただきます。
guest

0

ベストアンサー

カンマ(,)があるから,その後は読み込めずに不定になります。

sscanf(linebuf, "%d, %d", &parcel[i][0], &parcel[i][1]);

sscanf(linebuf, "%d %d", &parcel[i][0], &parcel[i][1]);

~/Project/c >./a.out
12 25
linebuf[0]=1
linebuf[1]=2
linebuf[2]=
linebuf[3]=2
linebuf[4]=5
parcel[0][0]=12 parcel[0][1]=25

投稿2022/01/04 03:29

cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cateye

2022/01/04 03:48 編集

~/Project/c >./a.out 12 25 linebuf[0]=1 linebuf[1]=2 linebuf[2]= linebuf[3]=2 linebuf[4]=5 error ~/Project/c >echo $? 1 ~/Project/c >cat tera.c #include <stdio.h> int main() { char linebuf[256]; int parcel[256][2]; int i = 0; while (fgets(linebuf, 256, stdin) != NULL) { printf("linebuf[0]=%c \n", linebuf[0]); printf("linebuf[1]=%c \n", linebuf[1]); printf("linebuf[2]=%c \n", linebuf[2]); printf("linebuf[3]=%c \n", linebuf[3]); printf("linebuf[4]=%c \n", linebuf[4]); if(sscanf(linebuf, "%d, %d", &parcel[i][0], &parcel[i][1]) !=2){ puts("error"); return 1; } printf("parcel[%d][0]=%d ", i, parcel[i][0]); printf("parcel[%d][1]=%d \n", i, parcel[i][1]); ++i; } return 0; }
yonitugu

2022/01/04 06:09

ありがとうございます。カンマをとれば通ること、理解できました。
yonitugu

2022/01/04 06:20

カンマを取ったらうまくいきました。ありがとうございます!
cateye

2022/01/04 07:07

scanf()系のライブラリ(sscanf,fscanfなど )は、戻り値は必ずチェックしましょうd(^^ ・・・(上記の!=2など)
yonitugu

2022/01/04 11:15

scanf系の戻り値、重要とのこと、了解です。頭に入れておきます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問