ファイルへの出力(読み込み)

コンピュータ基礎実験 第13回
コンピュータープログラミング
(C言語)(10)
1.ファイル入出力
ファイル入出力
C言語では、ファイルにデータを出力したり、ファ
イルからデータを入力する機能があります。
この機能を使うと、画面への出力(printf関数)や
キーボードからの入力(scanf関数)とよく似たや
り方でファイル入出力が可能です。
ファイルに出力
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
ファイル用変数(ファイルポインタ)の
宣言
ファイルをオープン
}
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
ファイルへの書き込み
ファイルをクローズ
if((f = fopen(”test.txt”,”w”))==NULL){
printf(”オープン失敗\n”);
exit(1);
}
fprintf(f, ”Hello world!\n”);
fclose(f);
return 0;
return 0;
}
ファイルから入力
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
ファイル用変数(ファイルポインタ)の
宣言
ファイルをオープン
ファイルから読み込み
ファイルをクローズ
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
int i;
if((f = fopen(”test.txt”,”r”))==NULL){
printf(”オープン失敗\n”);
exit(1);
}
fscanf(f, ”%d”,&i);
fclose(f);
return 0;
}
return 0;
}
ファイルオープン時のモード
「fopen(”test.txt”,”w”)」: ”w”部分の文字によって
ファイルオープンのモードが決定
文字
モード
備考
”r”
読み込みモード
read
”w”
書き込みモード
write, 新しく上書きされる
”a”
追加書き込みモード
”r+”
読み書き両用モード
”w+”
読み書き両用モード
オープン時に内容がクリア
”a+”
読み書き両用モード
書き込みは必ず末尾
append, 末尾に追加書き込み
両用モードは混乱の元なので上級者になってから
[例題 ex13-1]
次の例を実行せよ.
 このプログラムを実
行すると,同じフォ
ルダ(ディレクトリ)
内に
kekka.txt
というデータファイル
が作られる
(注) この例は
0から N までの和を
求めるプログラム
/* --- データの書き込み ex13-1.c --- */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
printf("start ... \n");
if((f=fopen("kekka.txt","w"))==NULL){
printf(“オープン失敗\n");
exit(1);
}
/* --- ここから計算例 --- */
int i=0, sum=0;
do{
sum =sum+i;
i++;
fprintf(f,"%d %d\n",i-1,sum);
}while(i<=20);
/* --- ここまで計算例 --- */
fclose(f);
printf("finished \n");
return 0;
}
6
データの書き込み
■ 次のex13-1.cは,結果をファイル“kekka.txt”に出力(書き込み)した例.
/* File 書き込み ex13-1.c */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
printf(”start \n");
If((f=fopen("kekka.txt","w")
==NULL){
printf(“オープン失敗\n");
exit(1);
}
1)
2)
3)
4)
/* --- ここから計算例 --- */
int i=0, sum=0;
do{
sum = sum+i; i++;
fprintf(f,“%d %d\n”,i-1,sum);
}while(i<=20);
/* --- ここまで計算例 --- */
あくまで
一例
fclose(f);
printf("finished \n"); return 0;
}
ファイルポインターという、ファイルを指定するための変数「f」を宣言する  FILE *f
fopen関数による指定  fopen(ファイル名, “w”) …ここで wはファイルへの書き込み
ファイルが開けなかったら exit(1) としてプログラムを終了させる
fprintf(f, …)でデータを書き込む  終わったらfclose(f)としてファイルを閉じる
データ リスト
Ex13-1.cの実行結果:
ファイル"kekka.txt”
0 0
1 1
2 3
3 6
4 10
5 15
6 21
7 28
……..
15
16
17
18
19
20
120
136
153
171
190
210
(注1) 関数 exit
exit(status); のように使う
ここでstatusは整数
異常がなければ 0
異常があると 0 以外の値
(注2) 関数 fprintf
fprintf(f, 書式制御文字列,出力変数)
のように使う
f以外は printf と同様
[例題 ex13-2]
次の例を実行せよ.
 このプログラムを
実行すると,同じ
フォルダ(ディレ
クトリ)内にある
kekka.txt
というファイルから
データが読み込まれ
る
/* --- データの読み込み ex13-2.c --- */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
int i,x[100],y[100];
if((f=fopen("kekka.txt","r"))== NULL){
printf("オープン失敗\n");
exit(1);
}
for(i=0;i<=20;i++){
fscanf(f,"%d %d",&x[i],&y[i]);
printf("%d, %d \n", x[i], y[i]);
}
fclose(f);
return 0;
}
9
データの読み込み
/* File 読み込み */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f;
int i, …;
■ 次の例は,ファイル"kekka.txt"から
データの入力(読み込みを)している.
読み込み用のファイル (ここではkekka.txt )を開き,
そのファイルをファイルポインタfで管理する.
If((f=fopen("kekka.txt","r"))== NULL){
printf(“オープン失敗\n");
exit(1);
}
for(i=0;i<=20;i++){
fscanf(f,"%d, %d",&x[i],&y[i]);
printf("%d, %d \n", x[i], y[i]);
}
fclose(f);
return 0;
}
戻り値がエラー(NULL)なら,
次のメッセージを出力してプログラム
を終了
条件を満たす限り
データ取り込みの操作を繰り返す
10
[課題 ex13-3] 実数(float)を、0から0.01刻みで6.28になる
まで増加させ、その結果をファイル名「data1.txt」の
ファイルに出力せよ
→「ex13-3.c」
(ヒント) float x; で実数の変数を用意し、「for文」や「while文」を
用いて繰り返し計算する。
「data1.txt」のファイル名で、書き込みモードでファイルをオー
プンし、「fprintf()」で結果を書き込む
最後に、ファイルをクローズするのを忘れないこと
float型は7桁の精度なので、0.01を加えるごとに誤差が積算
される。この誤差はこの問題では無視してよいです。
11
複数ファイルの同時使用
複数のファイルを同時にオープンして、同時に
使用することができます
どのファイルから読み込み、どのファイルに書き
込むかは、ファイルポインタで指定します
FILE *f1, *f2; /* ファイルポインタを2個用意 */
if((f1=fopen(”kekka1.txt”,”r”)==NULL){‥‥} /* f1をオープン */
if((f2=fopen(”kekka2.txt”,”w”)==NULL){‥‥} /* f2をオープン */
fscanf(f1,”%d”,&a); /* f1(ファイル名kekka1.txt)から読み込み */
fprintf(f2,”%d\n”,b); /* f2(ファイル名kekka2.txt)に書き込み */
fclose(f1); /* f1をクローズ */
fclose(f2); /* f2をクローズ */
[例題 ex13-4]
次の例を実行せよ.
(ex13-4.c)
 このプログラムを実行すると
「kekka.txt」というファイルから
データが読み込まれ、yが偶数
なら「kekka1.txt」に、奇数な
ら「kekka2.txt」に書き込まれ
る
/*--複数ファイルの読み書き ex13-3.c*/
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f1, *f2, *f3;
int i,x[100],y[100];
if((f1=fopen("kekka.txt","r"))== NULL){
printf("オープン失敗\n");
exit(1);}
if((f2=fopen("kekka1.txt", "w"))== NULL){
printf("オープン失敗\n");
exit(1);}
if((f3=fopen("kekka2.txt","w"))== NULL){
printf("オープン失敗\n");
exit(1);}
for(i=0;i<=20;i++){
fscanf(f1,"%d %d",&x[i],&y[i]);
if(y[i]%2==0){
fprintf(f2,"%d %d\n",x[i] , y[i] );
}
else{
fprintf(f3,"%d %d\n",x[i] , y[i] );
}
}
fclose(f1); fclose(f2); fclose(f3);
return 0;
}
13
[課題 ex13-5] 課題ex13-3で作成した「data1.txt」から実
数xを読み込み、xに対するsin関数の値sin(x)を計算せよ。
計算結果をファイル名「data2.txt」のファイルに出力せ
よ。ファイルには、「xの値 sin(x)の値」の順にスペース
を挟んで出力せよ。結果のファイルをエクセルで読み込
み、グラフとして表示せよ
→「ex13-5.c」
(ヒント) ファイルポインタを2個用意し、読み込みモード、書き
込みモードでそれぞれオープンする
「data1.txt」のデータ数は629個あるので、「for文」や「while文」
で629回繰り返す*
最後に、ファイルをクローズするのを忘れないこと
*上級者向け: データ数が未定の場合、ループ回数を固定する
ことができない。この場合「C EOF」のキーワードでWEB検索して
みよ。
14
[課題 ex13-6] WEBからファイルdata10.txtをダウンロード
(http://www.tuat.ac.jp/~muroo/computer-ex/data10.txt)し、data10.txtからN
個のデータを読み込み,それらの平均値と標準偏差を計算せよ.その際,
取り込むデータの数Nが
(1) N=10, (2) N=100, (3) N=200, (4) N=400
(5) N=800, (6) N=1200 (7)N=2400
のそれぞれについて計算し,比較せよ.また,N=2400の場合について,
data10.txtをExcelで読み込み平均[=AVERAGE(A1:A…)]と標準偏差
[=STDEV(A1:A…)]
を計算し比較せよ.→ex13-6.c
(注) n個のデータの平均値,標準偏差はそれぞれ
n
1
x = å xi
n i=1
n
s=
2
(x
x
)
å i
i =1
n -1
n
=
2
2
x
nx
åi
i =1
n -1
と定義される.
15
[発展課題 ex13-7] data10.txtを読み込み,それらのデー
タのヒストグラムを計算せよ.
その際,取り込むデータの数Nが
(1) N=10, (2) N=50, (3) N=200, (4) N=2400
のそれぞれについて計算し,比較せよ.
計算した結果について、エクセルでヒストグラムを作成
せよ.→ex13-7.c
(工学基礎実験参照)
(ヒント) このデータxは0から19の間の整数で2400個ある。
 そこで,ヒストグラムを作るにあたり,h[20]のような整
数の配列データを用意し,読み込んだデータがxのとき
h[x]=h[x]+1; (h[x]++;でもよい)
のように加算すれば,最終的にh[0], h[1], … にxnew の出現頻
度が格納される.(h[20]の初期化を忘れないこと)
16
☞ ヒストグラムの例
N=10
N=50
3.5
14
3
12
2.5
10
2
8
Series1
1.5
1
Series1
6
4
0.5
2
0
0
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
N=200
N=2400
45
600
40
500
35
400
30
25
Series1
20
300
Series1
200
15
10
100
5
0
0
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
17
[発展課題 ex13-8] 区間[0,2π]で, 関数
(1) y1 = sin x
1
(2) y2 = sin x + sin(2x)
2
1
1
(3) y3 = sin x + sin(2x) + sin(3x)
2
3
を計算し,グラフに重ね書きをして示せ.
18
実習結果のレポート
• 3つのソースファイル「ex13-3.c」、「ex13-5.c」、
「ex13-6.c」を添付ファイルにしてメールを送っ
てください。
• 宛先: [email protected]
• 件名:コンピューター基礎実験13
• 本文:感想および一言
19