<タブ区切りのテキスト形式>
二次元データをテキストファイルとして読み書きする際、「タブ区切り」形式にしておくと、エクセルなど他のソフトとデータをやり取りできるので便利です。また、タブではなくカンマ(,)で区切った形式はCSV(comma separated volume)形式といわれ、汎用のテキスト形式として近年定着してきています。
タブ区切りという名の通り、二次元配列の列要素間をタブで区切ります。行間は改行で区切ります。例えば二次元配列dt[N][M]であれば
dt[0][0]
<タブ> dt[0][1] <タブ> ... <タブ> dt[0][M-1] <改行>
dt[1][0]
<タブ> dt[1][1] <タブ> ... <タブ> dt[1][M-1] <改行>
...
dt[N-1][0]
<タブ> dt[N-1][1] <タブ> ... <タブ> dt[N-1][M-1] <改行>
となります。ただし、データの内容によっては行と列を逆にしたほうがよい場合もあります。
ファイルに書き出す時は、fprintf関数を使って、\tや\nで区切りながら書き込むだけです。
(例)
#include
<stdio.h>
#define
N 5
#define
M 4
int
main(void) {
int
dt[N][M]= {{0,0,0,0}, /* 2次元配列dtの宣言と初期化 */
{1,10,100,1000},
{2,20,200,2000},
{3,30,300,3000},
{4,40,400,4000}};
int
i, j;
char
filename[]="tabtest.txt"; /*
書き出し用ファイル名 */
FILE
*fp;
/*
データの書き出し */
fp
= fopen(filename, "w"); /*
書き出しモードでテキストファイルをオープン */
for
(i = 0; i < N; i++) { /*
行のループ */
for
(j = 0; j < M; j++) { /*
列のループ */
fprintf(fp,
"%d", dt[i][j]); /* 要素の値をファイルに書き出し */
if
(j == M-1) { /*
行末なら改行を書き込み */
fprintf(fp,
"\n");
}
else { /*
それ以外ならタブを書き込み */
fprintf(fp,
"\t");
}
}
}
fclose(fp); /* ファイルのクローズ */
return
0;
}
一方、読み込む場合ですが、任意のタブ区切りのファイルを読み込めるプログラムにするには、一行中の項目数やそのデータ型を判別しつつ読み込まなくてはならないので結構大変です。しかし、データ型と要素数の分かっている配列であれば、以下のように簡単に読み込めます。tabtest.txtには5×4の整数型の二次元配列がタブ区切りで書かれています。
(例)
#include
<stdio.h>
#define
N 5
#define
M 4
int
main(void) {
int
dt[N][M]; /*
データ読み込み用配列 */
int
i, j;
char
filename[]="tabtest.txt"; /*
読み込み用ファイル名 */
FILE
*fp;
/*
データの読み込み */
fp
= fopen(filename, "r"); /*
読み込みモードでテキストファイルをオープン */
for
(i = 0; i < N; i++) { /*
行のループ */
for
(j = 0; j < M; j++) { /*
列のループ */
fscanf(fp,
"%d", &dt[i][j]); /* データ1つ読み込み */
}
}
fclose(fp);
/*
データの表示 */
for
(i = 0; i < N; i++) {
for
(j = 0; j < M; j++) {
printf("%d\t",
dt[i][j]);
}
printf("\n");
}
return
0;
}
scanf関数と同様にfscanf関数は、\tや\nなどの空白文字を読み飛ばすので、
fscanf(fp,
"%d", &dt[i][j]);
を繰り返すだけで、数値だけを順番に値を読み込んでいくことができるわけです。