C言語でデータ処理を行う際、Excelやデータベースから出力されたCSVファイル(カンマ区切りファイル)を読み込みたいという場面は頻繁に訪れます。
そのため、「ファイルを1行ずつ読み込む」「カンマで区切る」「数値に変換する」といった処理をすべて自分で実装する必要があります。
ここでつまずく初心者の方は非常に多いですが、一度パターンを覚えてしまえば、どのような形式のCSVでも自由自在に扱えるようになります。
この記事では、C言語でCSVファイルを読み込むための基本的な手順から、2次元配列や構造体への格納方法、さらに特定列の抽出テクニックまで、現在の開発環境でも通用する実装方法をサンプルコード付きで徹底解説します。
![]() 執筆者:マヒロ |
|
CSV読み込みの基本手順と必要な関数
C言語でCSVを読み込む処理は、大きく分けて以下の3ステップで構成されます。
fopenでファイルを開く。fgetsでファイルを「1行ずつ」読み込む。strtokまたはsscanfで、読み込んだ行を「カンマ」で分割する。
まずは、最も基本となる「文字列として読み込んで画面に表示する」プログラムを見てみましょう。
カンマ区切りで文字列を表示する基本コード
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_LINE_LENGTH 1024
int main(void) {
FILE *fp;
char line[MAX_LINE_LENGTH];
char *token;
// 読み込むCSVファイルを開く
fp = fopen("data.csv", "r");
if (fp == NULL) {
printf("ファイルを開けませんでした。\n");
return 1;
}
// 1行ずつ読み込む
while (fgets(line, MAX_LINE_LENGTH, fp) != NULL) {
// 改行文字を削除(任意)
line[strcspn(line, "\n")] = 0;
// カンマを区切り文字として最初のトークンを取得
token = strtok(line, ",");
// 行末までトークンを取得し続ける
while (token != NULL) {
printf("[%s] ", token);
token = strtok(NULL, ","); // 次のトークンへ
}
printf("\n"); // 1行読み終わったら改行
}
fclose(fp);
return 0;
}
実行結果(data.csvが “ID,Name,Score” の場合)
[ID] [Name] [Score]
[1] [Tanaka] [80]
[2] [Suzuki] [90]
fgets 関数は、ファイルから改行コードまで(または最大文字数まで)を1行として読み込み、バッファ(line 配列)に格納します。
その後、strtok 関数を使って、読み込んだ1行の文字列をカンマ , で分割(トークン化)しています。
strtok は少し特殊な関数で、2回目以降の呼び出しには NULL を指定することで、「さっきの続き」から分割を行ってくれます。
読み込んだデータを「配列」や「構造体」に格納する
単に表示するだけでなく、読み込んだデータをプログラム内で計算や並べ替えに使いたい場合は、変数に格納する必要があります。
ここでは、実務でよく使われる「構造体」への格納方法を紹介します。
構造体を使ってCSVデータを管理する
例えば、「ID(整数)」、「名前(文字列)」、「得点(実数)」というデータを持つCSVを読み込む場合を考えます。
セキュリティ上のリスク(バッファオーバーフロー)を避けるため、文字数制限付きで読み込むのが鉄則です。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE 1024
#define MAX_RECORDS 100
// データを格納する構造体
typedef struct {
int id;
char name[50];
double score;
} Student;
int main(void) {
FILE *fp;
char line[MAX_LINE];
Student students[MAX_RECORDS]; // 構造体の配列
int count = 0; // 読み込んだレコード数
fp = fopen("students.csv", "r");
if (fp == NULL) return 1;
// ヘッダー行(1行目)を読み飛ばす場合
// fgets(line, MAX_LINE, fp);
while (fgets(line, MAX_LINE, fp) != NULL) {
if (count >= MAX_RECORDS) break; // 配列の上限チェック
// sscanfを使ってカンマ区切りで型変換しながら読み込む
// %49[^,] は「カンマ以外の文字を最大49文字まで読み込む」という意味(ヌル文字分を考慮してサイズ-1)
sscanf(line, "%d,%49[^,],%lf", &students[count].id, students[count].name, &students[count].score);
count++;
}
fclose(fp);
// 格納結果の確認
for (int i = 0; i < count; i++) {
printf("ID:%d 名前:%s 得点:%.1f\n", students[i].id, students[i].name, students[i].score);
}
return 0;
}
実行結果
ID:1 名前:Tanaka 得点:80.5
ID:2 名前:Suzuki 得点:90.0
ID:3 名前:Sato 得点:75.2
ここでは strtok の代わりに sscanf 関数を使用しています。
sscanf は「文字列からフォーマットに従って値を読み取る」関数です。
重要なポイントは、文字列を読み込む際に %[^,] ではなく %49[^,] のように最大文字数を指定している点です。
配列サイズを超えて書き込まれるのを防ぐために、必ずバッファサイズより1小さい値を指定しましょう。
特定の列だけを読み込む・抽出する方法
巨大なCSVファイルから、「3列目のデータだけ欲しい」という場合もあります。
その場合は、strtok でトークンを数えながら読み進める方法が有効です。
指定した列(カラム)の値を取得する関数
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_LINE 1024
// 指定した列番号(0始まり)の文字列を取得する
void get_column(char *line, int col_index, char *result) {
char *token;
int current_col = 0;
// 行をコピーして破壊されないようにする(strtok用)
char temp_line[MAX_LINE];
strcpy(temp_line, line);
token = strtok(temp_line, ",");
while (token != NULL) {
if (current_col == col_index) {
strcpy(result, token); // 見つかったら結果にコピー
return;
}
token = strtok(NULL, ",");
current_col++;
}
strcpy(result, ""); // 見つからなかったら空文字
}
int main(void) {
char line[] = "101,Apple,150,Red"; // テスト用のCSV行
char value[100];
// 2列目(価格:150)を取得
get_column(line, 2, value);
printf("抽出した値: %s\n", value);
return 0;
}
実行結果
抽出した値: 150
get_column 関数を作成し、行データと欲しい列番号を渡すことで、その列の文字列だけを抽出できるようにしました。
strtok は元の文字列を書き換えてしまう(区切り文字をヌル文字にする)ため、strcpy で一時的なバッファにコピーしてから処理を行っている点がポイントです。
CSV読み込み時の注意点とトラブルシューティング
CSV読み込みはシンプルに見えますが、実務では「ダブルクォーテーションで囲まれたデータ」や「空のデータ」などでハマることがあります。
空フィールド(,,)の扱いに注意
strtok 関数は、連続する区切り文字を1つとみなす仕様があります。
そのため、1,,80 のようにデータが空(欠損)の場合、strtok は空欄をスキップしてしまい、データが左にずれるという問題が発生します。
空データが含まれる可能性があるCSVを扱う場合は、strtok を使わずに strchr などを使って自力でカンマを探すループ処理を書くか、strsep(非標準)の使用を検討してください。
ダブルクォーテーション " の扱い
Excelなどで出力したCSVは、データの中にカンマが含まれる場合、"Tanaka, Taro", 20 のようにダブルクォーテーションで囲まれます。
標準の strtok やシンプルな sscanf では、このダブルクォーテーション内のカンマも区切り文字として認識してしまい、正しく読み込めません。
これに対応するには、1文字ずつ解析して「引用符の中かどうか」を判定する自作のパーサー(解析ロジック)を組む必要があります。
改行コードの違い
Windowsで作成されたCSVは改行コードが \r\n ですが、Linuxなどでは \n です。
fgets は改行コードも含めて読み込むため、行末のデータ(最後の列)に \r が付着してしまい、数値変換や文字列比較がおかしくなることがあります。
読み込み直後に strcspn などで改行コードを除去する処理を入れるのが鉄則です。
C言語のスキルを活かして年収を上げる方法
以上、C言語でCSVファイルを読み込む方法について解説してきました。
なお、C言語のスキルがある場合には、「転職して年収をアップさせる」「副業で稼ぐ」といった方法を検討するのがおすすめです。
C言語を扱えるエンジニアは比較的希少価値が高く、転職によって数十万円の年収アップはザラで、100万円以上年収が上がることも珍しくありません。
なお、転職によって年収を上げたい場合は、エンジニア専門の転職エージェントサービスを利用するのが最適です。
併せて、副業案件を獲得できるエージェントにも登録しておくと、空いている時間を活かして稼げるようなC言語の案件を探しやすくなります。
転職エージェントも副業エージェントも、登録・利用は完全無料なので、どんな求人や副業案件があるのか気になる方は、気軽に利用してみるとよいでしょう。



