ファイル

[C言語] CSVファイルを読み込んで2次元配列に格納する方法を詳しく解説

C言語でCSVファイルを読み込み、2次元配列に格納する方法について解説します。

まず、ファイルを開くためにfopen関数を使用し、読み込みモードでCSVファイルを開きます。

次に、fgets関数を用いてファイルから1行ずつデータを読み込みます。

読み込んだ行をstrtok関数でカンマ区切りに分割し、各要素を2次元配列に格納します。

最後に、ファイルを閉じるためにfclose関数を使用します。

この方法を用いることで、CSVデータを効率的に処理することが可能です。

CSVファイルの読み込み手順

CSVファイルをC言語で読み込む際の基本的な手順を解説します。

CSVファイルは、カンマで区切られたデータを持つテキストファイルで、データの保存や交換に広く利用されています。

以下の手順に従って、CSVファイルを2次元配列に格納する方法を学びましょう。

ファイルのオープンと確認

CSVファイルを読み込むためには、まずファイルを開く必要があります。

C言語では、fopen関数を使用してファイルを開きます。

ファイルが正常に開けたかどうかを確認することも重要です。

#include <stdio.h>
int main() {
    FILE *file = fopen("data.csv", "r"); // CSVファイルを読み込みモードで開く
    if (file == NULL) {
        printf("ファイルを開けませんでした。\n");
        return 1; // エラーコードを返す
    }
    // ファイルが正常に開けた場合の処理
    fclose(file); // ファイルを閉じる
    return 0;
}

上記のコードでは、fopen関数を使用して”data.csv”というファイルを読み込みモードで開いています。

ファイルが開けない場合は、エラーメッセージを表示し、プログラムを終了します。

1行ずつデータを読み込む方法

ファイルを開いた後は、fgets関数を使用して1行ずつデータを読み込みます。

fgetsは、指定したバッファに1行分のデータを読み込む関数です。

#include <stdio.h>
int main() {
    FILE *file = fopen("data.csv", "r");
    char buffer[1024]; // 1行分のデータを格納するバッファ
    if (file == NULL) {
        printf("ファイルを開けませんでした。\n");
        return 1;
    }
    while (fgets(buffer, sizeof(buffer), file)) {
        printf("%s", buffer); // 読み込んだ行を表示
    }
    fclose(file);
    return 0;
}

このコードでは、fgetsを使ってファイルから1行ずつデータを読み込み、読み込んだ行をそのまま表示しています。

データをトークンに分割する

読み込んだ1行のデータをカンマで区切られたトークンに分割するには、strtok関数を使用します。

strtokは、指定した区切り文字で文字列を分割する関数です。

#include <stdio.h>
#include <string.h>
int main() {
    FILE *file = fopen("data.csv", "r");
    char buffer[1024];
    if (file == NULL) {
        printf("ファイルを開けませんでした。\n");
        return 1;
    }
    while (fgets(buffer, sizeof(buffer), file)) {
        char *token = strtok(buffer, ","); // カンマで分割
        while (token != NULL) {
            printf("%s ", token); // 分割されたトークンを表示
            token = strtok(NULL, ",");
        }
        printf("\n");
    }
    fclose(file);
    return 0;
}

このコードでは、strtokを使って各行をカンマで分割し、各トークンを表示しています。

トークンを2次元配列に格納する

分割したトークンを2次元配列に格納することで、データをプログラム内で扱いやすくします。

以下の例では、固定サイズの2次元配列にトークンを格納しています。

#include <stdio.h>
#include <string.h>
#define MAX_ROWS 100
#define MAX_COLS 10
#define MAX_LEN  100
int main() {
    FILE *file = fopen("data.csv", "r");
    char buffer[1024];
    char data[MAX_ROWS][MAX_COLS][MAX_LEN]; // 2次元配列
    int row = 0;
    if (file == NULL) {
        printf("ファイルを開けませんでした。\n");
        return 1;
    }
    while (fgets(buffer, sizeof(buffer), file) && row < MAX_ROWS) {
        int col = 0;
        char *token = strtok(buffer, ",");
        while (token != NULL && col < MAX_COLS) {
            strncpy(data[row][col], token, MAX_LEN - 1); // トークンを配列に格納
            data[row][col][MAX_LEN - 1] = '\0'; // 文字列の終端を設定
            token = strtok(NULL, ",");
            col++;
        }
        row++;
    }
    fclose(file);
    // 配列の内容を表示
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < MAX_COLS; j++) {
            printf("%s ", data[i][j]);
        }
        printf("\n");
    }
    return 0;
}

このコードでは、dataという2次元配列に各トークンを格納しています。

strncpyを使用してトークンを配列にコピーし、文字列の終端を設定しています。

配列の内容を表示することで、CSVファイルのデータが正しく格納されていることを確認できます。

実装例:CSVファイルを2次元配列に格納する

ここでは、CSVファイルを2次元配列に格納する具体的な実装例を紹介します。

サンプルCSVファイルを用意し、コードの全体構造を理解した上で、各関数の詳細を解説します。

サンプルCSVファイルの準備

まずは、サンプルとして使用するCSVファイルを用意します。

このファイルは、簡単なデータを含むものとします。

名前,年齢,職業
山田太郎,30,エンジニア
鈴木花子,25,デザイナー
佐藤次郎,40,マネージャー

このCSVファイルを”sample.csv”という名前で保存します。

コードの全体構造

次に、CSVファイルを読み込み、2次元配列に格納するプログラムの全体構造を示します。

このプログラムは、ファイルのオープン、行の読み込み、トークンの分割、配列への格納という4つの主要な機能を持つ関数で構成されています。

#include <stdio.h>
#include <string.h>
#define MAX_ROWS 100
#define MAX_COLS 10
#define MAX_LEN  100
void openFile(FILE **file, const char *filename);
void readLine(FILE *file, char *buffer, size_t size);
void splitTokens(char *buffer, char tokens[MAX_COLS][MAX_LEN]);
void storeInArray(char tokens[MAX_COLS][MAX_LEN], char data[MAX_ROWS][MAX_COLS][MAX_LEN], int row);
int main() {
    FILE *file;
    char buffer[1024];
    char data[MAX_ROWS][MAX_COLS][MAX_LEN];
    int row = 0;
    openFile(&file, "sample.csv");
    while (fgets(buffer, sizeof(buffer), file) && row < MAX_ROWS) {
        char tokens[MAX_COLS][MAX_LEN];
        splitTokens(buffer, tokens);
        storeInArray(tokens, data, row);
        row++;
    }
    fclose(file);
    // 配列の内容を表示
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < MAX_COLS; j++) {
            printf("%s ", data[i][j]);
        }
        printf("\n");
    }
    return 0;
}

各関数の詳細解説

ファイルオープン関数

ファイルを開くための関数です。

fopenを使用してファイルを開き、ポインタを返します。

void openFile(FILE **file, const char *filename) {
    *file = fopen(filename, "r");
    if (*file == NULL) {
        printf("ファイルを開けませんでした。\n");
        exit(1);
    }
}

行読み込み関数

ファイルから1行を読み込む関数です。

fgetsを使用してバッファにデータを格納します。

void readLine(FILE *file, char *buffer, size_t size) {
    if (fgets(buffer, size, file) == NULL) {
        printf("行を読み込めませんでした。\n");
        exit(1);
    }
}

トークン分割関数

読み込んだ行をカンマで分割し、トークンを配列に格納する関数です。

void splitTokens(char *buffer, char tokens[MAX_COLS][MAX_LEN]) {
    int col = 0;
    char *token = strtok(buffer, ",");
    while (token != NULL && col < MAX_COLS) {
        strncpy(tokens[col], token, MAX_LEN - 1);
        tokens[col][MAX_LEN - 1] = '\0';
        token = strtok(NULL, ",");
        col++;
    }
}

配列格納関数

分割したトークンを2次元配列に格納する関数です。

void storeInArray(char tokens[MAX_COLS][MAX_LEN], char data[MAX_ROWS][MAX_COLS][MAX_LEN], int row) {
    for (int col = 0; col < MAX_COLS; col++) {
        strncpy(data[row][col], tokens[col], MAX_LEN - 1);
        data[row][col][MAX_LEN - 1] = '\0';
    }
}

完成したプログラム

上記の関数を組み合わせて、CSVファイルを2次元配列に格納するプログラムが完成しました。

このプログラムを実行すると、CSVファイルの内容が2次元配列に格納され、各行が表示されます。

名前 年齢 職業 
山田太郎 30 エンジニア 
鈴木花子 25 デザイナー 
佐藤次郎 40 マネージャー

この実行例では、CSVファイルの各行が2次元配列に格納され、正しく表示されていることが確認できます。

各関数が役割を分担しているため、コードの可読性と保守性が向上しています。

応用例

CSVファイルを2次元配列に格納する基本的な方法を学んだところで、次はそのデータを活用する応用例を紹介します。

ここでは、CSVデータのソート、フィルタリング、別の形式への変換について解説します。

CSVファイルのデータをソートする

CSVデータをソートすることで、特定の列に基づいてデータを並べ替えることができます。

例えば、年齢順にデータをソートする場合、以下のように実装します。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_ROWS 100
#define MAX_COLS 10
#define MAX_LEN  100
void sortData(char data[MAX_ROWS][MAX_COLS][MAX_LEN], int rows, int colIndex);
int main() {
    // 既にデータが2次元配列に格納されていると仮定
    char data[MAX_ROWS][MAX_COLS][MAX_LEN] = {
        {"名前", "年齢", "職業"},
        {"山田太郎", "30", "エンジニア"},
        {"鈴木花子", "25", "デザイナー"},
        {"佐藤次郎", "40", "マネージャー"}
    };
    int rows = 4; // データの行数
    sortData(data, rows, 1); // 年齢でソート
    // ソート後のデータを表示
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < MAX_COLS; j++) {
            printf("%s ", data[i][j]);
        }
        printf("\n");
    }
    return 0;
}
void sortData(char data[MAX_ROWS][MAX_COLS][MAX_LEN], int rows, int colIndex) {
    for (int i = 1; i < rows - 1; i++) {
        for (int j = i + 1; j < rows; j++) {
            if (atoi(data[i][colIndex]) > atoi(data[j][colIndex])) {
                char temp[MAX_COLS][MAX_LEN];
                memcpy(temp, data[i], sizeof(temp));
                memcpy(data[i], data[j], sizeof(temp));
                memcpy(data[j], temp, sizeof(temp));
            }
        }
    }
}

このコードでは、年齢の列(インデックス1)を基準にデータをソートしています。

atoi関数を使って文字列を整数に変換し、比較を行っています。

CSVファイルのデータをフィルタリングする

特定の条件に基づいてデータをフィルタリングすることも可能です。

例えば、職業が「エンジニア」のデータだけを抽出する場合、以下のように実装します。

#include <stdio.h>
#include <string.h>
#define MAX_ROWS 100
#define MAX_COLS 10
#define MAX_LEN  100
void filterData(char data[MAX_ROWS][MAX_COLS][MAX_LEN], int rows, const char *criteria, int colIndex);
int main() {
    char data[MAX_ROWS][MAX_COLS][MAX_LEN] = {
        {"名前", "年齢", "職業"},
        {"山田太郎", "30", "エンジニア"},
        {"鈴木花子", "25", "デザイナー"},
        {"佐藤次郎", "40", "マネージャー"}
    };
    int rows = 4;
    filterData(data, rows, "エンジニア", 2); // 職業がエンジニアのデータをフィルタリング
    return 0;
}
void filterData(char data[MAX_ROWS][MAX_COLS][MAX_LEN], int rows, const char *criteria, int colIndex) {
    for (int i = 0; i < rows; i++) {
        if (strcmp(data[i][colIndex], criteria) == 0) {
            for (int j = 0; j < MAX_COLS; j++) {
                printf("%s ", data[i][j]);
            }
            printf("\n");
        }
    }
}

このコードでは、職業の列(インデックス2)を基準に「エンジニア」のデータをフィルタリングし、該当する行を表示しています。

CSVファイルのデータを別の形式に変換する

CSVデータを別の形式に変換することで、他のアプリケーションやシステムで利用しやすくなります。

例えば、CSVデータをJSON形式に変換する場合、以下のように実装します。

#include <stdio.h>
#include <string.h>
#define MAX_ROWS 100
#define MAX_COLS 10
#define MAX_LEN  100
void convertToJSON(char data[MAX_ROWS][MAX_COLS][MAX_LEN], int rows);
int main() {
    char data[MAX_ROWS][MAX_COLS][MAX_LEN] = {
        {"名前", "年齢", "職業"},
        {"山田太郎", "30", "エンジニア"},
        {"鈴木花子", "25", "デザイナー"},
        {"佐藤次郎", "40", "マネージャー"}
    };
    int rows = 4;
    convertToJSON(data, rows);
    return 0;
}
void convertToJSON(char data[MAX_ROWS][MAX_COLS][MAX_LEN], int rows) {
    printf("[\n");
    for (int i = 1; i < rows; i++) {
        printf("  {\n");
        for (int j = 0; j < MAX_COLS; j++) {
            printf("    \"%s\": \"%s\"", data[0][j], data[i][j]);
            if (j < MAX_COLS - 1) printf(",");
            printf("\n");
        }
        printf("  }");
        if (i < rows - 1) printf(",");
        printf("\n");
    }
    printf("]\n");
}

このコードでは、CSVデータをJSON形式に変換し、各行をJSONオブジェクトとして出力しています。

JSON形式に変換することで、WebアプリケーションやAPIでの利用が容易になります。

まとめ

CSVファイルをC言語で読み込み、2次元配列に格納する方法を学びました。

振り返ると、ファイルのオープンからデータのトークン分割、配列への格納、さらにはデータのソートやフィルタリング、形式変換といった応用例までをカバーしました。

これらの知識を活用して、CSVデータを効率的に処理し、プログラムの機能を拡張してみてください。

関連記事

Back to top button
目次へ