[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;
}
このコードは、各行をカンマで分割し、各要素を表示します。
文字列の分割と解析
分割された文字列を解析することで、必要なデータを取得できます。
例えば、数値データを取得する場合は、atoi
やatof関数
を使用します。
#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;
}
このループでは、fgets
がNULL
を返すまで、つまりファイルの終わりに達するまで行を読み込み続けます。
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ファイルを効率的に扱うプログラムを作成し、データ処理のスキルを向上させましょう。