[PR]口が臭う人の共通点…:臭いが見える対策は?

- Comma Separated Value(CSV)フォーマットによる計測データのファイル出力 - 
〜Microsoft Excel へデータのインポート〜

yosirin-hello / yosi-s@galaxy.ocn.ne.jp

1. はじめに

 今まで, 数値計算の実験の計測データを実行画面からコピー&ペーストをしてExcelで処理をしていました. この方法は計測データが少ないときには手軽で便利ですが, モンテカルロ法などで非常に多くのデータをサンプリングする場合, 非効率ですしイライラします. そこでこの問題を解決するために, CSVフォーマットでデータをファイル出力し, Excelでそのファイルを読み込んで処理をできるように考えました. また, CSVは表計算ソフトやデータベースソフトでも対応しているフォーマットなので汎用性があり, 利用価値は十分あると思います.
2. CSVフォーマットとは

 CSVフォーマットは, 簡単に言うと値と値の間をコンマで区切って表現するフォーマットです.(Fig1.) 今回の場合は, ただ単に計測データをコンマで区切ればいいわけですから, 本当に手軽にデータをファイル出力ができるのです.

3. Cによる実装

今回はプログラムはそれほど複雑ではないので簡単だと思います.

List1. CSVフォーマットで計測データを出力するプログラム 実行結果(ファイルの中身)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//----------------------------------------------------------------------------//
//                              マクロの定義                                   //
//----------------------------------------------------------------------------//
#define MAX_DECODE_LENG 50  // _itoa(), _gcvt()の際に使用する配列のインデックスの最大値
#define MAX_DATA        500 // 構造体DATAの計測データの記憶できる個数の最大値

#define INSERT_COMMA( fp )  fprintf( fp, "," );  // コンマの書き出しマクロ
#define INSERT_RETURN( fp ) fprintf( fp, "\n" ); // 改行の書き出しマクロ

// varをファイルに書き出してコンマを挿入するマクロ
#define WRITE_VAR_AND_COMMA( var, fp )          fprintf( fp, var );             \
                                                INSERT_COMMA( fp )

// varをファイルに書き出して改行を挿入するマクロ
#define WRITE_VAR_AND_RETURN( var, fp )         fprintf( fp, var );             \
                                                INSERT_RETURN( fp )

#define WRITE           "w" // OutputData_CSVFormat()のファイルの書き込みモード
#define APPEND          "a" // 追加書き込み

#define SHOW_WORKING // OutputData_CSVFormat()の動作状況の表示

//----------------------------------------------------------------------------//
//                           構造体 DATAの定義                                 //
//----------------------------------------------------------------------------//
typedef struct {
        char*  p_strTitle; // 計測のタイトル 

        char*  p_strData1_Name; // 計測データ1の名前
        char*  p_strData2_Name; // 計測データ2の名前

        int    nDataCount; // 計測データの個数

        int    nSampling[MAX_DATA]; // サンプリング数
        double dbData1[MAX_DATA];   // データ1
        double dbData2[MAX_DATA];   // データ2
} DATA;


//----------------------------------------------------------------------------//
// Name : OutputData_CSVFormat()
// Desc : CSVフォーマットで計測データを出力する
// Parameter
//        pFileName : (in) ファイル名(拡張子.csvも必要)
//        Data      : (in) 計測データ
//        p_mode    : (in) 書き込みモード
//                    WRITE または"w"を指定するとファイルが存在すると上書きされる
//                    APPEND または"a"を指定するとファイルの最後から書き込む
//
// Note : #define SHOW_WORKING で動作状況の表示をする
//----------------------------------------------------------------------------//
void OutputData_CSVFormat( char* pFileName, DATA Data, char* p_mode )
{
        FILE* fp = NULL;
        char strData[MAX_DECODE_LENG];
        char strSampling[MAX_DECODE_LENG];

        fp = fopen( pFileName, p_mode );
        if( fp == NULL ) {
                printf("ファイルオープンの失敗.\n");
                exit( 1 );
        }

#ifdef SHOW_WORKING
        printf( "ファイルをオープンしました.[%s, %s]\n", pFileName, Data.p_strTitle );
#endif
        
        WRITE_VAR_AND_RETURN( Data.p_strTitle, fp )       // タイトルの書き出し
        WRITE_VAR_AND_COMMA(  "サンプル数", fp  )          // "サンプル数"の書き出し
        WRITE_VAR_AND_COMMA(  Data.p_strData1_Name, fp )  // "Data1の名前の書き出し
        WRITE_VAR_AND_RETURN( Data.p_strData2_Name, fp  ) // "Data2の名前の書き出し

        for( int i = 0; i < Data.nDataCount; i++ ) {
                _itoa( Data.nSampling[i], strSampling, 10 );
                WRITE_VAR_AND_COMMA(  strSampling, fp ); // 試行回数の書き出し
                
                _gcvt( Data.dbData1[i], 10, strData );
                WRITE_VAR_AND_COMMA(  strData, fp ); // Data1の書き出し
                
                _gcvt( Data.dbData2[i], 10, strData );
                WRITE_VAR_AND_RETURN(  strData, fp ); // Data2の書き出し
        }
        INSERT_RETURN( fp ); // 改行の書き出し
        INSERT_RETURN( fp ); // 改行の書き出し

        fclose( fp );

#ifdef SHOW_WORKING
        printf( "ファイルをクローズしました.[%s, %s]\n\n", pFileName, Data.p_strTitle );
#endif
}
4. 計測データを出力したCSVファイルをExcelにインポート

計測データを出力したCSVファイルをExcelで開くと下のようになります.



後は自分の好きなようにデータを処理してやればいいだけです.
5. 最後に

 このプログラムは直感で作ったので構造体のデータ構造はあまり納得していません. できればもっと汎用性のあるデータ構造にできればよかったですね. このプログラムを作っていて感じたのは, XMLようなフォーマットで書けばもっと色々な所でデータの使い回しができそうだなということです. まあ, 今回のような計測の仕方だったらCSVでも十分ですけど.
6. 参考文献

1. 拡張子辞典
2. Microsoft MSDN Library, VisualC++プログラマーズガイド/ランタイム ライブラリ リファレンス/カテゴリー別ランタイムルーチン/データ変換
7. 改訂履歴

改訂 履歴 日付
1.0 初公開 02/21/2002


Copyright © 2002 yosirin-hello All rights reserved.


[PR]当たる!無料占いで仕事鑑定:大人気!無料占い『スピリチュアルの館』