C言語ケーススタディ Excelで作ったデータ(CSVファイル)の読み込みプログラム2




2014年10月より個人の方を対象に、Study C無料提供を開始しました。
C言語を勉強中の方は、学習・教育に最適なC言語インタープリタのStudy Cを使ってみてください(個人の方は無料です)。
大学・高専・高校などの教育機関での採用実績も多数あるロングセラー商品Study Cが、個人向けに無料提供を始めました。
インタープリタの手軽さに加え、ゲームや3Dタートルグラフィックで楽しく勉強したりと、C言語の学習を強力にサポートします。
ブロック崩しゲーム 3Dツリー クリスマスツリー
また、このようなボタンの用意されているページでは、掲載しているプログラムをStudy Cに直接ロードし実行したりすることができます。
Study Cにロードする Study Cにロードし編集する Study Cにロードし実行する
Study C無料利用についての詳細は、このページを参照してください。



"..."形式のデータを作成するために、前回のExcelデータの次の行に下記の3個のデータを追加します。
1番目   "
2番目   ,
3番目   ",
データに','が存在するとCSV形式の区切り文字である','と区別がつかなくなってしまいます。 そのため','が含まれる項目は"..."の形式で囲まれます。 ','同様'"'も特殊な文字のためデータに'"'が含まれる場合は特殊な扱いになります。 '"'が含まれる項目も"..."の形式になりデータの'"'は'""'と2文字に変換されます。 上記のデータは次のように変換されます。
        データ          "..."で囲む             データの'"'は'""'に変換
1番目   "               """                     """"
2番目   ,               ","                     ","
3番目   ",              "","                    ""","
結局Excelで出力したCSVファイルは次のようになります。
1,2,3
11,12,13
21,22,23
"""",",",""","
今回は上記のようなデータにも対応できるようにGetCSVItem関数を修正します。
(1)項目の先頭文字が'"'かどうかで処理を分けます(dq_flagを1にセットします)。
(2)dq_flagが1の場合は','ではなく'"'を終了条件とします。
(3)dq_flagが1の場合は'"'が2個連続する場合は終了とせず1個の'"'データとして取り扱います。
#include <stdio.h>

#define MAX_ITEM_SIZE   100
#define MAX_LINE_SIZE   1024

char    *GetCSVItem(char *wp, char *buff, int size);

void    main(int argc, char *argv[])
{
        FILE    *fp;
        char    buff[MAX_LINE_SIZE], *wp, item[3][MAX_ITEM_SIZE];
        int     i1, len;

        if(argc != 2){
                printf("コマンドの入力形式が間違っています.\n");
                return;
        }

        fp = fopen(argv[1], "r");
        if(fp == NULL){
                printf("ファイルがオープンできません[%s].\n", argv[1]);
                return;
        }
        for(;;){
                if(fgets(buff, MAX_LINE_SIZE, fp) == NULL)
                        break;
                len = strlen(buff);
                if(len == 0 || buff[len-1] != '\n'){
                        if(feof(fp) == 0){
                                printf("データが不正です[%s].\n", buff);
                                return;
                        }
                }
                buff[len-1] = '\0';
                wp = buff;

                if((wp = GetCSVItem(wp, item[0], MAX_ITEM_SIZE)) == NULL){
                        printf("エラー(1)\n");
                        break;
                }
                if((wp = GetCSVItem(wp, item[1], MAX_ITEM_SIZE)) == NULL){
                        printf("エラー(2)\n");
                        break;
                }
                if((wp = GetCSVItem(wp, item[2], MAX_ITEM_SIZE)) == NULL){
                        printf("エラー(3)\n");
                        break;
                }
                if(*wp != '\0'){
                        printf("エラー(4)\n");
                        break;
                }
                for(i1 = 0; i1 < 3; i1++){
                        printf("%d:%s\n", i1+1, item[i1]);
                }
        }
        fclose(fp);
}


char    *GetCSVItem(char *wp, char *buff, int size)
{
        int     i1, dq_flag;

        dq_flag = 0;
        buff[0] = '\0';
        while(*wp == ' ' || *wp == '\t')
                wp++;
        if(*wp == '\0'){
                return(NULL);
        }
        if(*wp == '"'){
                dq_flag = 1;
                wp++;
        }
        for(i1 = 0; i1 < MAX_ITEM_SIZE; i1++, wp++){
                if(i1 >= size)
                        return(NULL);
                buff[i1] = *wp;
                if(*wp == '\0'){
                        buff[i1] = '\0';
                        return(wp);
                }
                if(dq_flag == 1){
                        if(*wp == '"'){
                                if(*(wp+1) == '"'){
                                        wp++;
                                }
                                else{
                                        wp++;
                                        while(*wp == ' ' || *wp == '\t')
                                                wp++;
                                        if(*wp != ','){
                                                buff[i1] = '\0';
                                                if(*wp == '\0')
                                                        return(wp);
                                                return(NULL);
                                        }
                                        wp++;
                                        buff[i1] = '\0';
                                        break;
                                }
                        }
                }
                if(dq_flag == 0 && *wp == ','){
                        wp++;
                        buff[i1] = '\0';
                        break;
                }
        }
        return(wp);
}
Study Cにロードする Study Cにロードし編集する ブラウザとの連携機能が使用可能なStudy Cのバージョンなどについて... 「run csvdata1.csv」のように実行する必要があるので実行ボタンはありません


[an error occurred while processing this directive]