ファイル

[C言語] CSVを読み込んで2行目からデータを取得する方法を解説

C言語でCSVファイルを読み込み、2行目以降のデータを取得する方法について解説します。

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

次に、fgets関数を用いて1行目をスキップし、2行目以降のデータを取得します。

取得したデータは、strtok関数を使ってカンマ区切りで分割し、各要素を処理します。

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

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

CSVファイルをC言語で読み込む際には、いくつかの基本的な手順を踏む必要があります。

ここでは、ファイルのオープンからデータの解析までの流れを解説します。

ファイルのオープン方法

CSVファイルを読み込むためには、まずファイルをオープンする必要があります。

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

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

このコードでは、data.csvというファイルを読み込みモードで開いています。

ファイルが存在しない場合や開けない場合には、エラーメッセージを表示します。

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

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

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

このコードは、data.csvの内容を1行ずつ読み込み、コンソールに表示します。

fgetsは、ファイルの終わりに達するとNULLを返します。

デリミタ(区切り文字)の処理

CSVファイルでは、カンマ,がデリミタとして使用されます。

strtok関数を使って、行をカンマで分割します。

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

このコードは、各行をカンマで分割し、各要素を表示します。

文字列の分割と解析

分割された文字列を解析することで、必要なデータを取得できます。

例えば、数値データを取得する場合は、atoiatof関数を使用します。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
    FILE *file = fopen("data.csv", "r");
    if (file == NULL) {
        printf("ファイルを開けませんでした。\n");
        return 1;
    }
    char line[1024];
    while (fgets(line, sizeof(line), file)) {
        char *token = strtok(line, ",");
        while (token != NULL) {
            // 文字列を数値に変換して表示
            int number = atoi(token);
            printf("%d\n", number);
            token = strtok(NULL, ",");
        }
    }
    fclose(file);
    return 0;
}

このコードは、CSVファイルの各要素を整数に変換して表示します。

atoi関数は文字列を整数に変換するために使用されます。

2行目からデータを取得する方法

CSVファイルを読み込む際に、1行目はヘッダー情報として扱われることが多く、2行目以降から実際のデータを取得することが一般的です。

ここでは、1行目をスキップして2行目からデータを取得する方法を解説します。

1行目をスキップする方法

1行目をスキップするためには、最初にfgets関数を1回呼び出して、1行目を読み込んで無視します。

#include <stdio.h>
int main() {
    FILE *file = fopen("data.csv", "r");
    if (file == NULL) {
        printf("ファイルを開けませんでした。\n");
        return 1;
    }
    char line[1024];
    // 1行目を読み込んでスキップ
    fgets(line, sizeof(line), file);
    // ここから2行目以降の処理を行う
    while (fgets(line, sizeof(line), file)) {
        printf("%s", line);
    }
    fclose(file);
    return 0;
}

このコードでは、最初のfgetsで1行目を読み込んでいますが、その内容は使用せずに次の行から処理を開始します。

ループを使った行の読み込み

2行目以降のデータを取得するためには、fgetsを使ってループで行を読み込みます。

ループはファイルの終わりに達するまで続けます。

#include <stdio.h>
int main() {
    FILE *file = fopen("data.csv", "r");
    if (file == NULL) {
        printf("ファイルを開けませんでした。\n");
        return 1;
    }
    char line[1024];
    fgets(line, sizeof(line), file); // 1行目をスキップ
    // 2行目以降を読み込むループ
    while (fgets(line, sizeof(line), file)) {
        printf("%s", line);
    }
    fclose(file);
    return 0;
}

このループでは、fgetsNULLを返すまで、つまりファイルの終わりに達するまで行を読み込み続けます。

2行目以降のデータの処理

2行目以降のデータを処理する際には、前述のデリミタ処理や文字列解析を行います。

以下の例では、2行目以降のデータをカンマで分割し、各要素を表示します。

#include <stdio.h>
#include <string.h>
int main() {
    FILE *file = fopen("data.csv", "r");
    if (file == NULL) {
        printf("ファイルを開けませんでした。\n");
        return 1;
    }
    char line[1024];
    fgets(line, sizeof(line), file); // 1行目をスキップ
    // 2行目以降のデータを処理
    while (fgets(line, sizeof(line), file)) {
        char *token = strtok(line, ",");
        while (token != NULL) {
            printf("%s\n", token);
            token = strtok(NULL, ",");
        }
    }
    fclose(file);
    return 0;
}

このコードは、2行目以降の各行をカンマで分割し、各要素を表示します。

strtok関数を使って、デリミタであるカンマを基に文字列を分割しています。

エラーハンドリング

CSVファイルを読み込む際には、さまざまなエラーが発生する可能性があります。

ここでは、ファイルが存在しない場合や読み込みエラー、データ形式が不正な場合の対処方法について解説します。

ファイルが存在しない場合の対処

ファイルが存在しない場合、fopen関数NULLを返します。

この場合、適切なエラーメッセージを表示し、プログラムを終了させることが重要です。

#include <stdio.h>
int main() {
    FILE *file = fopen("data.csv", "r");
    if (file == NULL) {
        // ファイルが存在しない場合のエラーメッセージ
        printf("エラー: ファイルが見つかりません。\n");
        return 1;
    }
    // ファイルが正常に開けた場合の処理
    fclose(file);
    return 0;
}

このコードは、ファイルが存在しない場合にエラーメッセージを表示し、プログラムを終了します。

読み込みエラーの処理

ファイルの読み込み中にエラーが発生することがあります。

fgets関数NULLを返した場合、エラーが発生した可能性があります。

エラーの原因を特定するために、ferror関数を使用します。

#include <stdio.h>
int main() {
    FILE *file = fopen("data.csv", "r");
    if (file == NULL) {
        printf("エラー: ファイルが見つかりません。\n");
        return 1;
    }
    char line[1024];
    while (fgets(line, sizeof(line), file)) {
        // 読み込んだ行を処理
    }
    if (ferror(file)) {
        // 読み込みエラーが発生した場合の処理
        printf("エラー: ファイルの読み込み中に問題が発生しました。\n");
    }
    fclose(file);
    return 0;
}

このコードは、ファイルの読み込み中にエラーが発生した場合にエラーメッセージを表示します。

データ形式が不正な場合の対応

CSVファイルのデータ形式が不正な場合、プログラムが期待通りに動作しないことがあります。

データ形式のチェックを行い、問題がある場合には適切な処理を行います。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
    FILE *file = fopen("data.csv", "r");
    if (file == NULL) {
        printf("エラー: ファイルが見つかりません。\n");
        return 1;
    }
    char line[1024];
    fgets(line, sizeof(line), file); // 1行目をスキップ
    while (fgets(line, sizeof(line), file)) {
        char *token = strtok(line, ",");
        while (token != NULL) {
            // 文字列を数値に変換
            char *endptr;
            int number = strtol(token, &endptr, 10);
            if (*endptr != '\0' && *endptr != '\n') {
                // データ形式が不正な場合の処理
                printf("エラー: 不正なデータ形式が検出されました: %s\n", token);
            } else {
                printf("%d\n", number);
            }
            token = strtok(NULL, ",");
        }
    }
    fclose(file);
    return 0;
}

このコードは、各トークンを整数に変換し、変換に失敗した場合にはエラーメッセージを表示します。

strtol関数を使用して、変換の成否を確認しています。

応用例

CSVファイルの基本的な読み込み方法を理解したら、次はそのデータを活用する応用例を考えてみましょう。

ここでは、複数行のデータを配列に格納する方法、特定の列のデータを抽出する方法、そしてCSVデータを構造体にマッピングする方法を紹介します。

複数行のデータを配列に格納する

CSVファイルのデータを配列に格納することで、後でデータを簡単に操作することができます。

以下の例では、各行のデータを2次元配列に格納します。

#include <stdio.h>
#include <string.h>
#define MAX_ROWS 100
#define MAX_COLS 10
#define MAX_LINE_LENGTH 1024
int main() {
    FILE *file = fopen("data.csv", "r");
    if (file == NULL) {
        printf("エラー: ファイルが見つかりません。\n");
        return 1;
    }
    char data[MAX_ROWS][MAX_COLS][MAX_LINE_LENGTH];
    char line[MAX_LINE_LENGTH];
    int row = 0;
    fgets(line, sizeof(line), file); // 1行目をスキップ
    while (fgets(line, sizeof(line), file) && row < MAX_ROWS) {
        int col = 0;
        char *token = strtok(line, ",");
        while (token != NULL && col < MAX_COLS) {
            strcpy(data[row][col], token);
            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;
}

このコードは、CSVファイルのデータを2次元配列に格納し、後でそのデータを表示します。

特定の列のデータを抽出する

特定の列のデータを抽出することで、必要な情報だけを効率的に取得できます。

以下の例では、2列目のデータを抽出して表示します。

#include <stdio.h>
#include <string.h>
int main() {
    FILE *file = fopen("data.csv", "r");
    if (file == NULL) {
        printf("エラー: ファイルが見つかりません。\n");
        return 1;
    }
    char line[1024];
    fgets(line, sizeof(line), file); // 1行目をスキップ
    while (fgets(line, sizeof(line), file)) {
        char *token = strtok(line, ",");
        int col = 0;
        while (token != NULL) {
            if (col == 1) { // 2列目のデータを抽出
                printf("%s\n", token);
            }
            token = strtok(NULL, ",");
            col++;
        }
    }
    fclose(file);
    return 0;
}

このコードは、CSVファイルの2列目のデータを抽出して表示します。

CSVデータを構造体にマッピングする

CSVデータを構造体にマッピングすることで、データをより直感的に扱うことができます。

以下の例では、CSVデータを構造体に格納します。

#include <stdio.h>
#include <string.h>
#define MAX_ENTRIES 100
typedef struct {
    char name[50];
    int age;
    float salary;
} Employee;
int main() {
    FILE *file = fopen("data.csv", "r");
    if (file == NULL) {
        printf("エラー: ファイルが見つかりません。\n");
        return 1;
    }
    Employee employees[MAX_ENTRIES];
    char line[1024];
    int index = 0;
    fgets(line, sizeof(line), file); // 1行目をスキップ
    while (fgets(line, sizeof(line), file) && index < MAX_ENTRIES) {
        char *token = strtok(line, ",");
        strcpy(employees[index].name, token);
        token = strtok(NULL, ",");
        employees[index].age = atoi(token);
        token = strtok(NULL, ",");
        employees[index].salary = atof(token);
        index++;
    }
    fclose(file);
    // 構造体に格納されたデータを表示
    for (int i = 0; i < index; i++) {
        printf("名前: %s, 年齢: %d, 給与: %.2f\n", employees[i].name, employees[i].age, employees[i].salary);
    }
    return 0;
}

このコードは、CSVファイルのデータをEmployee構造体に格納し、各エントリを表示します。

構造体を使用することで、データの各フィールドに簡単にアクセスできます。

まとめ

CSVファイルをC言語で扱う際の基本的な手順と応用例、エラーハンドリングについて学びました。

これにより、CSVファイルの読み込みやデータ処理の基礎を理解し、実際のプログラムに応用できるようになります。

この記事を参考に、CSVファイルを効率的に扱うプログラムを作成し、データ処理のスキルを向上させましょう。

関連記事

Back to top button