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

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

ただいまの
回答率

90.48%

  • C

    3836questions

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

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

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 927

cingyan

score 19

#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でコンパイルしています。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

0

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

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

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/22 15: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が文字列を数値へ変換すると納得していいでしょうか。

    この本にはミスプリントが多かったので、そういうことでこの話を終わりにしたいと思います。

    キャンセル

  • 2016/05/22 15:54

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

    キャンセル

  • 2016/05/23 17:13

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

    キャンセル

  • 2016/05/23 17:27

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

    キャンセル

  • 2016/05/24 17:36

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

    キャンセル

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/22 14:56 編集

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

    キャンセル

0

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/22 14:57

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

    キャンセル

0

こんにちは。

abcdef
ghijkl
mnopqr
stuvwx
yz

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/22 15:04

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

    キャンセル

  • 2016/05/22 15:42

    横から失礼します。

    質問者さんが何をなさろうとしているのかが理解できません。
    合計と平均を算出するように見えますが、データは abc・・・xyz を与えているようです。
    abc・・・xyzの合計とか、平均とかは何を期待されているのでしょう?

    sscanf()の仕様にある "文字列” とは、 ”1”という文字列(16進で言うと、0x31,0x00 のことです。
    (0x00は文字列終了を示す)

    もう一度、scanf() 関連の仕様や具体例を参考にして、考えて下さい。

    キャンセル

  • 2016/05/22 18:15

    > これを第2引数のフォーマットに従って数値へ変換します。

    そのフォーマットが書式指定子です。今回は%dを指定しています。
    %dは数字を数値へ変換します。しかし、数字でない文字を与えているので数値へ変換できずエラーになっている筈です。

    ところで、"abcdef "がどんな数値に変換されることを期待されてます?
    "10"や"123"のような数字なら数値へ変換されますよ。

    キャンセル

  • 2016/05/23 16:29 編集

    回答有り難うございました。
    一人で、C言語の基礎を勉強していて、使っている本に上記のプログラムが書いてあり、その実行結果は書かれていませんでしたが、自分で入力、実行すると、実行の度に結果が違うので今回の質問に至ったわけです。
    本では、fscanfで文字列を読む込むとエラーになるので、fgetsとsscanfを使用し、その例として上記のプログラムが載っていたのです。

    文字列を数値へ変換するというのは、文字列「a」のコード、0x61の事かと思っていました。
    実際それで計算すると、合計、597になり、違っていました。

    前のページにある、数字の場合のプログラミングの、indata.datを使用すると、正確な値になりました。

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

    キャンセル

  • 2016/05/23 17:37

    先のコメントにも記載しましたが、書式指定子%dは数字を数値へ変換します。

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

    キャンセル

関連した質問

同じタグがついた質問を見る

  • C

    3836questions

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