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

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

ただいまの
回答率

87.38%

fscanfがうまく動作しない

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 6,843

score 17

前提・実現したいこと

テキストファイルから情報を取り込みたい。
中身は
Dbrenlhsij,11,162.2,55.9
Ijnpwthy,14,163.8,62.6
Csaztvsy,30,176.2,57.1
Pgqfcwlx,22,161.2,57.3
Mgjwpmdxr,19,162.,65.2
Jryebcpduv,54,167.2,55.2
Dqesqocy,22,169.,64.9
というように続いていきます。(10000行あります)

fgetsを使ってstrtokでも同じことができると思いますが、学習のためにfscanfを使った方法が知りたいです。またなぜこれでは値がとりこめないのかを教えていただきたいです。

発生している問題・エラーメッセージ

fscanf(46行目)が値をとりこまない。
結果としてprintfで出力する変数は全て0.0になっています。

該当のソースコード

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

#define SIZE 100

void cal(double*,double*,double*,double*,double*,int);

int main(int argc,char *argv[]){
    FILE *fp;
    int line=0;
    char c;

    if(argc!=2) {
        printf("コマンドの後に1つファイルを指定してください。\n");
        return 1;
    }

    if ((fp= fopen(argv[1], "r"))==NULL) {
        printf("ファイルを開くのに失敗しました\n");
        return 1;
    }

    while((c = getc(fp)) != EOF) {
        if(c == '\n') {
            line++;
        }
    }

    fseek(fp,0,SEEK_SET);

    double *a;
    double *h;
    double *w;
    double *max,*min,*mean,*stdev;

    max=(double*)malloc(sizeof(double));
    min=(double*)malloc(sizeof(double));
    mean=(double*)malloc(sizeof(double));
    stdev=(double*)malloc(sizeof(double));
    a=(double*)malloc(sizeof(double)*line);
    h=(double*)malloc(sizeof(double)*line);
    w=(double*)malloc(sizeof(double)*line);

    for (int i=0; i<line; i++) {
        fscanf(fp,"%*[^,]%lf,%lf,%lf\n",a+i,h+i,w+i);
    }

    cal(a,max,min,mean,stdev,line);
    printf("Age : (max,min,mean,stdev) = (%lf, %lf, %lf, %lf)\n",
           *max,*min,*mean,*stdev);

    cal(h,max,min,mean,stdev,line);
    printf("Age : (max,min,mean,stdev) = (%lf, %lf, %lf, %lf)\n",
           *max,*min,*mean,*stdev);

    cal(w,max,min,mean,stdev,line);
    printf("Age : (max,min,mean,stdev) = (%lf, %lf, %lf, %lf)\n",
           *max,*min,*mean,*stdev);

    free(max);
    free(min);
    free(mean);
    free(stdev);
    free(a);
    free(h);
    free(w);

    fclose(fp);

    return 0;
}

void cal(double *x,double *max,double *min,double *mean,double *stdev,int line){
    *max=0,*min=1000,*mean=0,*stdev=0;

    for (int i=0; i<line; i++) {
        if ( *(x+i) > *max) {
            *max = *(x+i);
        }
        if ( *(x+i) < *min) {
            *min = *(x+i);
        }
        *mean= *mean + *(x+i);
    }
    *mean = *mean/line;
    for (int i=0; i<line; i++) {
        *stdev= *stdev + pow(*(x+i)-*mean,2);
    }
    *stdev= sqrt( *stdev/(double)line );
}

試したこと

fscanfの返り値を調べたところ毎回0でした。デバッガを用いて動きを追ってみたのですがやはりfscanfが問題のようです。

補足情報(言語/FW/ツール等のバージョンなど)

OS Xです。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

+1

回答ではないですが、

clang -pipe -Weverything -Ofast -c "untitled.c"(ディレクトリ: /home/kondo/test/ctst)
untitled.c:48:16: warning: implicit conversion loses integer precision: 'int' to 'char' [-Wconversion]
    while((c = getc(fp)) != EOF) {
             ~ ^~~~~~~~
/usr/include/stdio.h:523:35: note: expanded from macro 'getc'
#define getc(fp)        (!__isthreaded ? __sgetc(fp) : (getc)(fp))
                                         ^~~~~~~~~~~
/usr/include/stdio.h:480:37: note: expanded from macro '__sgetc'
#define __sgetc(p) (--(p)->_r < 0 ? __srget(p) : (int)(*(p)->_p++))
                                    ^~~~~~~~~~
untitled.c:48:16: warning: implicit conversion loses integer precision: 'int' to 'char' [-Wconversion]
    while((c = getc(fp)) != EOF) {
             ~ ^~~~~~~~
/usr/include/stdio.h:523:35: note: expanded from macro 'getc'
#define getc(fp)        (!__isthreaded ? __sgetc(fp) : (getc)(fp))
                                         ^~~~~~~~~~~
/usr/include/stdio.h:480:50: note: expanded from macro '__sgetc'
#define __sgetc(p) (--(p)->_r < 0 ? __srget(p) : (int)(*(p)->_p++))
                                                 ^~~~~~~~~~~~~~~~~
untitled.c:48:16: warning: implicit conversion loses integer precision: 'int' to 'char' [-Wconversion]
    while((c = getc(fp)) != EOF) {
             ~ ^~~~~~~~
/usr/include/stdio.h:523:49: note: expanded from macro 'getc'
#define getc(fp)        (!__isthreaded ? __sgetc(fp) : (getc)(fp))
                                                       ^~~~~~~~~~
untitled.c:65:38: warning: implicit conversion changes signedness: 'int' to 'unsigned long' [-Wsign-conversion]
    a=(double*)malloc(sizeof(double)*line);
                                    ~^~~~
untitled.c:66:38: warning: implicit conversion changes signedness: 'int' to 'unsigned long' [-Wsign-conversion]
    h=(double*)malloc(sizeof(double)*line);
                                    ~^~~~
untitled.c:67:38: warning: implicit conversion changes signedness: 'int' to 'unsigned long' [-Wsign-conversion]
    w=(double*)malloc(sizeof(double)*line);
                                    ~^~~~
untitled.c:99:11: warning: possible misuse of comma operator here [-Wcomma]
    *max=0,*min=1000,*mean=0,*stdev=0;
          ^
untitled.c:99:5: note: cast expression to void to silence warning
    *max=0,*min=1000,*mean=0,*stdev=0;
    ^~~~~~
    (void)( )
untitled.c:99:21: warning: possible misuse of comma operator here [-Wcomma]
    *max=0,*min=1000,*mean=0,*stdev=0;
                    ^
untitled.c:99:12: note: cast expression to void to silence warning
    *max=0,*min=1000,*mean=0,*stdev=0;
           ^~~~~~~~~
           (void)(  )
untitled.c:99:29: warning: possible misuse of comma operator here [-Wcomma]
    *max=0,*min=1000,*mean=0,*stdev=0;
                            ^
untitled.c:99:22: note: cast expression to void to silence warning
    *max=0,*min=1000,*mean=0,*stdev=0;
                     ^~~~~~~
                     (void)()
untitled.c:29:9: warning: macro is not used [-Wunused-macros]
#define SIZE 100
        ^
10 warnings generated.
コンパイル完了


(-Weverything)設定してるのでかなり厳しいですが、これだけワーニングがでます。確認しましたか? こちらの環境はFreeBSD clang version 4.0です。
また、while((c = getc(fp)) != EOF) はcがcharなのでEOFが判定できません。getc()の返り値はintです。・・・空読みするだけならfgets()がいいですよ。fscanf()も読み込んだ項目数が返るので読めたかどうか判定してください。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

読み込みの部分のみでたの部分までは見ておりませんでご参考にどうぞ
読み飛ばししたかったのですね、修正しました。

    int i;
    for (i=0; i<line; i++) {
        fscanf(fp,"%*[^,],%lf,%lf,%lf\n",a+i,h+i,w+i);
        printf("%lf %lf %lf\n",*(a+i),*(h+i),*(w+i));
    }

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

checkベストアンサー

0

書式指定文字列 "%*[^,],%lf,%lf,%lf\n" でいかがでしょう。1つ目のフィールド(%*[^,])の次に,の読み捨て指定が必要なはずです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

  • ただいまの回答率 87.38%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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