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

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

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

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

Q&A

解決済

4回答

5636閲覧

sscanf関数の仕様でしょうか?

cingyan

総合スコア29

C

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

0グッド

0クリップ

投稿2016/05/22 04:33

編集2016/05/22 04:40
#include <stdio.h> #include <stdlib.h> #define STRING_SIZE 200 int main(void) { int val; int sum=0; int cnt=0; char FileName[14]; char string[STRING_SIZE]; FILE *fp; printf("入力ファイル名>>>"); scanf("%s",FileName); if((fp=fopen(FileName,"r"))==NULL) { printf("ファイルが見つかりません。---%s\n",FileName); exit(EXIT_FAILURE); } cnt=0; while(fgets(string,STRING_SIZE,fp)) { sscanf(string,"%d",&val); sum+=val; cnt++; } if(cnt>0) { printf("合計=%d 平均値=%g\n",sum,(double)sum/cnt); } fclose(fp); return EXIT_SUCCESS; } indata.dat abcdef ghijkl mnopqr stuvwx yz

「C言語によるプログラミング基礎編」に書いてあったのですが、実行する度に結果の数字が違うのはなぜでしょうか。

Lubuntuで作業しています。gccでコンパイルしています。

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

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

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

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

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

guest

回答4

0

ベストアンサー

sscanf(string,"%d",&val);

ここで数値を読み取ろうとしているのに、indata.datの中身が数値でないので、読み取りに失敗しています。
読み取りに失敗したためvalには何も設定されず、初期化もされていないので不定値がsumに加算されることになり、意図しない結果になってしまうのです。

sscanfは戻り値として読み取った個数を返します。上記sscanfでは変数は1個だけなので、正しく読み取れれば1が返ってきます。ですので、戻り値をチェックして1の時だけ加算処理をするようにしてください。

sscanfで正しく読み取れなかったら、「不正なデータです」のように表示させると良いかもしれません。

投稿2016/05/22 05:07

編集2016/05/22 05:11
catsforepaw

総合スコア5938

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

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

cingyan

2016/05/22 06:48

sscanfの戻り値を入れる変数 a を設定し、 int val=0;をchar val=0;にし、 sscanf(string,"%d",&val);をa=sscanf(string,"%s",&val);にして、 実行すると、以下が出力されました。 入力ファイル名>>>indata.dat 合計=356 平均値=71.2 a=1 文字用の書式設定に変更したことで、sscanfが文字列を数値へ変換すると納得していいでしょうか。 この本にはミスプリントが多かったので、そういうことでこの話を終わりにしたいと思います。
catsforepaw

2016/05/22 06:54

変数valはint型なので%dのままで良いです。というか、int型の変数に対して%sを使ってはいけません。
cingyan

2016/05/23 08:13

取り込んだデータで計算を行うなら、入力データは数字でなければならないと言うことでしょうか。
catsforepaw

2016/05/23 08:27

その通りです。計算で使うなら数値を入力しないといけません。「abcdef」のように数値として判別できないものは数値として扱われません。
cingyan

2016/05/24 08:36

ご回答ありがとうございました。。勉強になりました。
guest

0

こんにちは。

abcdef
ghijkl
mnopqr
stuvwx
yz

を読ませているのですよね?
数字が含まれていませんので、sscanf(string,"%d",&val);は全てエラーになっている筈です。
従って、valには値が設定されることがなく不定値のままです。
プログラムを起動するたびに異なる値が入っているのだと思います。

投稿2016/05/22 04:52

Chironian

総合スコア23272

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

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

cingyan

2016/05/22 06:04

本には 「sscanf関数は、scanf関数の文字列版です。第1引数に文字列(文字配列、あるいは文字列へのポインタ(char*))を取り、これを第2引数のフォーマットに従って数値へ変換します。」 と書かれているので、成功しそうな気がするのですが、分かりませんね。
nob.

2016/05/22 06:42

横から失礼します。 質問者さんが何をなさろうとしているのかが理解できません。 合計と平均を算出するように見えますが、データは abc・・・xyz を与えているようです。 abc・・・xyzの合計とか、平均とかは何を期待されているのでしょう? sscanf()の仕様にある "文字列” とは、 ”1”という文字列(16進で言うと、0x31,0x00 のことです。 (0x00は文字列終了を示す) もう一度、scanf() 関連の仕様や具体例を参考にして、考えて下さい。
Chironian

2016/05/22 09:15

> これを第2引数のフォーマットに従って数値へ変換します。 そのフォーマットが書式指定子です。今回は%dを指定しています。 %dは数字を数値へ変換します。しかし、数字でない文字を与えているので数値へ変換できずエラーになっている筈です。 ところで、"abcdef "がどんな数値に変換されることを期待されてます? "10"や"123"のような数字なら数値へ変換されますよ。
cingyan

2016/05/23 08:11 編集

回答有り難うございました。 一人で、C言語の基礎を勉強していて、使っている本に上記のプログラムが書いてあり、その実行結果は書かれていませんでしたが、自分で入力、実行すると、実行の度に結果が違うので今回の質問に至ったわけです。 本では、fscanfで文字列を読む込むとエラーになるので、fgetsとsscanfを使用し、その例として上記のプログラムが載っていたのです。 文字列を数値へ変換するというのは、文字列「a」のコード、0x61の事かと思っていました。 実際それで計算すると、合計、597になり、違っていました。 前のページにある、数字の場合のプログラミングの、indata.datを使用すると、正確な値になりました。 sscanfで取り込んだデータで数値計算を行うなら、入力データは数字でなければならないと言うのが結論でしょうか。
Chironian

2016/05/23 08:37

先のコメントにも記載しましたが、書式指定子%dは数字を数値へ変換します。 例えば、文字列"10"を%dで変換すると10というint型の数値へ変換されます。%dはこのように人が目で見て解釈するのと同様な解釈を行う機能です。 "abcdef"のような文字列を人間が目でみて数値として解釈することはできませんので、%dも同じように数値として解釈しません。
guest

0

valが初期化されていないこと、sscanfで読み取りに失敗していることが理由です。読み取りに失敗すると、valに値が代入されず、初期化されないままsumに加算されます。

投稿2016/05/22 04:46

編集2016/05/22 04:50
majiponi

総合スコア1720

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

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

cingyan

2016/05/22 05:57

int val=0; で定義しなおしたのですが、合計と平均値は、0でした。
guest

0

sscanfで文字を数字として読み取ろうとしているところと、printfで%g(float型のためのもの)をしているところが気になります。

投稿2016/05/22 04:43

HogeAnimalLover

総合スコア4830

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

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

cingyan

2016/05/22 06:12 編集

回答ありがとうございました。C言語の基礎を勉強している身ですので、気になさるところが、私は気になっていませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問