掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板2

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.26054

CSVファイルからのデータ読込み
投稿者---雲(2006/02/09 20:52:46)


CSVファイルからデータを読込み、構造体に展開する際にstrtok()などを使用して、
データを一つ一つ格納しているのですが、ソースが冗長になってしまいます。
ループなどを使用して上手くコーディングする方法はないものでしょうか?

例えば、

名前,年齢,身長,体重,住所,TEL,

の並びであるCSVファイルのデータを

struct Data {
 char name[12];
 int age;
 int sincyo;
 int taijyu;
 char address[32];
 char tel[16];
};

という構造体に格納する際、

 struct Data data;
 strcpy(data.name, strtok(buf, ",")); // bufはCSVファイル1レコードを格納
 data.age = atoi(strtok(NULL, ","));
 data.sincyo = atoi(strtok(NULL, ","));
 data.taijyu = atoi(strtok(NULL, ","));
 strcpy(data.address, strtok(NULL, ","));
 strcpy(data.tel, strtok(NULL, ","));

などと書いているのですが、展開するデータの種類(カラム数)が多くなると、とても冗長に感じます。
実際に私が作成したあるプログラムではstrtok()で代入するくだりが50行近くになってしまっています。
ループなどですっきり書く方法をご存知でしたら是非教えてください。

宜しくお願い致します。

環境は UNIX C です。コンパイラはちょっと分かりません。



この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:CSVファイルからのデータ読込み 26056 2006/02/09 21:25:42


No.26056

Re:CSVファイルからのデータ読込み
投稿者---雲(2006/02/09 21:25:42)


実際にサンプルソースを書いてみました。
以下のコメント部分をもっとスマートにしたいのですが、何か方法はないでしょうか。

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

#define MAX_REC  128
#define MAX_DATA    256

struct Data {
    char name[12];
    int age;
    int sincyo;
    int taijyu;
    char address[32];
    char tel[16];
};

int main(void)
{
    int i, num;
    char rbuf[MAX_DATA], buf[MAX_DATA];
    FILE *fp;
    struct Data data[MAX_REC];

    fp = fopen("data.csv", "r");
    if (fp == NULL) {
        printf("ファイル開けません\n");
        return -1;
    }
    num = 0;
    memset(data, 0x00, sizeof(data));
    while (NULL != fgets(rbuf, sizeof(rbuf), fp)) {
        strcpy(buf, rbuf);
        /* ↓↓この部分をもっとスマートにしたい↓↓ */
        strcpy(data[num].name, strtok(buf, ","));
        data[num].age = atoi(strtok(NULL, ","));
        data[num].sincyo = atoi(strtok(NULL, ","));
        data[num].taijyu = atoi(strtok(NULL, ","));
        strcpy(data[num].address, strtok(NULL, ","));
        strcpy(data[num].tel, strtok(NULL, ","));
        /* ↑↑この部分をもっとスマートにしたい↑↑ */
        num++;
    }
    fclose(fp);

    for (i = 0; i < num; i++) {
        printf("%3d:%12s %3d %3d %3d %32s %16s\n", i+1,
            data[i].name, data[i].age, data[i].sincyo,
            data[i].taijyu, data[i].address, data[i].tel);
    }

    return 0;
}

/*** 実行結果 ***/
1: 名前 01 10 110 11 住所01 111-1111-1111
2: 名前 02 20 120 22 住所02 222-2222-2222
3: 名前 03 30 130 33 住所03 333-3333-3333
4: 名前 04 40 140 44 住所04 444-4444-4444
5: 名前 05 50 150 55 住所05 555-5555-5555
6: 名前 06 60 160 66 住所06 666-6666-6666
7: 名前 07 70 170 77 住所07 777-7777-7777
8: 名前 08 80 180 88 住所08 888-8888-8888
9: 名前 09 90 190 99 住所09 999-9999-9999
10: 名前 10 100 200 111 住所10 000-0000-0000



この投稿にコメントする

削除パスワード

No.26057

Re:CSVファイルからのデータ読込み
投稿者---かずま(2006/02/09 23:24:13)


> 以下のコメント部分をもっとスマートにしたいのですが、何か方法はないでしょうか。

sscanf を使ってみてはいかがでしょうか?
#include <stdio.h>
#include <stdlib.h>

#define MAX_REC     128
#define MAX_DATA    256

struct Data {
    char name[12];
    int  age;
    int  height;
    int  weight;
    char address[32];
    char tel[16];
};

int main(void)
{
    int i, num;  char buf[MAX_DATA];
    struct Data data[MAX_REC], *p;

    FILE *fp = fopen("data.csv", "r");
    if (fp == NULL) printf("ファイル開けません\n"), exit(1);
    for (p = data; fgets(buf, sizeof(buf), fp); p++)
        if (sscanf(buf, "%11[^,],%d,%d,%d,%31[^,],%15s", p->name,
                &p->age, &p->height, &p->weight, p->address, p->tel) != 6)
            puts("bad data"), exit(1);
    fclose(fp);

    num = p - data;
    for (i = 0; i < num; i++)
        printf("%3d:%12s %3d %3d %3d %32s %16s\n", i+1,
            data[i].name, data[i].age, data[i].height,
            data[i].weight, data[i].address, data[i].tel);
    return 0;
}



この投稿にコメントする

削除パスワード

No.26097

Re:CSVファイルからのデータ読込み
投稿者---雲(2006/02/13 18:56:55)


かずま様

>sscanf を使ってみてはいかがでしょうか?

回答ありがとうございます。
sscanf を組込んで正しく結果を得ることを確認しました。

sscanfの書式指定の書き方("%11[^,],%d,%d,%d,%31[^,],%15s")がちょっと理解できませんでしたが、
(特にこの部分→%11[^,] / %31[^,])
printf/scanf の書式指定はいろいろなことができそうなので、勉強してみます。

ありがとうございました。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧