[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データを効率的に処理し、プログラムの機能を拡張してみてください。