「C言語/ファイル入出力」の版間の差分

削除された内容 追加された内容
628 行
 
=== fgetsによる方法 ===
==== 簡単な例 ====
さきほどの章では、説明の都合上、fscanfを使ったが、じつは、fscanfでCSVファイルを作るのは、あまり実用的ではない。
 
662 ⟶ 663行目:
strtok(NULL,"区切り文字にしたい文字")
</source>
にすると、前の文字の続きから次ぎの区切り文字まで(その行に残りの区切り文字がない場合には行末まで)を読み込む。
 
 
757 ⟶ 758行目:
上記のように、たしかに、読み取った文字列を分解している。
 
 
==== 実際の例 ====
 
さきほどの例では、背つめいの単純化のため、たったの各行あたり、要素数はたった2個だった。
 
しかし、実際の場合は、もっと要素数が多い。
 
たとえば、
<pre>
名前,番号,国語の得点,数学の得点
山田,1,80,90
佐藤,2,70,100
</pre>
のように、各行あたり4個のデータを読み込む場合を考えよう。
 
 
;コード例
<source lang=c>
#include <stdio.h>
#include <stdlib.h> // 「続行するには何かキーを押してください . . .」を表示するのに必要。
#include <string.h>
 
#pragma warning(disable:4996)
 
int main()
{
FILE* fp1;
fp1 = fopen("sanpuru.csv", "r");
 
if ((fp1 = fopen("sanpuru.csv", "r")) == NULL) { // ここを読み取りモード"r"にするのを忘れないように
printf("ファイルを開けませんでした。\n");
system("pause");// 「続行するには何かキーを押してください . . .」の待機命令
return 1;
}
else {
printf("ファイルをオープンしました。\n");
printf("\n");
}
 
 
char buffer1[150];
printf("文字列を読み取っています。\n");
 
struct seisekihyou {
char str[150];
};
struct seisekihyou row[20]; // 構造体配列の宣言
 
 
for (int line = 1; line <= 2; line = line + 1) {
fgets(buffer1, 150, fp1);
 
printf("%d行目の文字列\n",line);
printf("%s", buffer1);
 
 
strncpy(row[0].str, strtok(buffer1, ","), 150); // str1 = strtok(buffer1,","); では代入できない。
 
printf("row[%d].strとして読み取った文字列\n", 0);
printf("%s\n", row[0].str);
 
 
for (int temp = 1; temp <= 3; ++temp) {
strncpy(row[temp].str, strtok(NULL, ","), 150);
 
printf("row[%d].strとして読み取った文字列\n", temp);
printf("%s\n", row[temp].str);
}
printf("\n");
}
 
 
fclose(fp1);
 
printf("ファイルをクローズしました。\n");
 
return 0;
}
</source>
 
 
;実行例
<pre>
ファイルをオープンしました。
 
文字列を読み取っています。
1行目の文字列
名前,番号,国語の得点,数学の得点
row[0].strとして読み取った文字列
名前
row[1].strとして読み取った文字列
番号
row[2].strとして読み取った文字列
国語の得点
row[3].strとして読み取った文字列
数学の得点
 
 
2行目の文字列
山田,1,80,90
row[0].strとして読み取った文字列
山田
row[1].strとして読み取った文字列
1
row[2].strとして読み取った文字列
80
row[3].strとして読み取った文字列
90
 
 
ファイルをクローズしました。
 
このウィンドウを閉じるには、任意のキーを押してください...
</pre>
 
;解説
前の節では、単純化のために配列や構造体やfor文は用いなかったが、実務では用いたほうがイイだろう。
 
 
各行の最初の項目だけ <code>strncpy(row[0].str, strtok(buffer1, ","), 150);</code> のようにstrtokの第一引数を指定する必要がある。
 
 
いっぽう、<code>strncpy(row[temp].str, strtok(NULL, ","), 150);</code> のように第一引数がnullなら、前の区切り文字から次の区切り文字までを抜き取るだけなので、2番目の項目からはfor文で使いまわしができる。
 
== 応用例 ==