C言語でテキストファイルに書き込まれているデータを読み込むプログラムの例をいくつか記述しておきます。
fscanf()関数を使うと楽に記述できるケースもありますが、思い通りに fscanf() が動作してくれないことがありますので、ファイルから1行ずつ文字列配列 char line[] に読み込んでから、データに変換するという手順で実装しています。
atoi() とatof() 関数
"123", "1.234" のように文字列として読み込んだデータはatoi(), atof()関数によりint型、double型に変換することができます。
なお、文字列の先頭に " 123" のようにスペースが入っていても、あるいは "1.234kcal/mol" のように後ろに余分な文字が入っていてもatoi(), atof()は動作してくれます。
int dat_i = atoi("123"); double dat_d = atof("1.234"); int dat_i2 = atoi(" 123"); // 文字列先頭にスペースがあってもOK double dat_d2 = atof(" 1.234kcal/mol"); // 数字データの後ろに別の文字があってもOK int dat_i3 = atoi("a 123"); // 先頭が数字でない文字なので 0 が代入される double dat_d3 = atof("kcal/mol 1.234"); // 先頭が数字でない文字なので 0.0 が代入される
1行に1つのデータが記述されているテキストファイルを読み込む
一番シンプルに1行に1つのデータが記述されている以下のようなファイル
52.321 1.523 -5.891
を読むプログラムを示します。
#include <stdio.h> #include <stdlib.h> #define LINE_LENGTH_MAX 256 // 1行の長さの上限 #define DAT_NUM_MAX 128 // データ数の上限 int main(int argc, _TCHAR* argv[]) { FILE *fp; char line[LINE_LENGTH_MAX]; double values[DAT_NUM_MAX]; int n; // テキストファイルを読み込み用に開く if(!(fp = fopen("C:/work/input.txt", "r"))){ // ファイルオープンに失敗 return 1; } n = 0; // ファイルから1行ずつ line に読み込む // データを読み終えたら while 文から抜ける while(fgets(line, LINE_LENGTH_MAX, fp)) { // atofにより文字列 "12.345" から double型に変換する values[n] = atof(line); n++; } // 配列 values[0 - (n-1)] に読み込まれたデータが保存されている // 読み込んだデータ数 n fclose(fp); return 0; }
1行に複数のデータがコンマ区切りで記述されているテキストファイル(.csvファイル)を読み込む
1行に複数のデータ(1行当たりのデータ数は任意)がコンマ区切りで記述されている以下のようなファイル
52.321,1.234,5.325,-124.234 1.523,199.239 -5.891,806.125,61.235,-15.238 -538.352
を読むプログラムを示します。
#include <stdio.h> #include <stdlib.h> #include <string.h> #define LINE_LENGTH_MAX 256 // 1行の長さの上限 #define DAT_NUM_MAX 128 // データ数の上限 int main(int argc, _TCHAR* argv[]) { FILE *fp; char line[LINE_LENGTH_MAX]; double values[DAT_NUM_MAX]; int n; // テキストファイルを読み込み用に開く if(!(fp = fopen("C:/work/input.txt", "r"))){ // ファイルオープンに失敗 return 1; } n = 0; // ファイルから1行ずつ line に読み込む // データを読み終えたら while 文から抜ける while(fgets(line, LINE_LENGTH_MAX, fp)) { char *ch = line; // char line[] 用の文字列ポインタ、最初は line[] の先頭を示す // "->52.321,1.234,5.325,-124.234" (->がchの示す位置) while(-1){ // 1行から複数データを取得するための無限ループ if(*ch == '\n') // 行末だったら while(-1)から抜ける break; // atofにより文字列 "12.345" から double型に変換する values[n] = atof(ch); n++; if(!(ch = strchr(ch, ','))) // "->52.321,1.234,5.325,-124.234" から "52.321->,1.234,5.325,-124.234" break; // ','が見つからない場合は行末なので while(-1) の無限ループを抜ける ch++; // ポインタ ch を',' の次に移動 // "52.321->,1.234,5.325,-124.234" から "52.321,->1.234,5.325,-124.234" } } // 配列 values[0 - (n-1)] に読み込まれたデータが保存されている // 読み込んだデータ数 n fclose(fp); return 0; }
複雑なフォーマットのデータファイルから特定の項目を読み込む
以下のような複雑なファイル(Gaussian03出力ファイル)からある項目の数値「 E(UB+HF-LYP) = xxxxx.xxxxxxx 」(複数回出現する)を読み込むプログラムを示します。
・・・ Gap= 0.081 Goal= None Shift= 0.000 RMSDP=8.53D-09 MaxDP=8.49D-07 DE=-3.55D-11 OVMax= 1.10D-06 SCF Done: E(UB+HF-LYP) = -1841.49580923 A.U. after 25 cycles Convg = 0.8535D-08 -V/T = 2.0826 S**2 = 2.0044 KE= 1.700992279018D+03 PE=-1.295249248986D+04 EE= 5.110287762944D+03 Annihilation of the first spin contaminant: S**2 before annihilation 2.0044, after ・・・ Gap= 0.082 Goal= None Shift= 0.000 RMSDP=7.16D-09 MaxDP=7.08D-07 DE=-1.36D-11 OVMax= 1.03D-06 SCF Done: E(UB+HF-LYP) = -1841.60229698 A.U. after 16 cycles Convg = 0.7165D-08 -V/T = 2.0830 S**2 = 2.0044 KE= 1.700433072720D+03 PE=-1.293752712536D+04 EE= 5.103154386887D+03 Annihilation of the first spin contaminant: ・・・
#include <stdio.h> #include <stdlib.h> #include <string.h> #define LINE_LENGTH_MAX 256 // 1行の長さの上限 #define DAT_NUM_MAX 128 // データ数の上限 int main(int argc, _TCHAR* argv[]) { FILE *fp; char line[LINE_LENGTH_MAX]; double values[DAT_NUM_MAX]; int n; // テキストファイルを読み込み用に開く if(!(fp = fopen("C:/work/input.txt", "r"))){ // ファイルオープンに失敗 return 1; } n = 0; // ファイルから1行ずつ line に読み込む // データを読み終えたら while 文から抜ける while(fgets(line, LINE_LENGTH_MAX, fp)) { if(!strstr(line, "E(UB+HF-LYP)")) // 文字列 "E(UB+HF-LYP)" が行内に含まれなければ continue; // 次の行にスキップ char *ch = line; // char line[] 用の文字列ポインタ、最初は line[] の先頭を示す // "-> SCF Done: E(UB+HF-LYP) = -1841.49580923 A.U. after 25 cycles" (->がchの示す位置) ch = strchr(line, '=') + 1; // ch を '=' の次の位置に移動 // "-> SCF Done: E(UB+HF-LYP) = -1841.49580923 A.U. after 25 cycles" // から " SCF Done: E(UB+HF-LYP) =-> -1841.49580923 A.U. after 25 cycles" // atofにより文字列 " -1841.49580923" から double型に変換する values[n] = atof(ch); n++; } // 配列 values[0 - (n-1)] に読み込まれたデータが保存されている // 読み込んだデータ数 n fclose(fp); return 0; }
- 作者: 林晴比古
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2004/02
- メディア: 単行本
- 購入: 3人 クリック: 61回
- この商品を含むブログ (39件) を見る