Thinkers'Studio
JavaとC言語の自習ツール
構造体配列のデータをcsvファイルに出力する例

 今回は、集計結果を保持する構造体配列の内容を csv形式でファイルに出力します(集計処理は含みません)。

構造体配列のデータをcsvファイルに出力するプログラム例 】
 ある月の各地の気温データを構造体配列 res に集計しました。
 res は、地名と平均気温、最低気温、最高気温を保持しています。
  • 出力する csvファイル名は、YYYYMMres.csv です。 処理年月を示す変数 year と month を使って生成します。
  • ファイルの先頭行に、データ項目を出力します。
  • 2行目以降に、各地点のデータをカンマ区切りで出力します。
#include <stdio.h>
#include <stdlib.h>
#define DTCNT  ((sizeof res)/(sizeof(res_t)))
typedef struct {
    char area[24]; //地名
    double avg;    //平均気温
    double min;    //最低気温
    double max;    //最高気温
} res_t;

main( )
{
    int     i, year, month;
    char    fname[24];
    FILE    *fp;

    // 本来なら、集計結果を求める処理 (ここでは仮に下記とします)
    res_t   res[] = { {"A地点", 23.24, 14.56, 30.23 }
                    , {"B地点", 27.21, 15.45, 32.18 }
                    , {"C地点", 20.12, 11.56, 29.40 } };
    year = 2014; month = 7;

    // 出力ファイル名を生成する
    sprintf( fname, "%04d%02dres.csv", year, month );
    // ファイルのオープン
    if( (fp = fopen( fname, "w" )) == NULL ) {
        printf( "結果ファイルがオープンできませんでした\n" );
        exit( 1 );
    }
    // ヘッダ行を出力する
    fprintf( fp, "エリア名,平均気温,最低気温,最高気温\n" );
    // 各データをカンマ区切りで出力する
    for( i = 0; i < DTCNT; i++ ) {
        fprintf( fp, "\"%s\",%f,%f,%f\n"
           , res[i].area, res[i].avg, res[i].min, res[i].max );
    }
    printf( "%s に結果が出力されました\n", fname );
    fclose( fp );
}
 実行すると、201407res.csv ファイルに次のように出力されます。
エリア名,平均気温,最低気温,最高気温
"A地点",23.240000,14.560000,30.230000
"B地点",27.210000,15.450000,32.180000
"C地点",20.120000,11.560000,29.400000

 出力ファイル名は、"%04d%02d" の変換書式を指定し、year, month を埋め込んだ文字列を作ります。
 csvファイル出力では、fprintf にカンマ区切りの書式を指定し、データがある間(i < DTCNT) 構造体配列 res[i] のデータを1行ずつ書き込みます。 文字列のデータは、ダブルクォート(")で囲んで出力しています。ダブルクォートを出力するには、エスケープが必要です。

(今回のクイズです)
 csvファイルへの出力内容を次のように変えるには、上のプログラムをどう変えればよいでしょう?
  ・ ヘッダ行の次に処理年月を YYYY/MM の書式で出力する
  ・ 最高気温-最低気温のデータを各行の最後に出力する
    (答えは、次回のC言語の Tips で ・・・)

[ 関連記事 ] 構造体配列にデータを読み込む, fscanfでcsvから入力
[ ご案内 ] 構造体の要点を学習できるコース:要点講座 [ 構造体編 ]

前回のクイズの答え: (前回の問題を見る
0.543000  atof は数値に変換できるところまでを返す
3.000000  先頭の空白は無視、小数点以下がない場合にも対応する
0.000000  数字でない
1.000000  数値に変換できるところまでを返す