Document

第14章
14.1
14.2
14.3
14.4
14.5
14.6
14.7
ファイル操作
ファイルへの書き込み
ファイルからの読み込み
ファイルへの追加書き込み
ファイル名の指定
複数のファイルの同時オープン
ファイルの構造
その他のファイル入出力関数
14.0 はじめに
これまでのプログラミングの学習では、
入力データは


プログラム中で設定
キーボードから入力
結果は画面に表示
データを入力してください。 3 8
和は 11
いわば、その場限りの処理だった…
14.0 はじめに
一般的なプログラミングでは、
入力データは



Excel等のアプリケーションで作成
画像や音声ファイル
キーボードから入力
プログラム中で
ファイルの操作が必要
結果は別の
ファイルに
保存
今日のポイント
ファイルへのデータの書き込み
FILE *fp;
fp=fopen("ファイル名", "w");
fprintf(fp, "書式指定子", 書き込む変数);
fclose(fp);
ファイルからのデータの読み込み
FILE *fp;
fp=fopen("ファイル名", "r");
fscanf(fp, "書式指定子", &読み込む変数);
fclose(fp);
14.1 ファイルへの書き込み
プログラム例 14.1.1
#include <stdio.h>
int main(void)
{
double a, b, sum;
FILE *fp;
1. ファイルポインタの宣言
 FILE 型のポインタ変数 fp
a = 2.345; b = 5.678;
sum = a + b;
fp = fopen("foo.txt", "w");
fprintf(fp, "%f, %f, %f¥n", a, b, sum);
fclose(fp);
return 0;
}
14.1 ファイルへの書き込み
プログラム例 14.1.1
#include <stdio.h>
int main(void)
{
2. ファイルを開く
double a, b, sum;
 foo.txt はファイル名
FILE *fp;
 w は書き込みのファイルモード
a = 2.345; b = 5.678;
sum = a + b;
fp = fopen("foo.txt", "w");
fprintf(fp, "%f, %f, %f¥n", a, b, sum);
fclose(fp);
ファイル識別子を txt にしておくとダブル
return 0;
クリックによりメモ帳で開くことができる
}
14.1 ファイルへの書き込み
プログラム例 14.1.1
#include <stdio.h>
int main(void)
{
double a, b, sum;
FILE *fp;
a = 2.345; b = 5.678;
sum = a + b;
fp = fopen("foo.txt", "w");
fprintf(fp, "%f, %f, %f¥n", a, b, sum);
fclose(fp);
3. ファイルにデータを書き込む
return 0;
 fp で書き込むファイル(foo.txt)を指定
 あとは printf と同じ
}
14.1 ファイルへの書き込み
プログラム例 14.1.1
#include <stdio.h>
実行後に例14.1.1 のフォルダ内に
foo.txt ができていることを確認する
int main(void)
{
double a, b, sum;
FILE *fp;
a = 2.345; b = 5.678;
sum = a + b;
fp = fopen("foo.txt", "w");
fprintf(fp, "%f, %f, %f¥n", a, b, sum);
fclose(fp);
return 0;
必ず閉じること!
4. ファイルを閉じる
}
14.2 ファイルからの読み込み
プログラム例 14.2.1
1. ファイルポインタの宣言
#include <stdio.h>
 FILE 型のポインタ変数 fp
int main(void)
{
2. ファイルを開く
 foo.txt はファイル名
double a, b, sum;
 r は読み込みのファイルモード
FILE *fp;
fp=fopen("foo.txt", "r");
fscanf(fp, "%lf, %lf, %lf¥n", &a, &b, &sum);
printf("a=%f, b=%f, sum=%f¥n", a, b, sum);
fclose(fp);
return 0;
}
実行前に例14.1.1 でできた foo.txt を 例14.2.1 のフォルダにコピーしておく
14.2 ファイルからの読み込み
プログラム例 14.2.1
#include <stdio.h>
int main(void)
3. ファイルからデータを読み込む
{
double a, b, sum;  fp で読み込むファイル(foo.txt)を指定
 あとは scanf と同じ
FILE *fp;
fp=fopen("foo.txt", "r");
fscanf(fp, "%lf, %lf, %lf¥n", &a, &b, &sum);
printf("a=%f, b=%f, sum=%f¥n", a, b, sum);
fclose(fp);
return 0;
}
実行前に例14.1.1 でできた foo.txt を 例14.2.1 のフォルダにコピーしておく
14.2 ファイルからの読み込み
プログラム例 14.2.1
#include <stdio.h>
int main(void)
{
double a, b, sum;
FILE *fp;
fp=fopen("foo.txt", "r");
fscanf(fp, "%lf, %lf, %lf¥n", &a, &b, &sum);
printf("a=%f, b=%f, sum=%f¥n", a, b, sum);
fclose(fp);
4. ファイルを閉じる
必ず閉じること!
return 0;
}
実行前に例14.1.1 でできた foo.txt を 例14.2.1 のフォルダにコピーしておく
14.3 ファイルへのデータの追加
プログラム例 14.3.1
実行前に例14.1.1 でできた foo.txt を
例14.3.1 のフォルダにコピーしておく
#include <stdio.h>
int main(void)
既存のファイルにデータを書き込む
{
 fp で書き込むファイル(foo.txt)を指定
double a, b, sum;  "a" なら foo.txt の EOF から書き込む
モード(a は append の意)
FILE *fp;
a = 1.134; b = 2.567;
sum = a + b;
fp=fopen("foo.txt", "a");
fprintf(fp, "%f, %f, %f¥n", a, b, sum);
fclose(fp);
実行後に例14.3.1 のフォルダにある
return 0;
foo.txt の追加内容を確認
}
14.4 ファイル名を指定
プログラム例 14.4.1
#include <stdio.h>
実行前に例14.1.1 でできた foo.txt を
int main(void)
例14.4.1 のフォルダにコピーしておく
{
double a, b, sum;
char rfile[15];
FILE *fp;
printf("データの保存されたファイルの名前を入力して下さい.");
gets(rfile);
文字列 rfile にファイル名を読み込む
fp=fopen(rfile, "r");
fscanf(fp, "%lf, %lf, %lf", &a, &b, &sum);
printf("a=%f, b=%f, sum=%f¥n", a, b, sum);
fclose(fp);
return 0;
実行時には foo.txt を入力
}
14.4 ファイル名の確認
プログラム例 14.4.2
ファイルポインタ fp が NULL でない.
#include <stdio.h>
(baz.dat というファイルが存在する)なら真
int main(void)
→ ファイルからデータを読み込む部分に進む.
{
double a, b, sum;
!= は「等しくない」という関係演算子(p.182)
FILE *fp;
if ((fp = fopen("baz.dat", "r")) != NULL) {
fscanf(fp, "%lf, %lf, %lf¥n", &a, &b, &sum);
printf("a=%f, b=%f, sum=%f¥n", a, b, sum);
fclose(fp);
}
else printf("ファイルが存在しません.\n");
return 0;
}
ファイル読み書きに良く使う文なので、マスターしよう
14.4 ファイル名の確認の詳細
fopen("baz.dat", "r")
baz.dat が同じフォルダに存在する → baz.dat へのポインタ
baz.dat が同じフォルダに存在しない → NULL
fp=fopen("baz.dat", "r")
ファイルポインタ fp に fopen 関数の値(baz.dat へのポインタか NULL)を代入
(fp=fopen("baz.dat", "r")) != NULL
fp が NULL と等しくない時 → 真(1)
NULL の時
→ 偽(0)
if ((fp=fopen("baz.dat", "r")) != NULL)
もし、ポインタ変数 fp が NULL でない(=baz.dat というファイルが存在)なら真
→ ファイルからデータを読み込む部分に進む
14.4 ファイル終端の検出
プログラム例 14.4.3
#include <stdio.h>
fscanf 関数の値が EOF と等しくない(= fp が
int main(void)
指すファイルの終端でない)間は、{ } を繰り返す
{
double x[100], y[100];
実行前に例14.4.3 のフォルダに p.135 の
int i;
最下段のデータをメモ帳で作成し、
FILE *fp;
foo.txt という名前で保存
fp = fopen("foo.txt", "r");
i = 0;
while (fscanf(fp, "%lf, %lf", &x[i], &y[i]) != EOF) {
printf("%f, %f\n", x[i], y[i]);
i++;
}
fclose(fp);
printf("ファイル中のデータ (x, y) の数は %d 組です.\n", i);
return 0;
}
14.4 ファイル終端の検出の詳細
fscanf(fp, "%lf, %lf", &x[i], &y[i])
fp が指すファイルにデータがある場合
→ データを読み込んで配列 x, y に代入する
fp が指すファイルにこれ以上のデータがない
(ファイル終端)、または何らかのエラーの場合
→ EOF
while (fscanf(fp, "%lf, %lf", &x[i], &y[i]) != EOF) {
…
}
fscanf 関数の値が EOF と等しくない(fp が指すファイルの終端でない)間は、
{…} を繰り返す。
14.5 複数のファイルを同時に開く
プログラム例 14.5.1
実行前に例14.4.3 で作成した foo.txt を
例14.5.1 のフォルダにコピーしておく
#include <stdio.h>
int main(void)
読み込むファイル、
{
書き込むファイルを
FILE *ifp, *ofp;
指すポインタ
double a, b, sum;
ifp = fopen("foo.txt", "r");
ofp = fopen("bar.txt", "w");
while (fscanf(ifp, "%lf, %lf", &a, &b) != EOF) {
sum = a + b;
fprintf(ofp, "%f, %f, %f¥n", a, b, sum);
}
両方とも閉じる
fclose(ofp); fclose(ifp);
return 0;
実行後に例14.5.1 のフォルダに
}
bar.txt ができていることを確認する
14.6 ファイルの構造
実際には、以下の例のような構造を持つファイルが多い
学籍番号
氏名
科目1の得点
科目2の得点
科目3の得点
1001
Arai Satoshi
90
70
5
1005
Inoue Makoto
65
85
75
1013
Kawada Keiko
77
89
97
1件分をレコードという
各項目をフィールドという
このようなファイルを「シーケンシャルアクセスファイル」という
興味のある人は 第16章 構造体 を自習してください.
「データ構造とアルゴリズム」や「演習II」で本格的に取り組むはず.
14.7 その他のファイル入出力関数




プログラム例 14.7.1 はファイル間のコピー
ファイルコピーは OS上(Windowsならエクスプ
ローラ)でファイルを複製するほうが実際的
主な入出力関数は p.185 に掲載
興味のある人は、いろいろ試してみよう
演習問題14.1(レポートの準備)
1.
y = 2x2 + 3 (-10≦ x ≦10) を刻み幅 1 で計算し、x, y の組を
1行ごとにファイル(data1.txt)に書き込むプログラム
(q14_1.c) を作成せよ。(プログラム例 14.1.1 参照)
2. コンパイル・実行して Z:\nyumon2 フォルダ内に data1.txt
ができているか、エクスプローラで確認せよ
3. アイコンをダブルクリックしてデータを確認せよ
-10.000000, 203.00000
-9.000000, 165.00000
-8.000000, 131.00000
-7.000000, 101.00000
・
・
・
・
・
・
こんなファイルをつくる
演習問題14.1のヒント
#include <stdio.h>
int main(void)
{
int i; double x, y;
FILE *fp;
fp=fopen("data1.txt", "w");
for (i = -10; i <= 10; i++) {
i を用いた x の式
x を用いた y の式
fprintf(fp, "%f, %f\n", x, y);
}
fclose(fp);
return 0;
}
スキルアップタイム1(レポート課題)
以下の機能を持つプログラム(q14_s1.c)を作成せよ
1. 演習14.1 で作ったファイルdata1.txt を開く
2. data1.txt から x と y を読み取ってディスプレイに表示
する(p.136, および例14.4.3参照)





x と y は double型の配列とする
プログラム例14.2.1 を参考に
21組なのでループが必要
簡単なのは for文
デキる人はプログラム例14.4.3 を参考に while文で
スキルアップタイム1のヒント1
#include <stdio.h>
#define N 21
int main(void)
{
double x[N], y[N];
int i;
FILE *fp;
fp=fopen("data1.txt", "r");
for (i = 0; i < N; i++) {
}
}
fclose(fp);
return 0;


ファイルからデータを読み込む文
ディスプレイに表示する文
スキルアップタイム1のヒント2
#include <stdio.h>
#define N 101
int main(void)
{
ファイルからデータを読み込み、
double x[N], y[N];
EOF でないかをチェックする式
int i;
FILE *fp;
fp=fopen("data1.txt", "r");
i = 0;
while (
) {
i++;
}
}
fclose(fp);
return 0;
ディスプレイに表示する文
スキルアップタイム2(レポート課題)
スキアップタイム1 で作成したプログラムに以下の
機能を追加し、進化させる(q14_s2.c)
1. プログラム中で z = x3 - 75x を計算する

z はdouble型の配列とする
x, y, z を新しいファイル data2.csv に書き込む
2.

データの間はコンマで区切る
データの間をコンマで区切り、ファイルの識別子を csv に
しておくと、ダブルクリックにより Excel で開くことができる
スキルアップタイム2のヒント1
#include <stdio.h>
#define N 21
int main(void)
{
double x[N], y[N], z[N];
int i;
FILE *ifp, *ofp;
ifp=fopen("data1.txt", "r");
ofp=fopen("data2.csv", "w");
for (i = 0; i < N; i++) {
ファイルからデータを読み込む文
 ディスプレイに表示する文
 z[i]を計算する文
 x[i],y[i],z[i]をファイルに
書き込む文

}
}
fclose(ifp); fclose(ofp);
return 0;
スキルアップタイム2のヒント2
#include <stdio.h>
#define N 101
int main(void)
{
double x[N], y[N], z[N];
int i;
FILE *ifp, *ofp;
ifp=fopen("data1.txt", "r");
ofp=fopen("data2.csv", "w");
i = 0;
while (
) {
i++;
}
}
fclose(ifp); fclose(ofp);
return 0;
ファイルからデータを読み込み、
EOF でないかをチェックする式



ディスプレイに表示する文
z[i]を計算する文
x[i],y[i],z[i]をファイル
に書き込む文
スキルアップタイム3(レポート課題)
1. データファイル data2.csv を Excelで開く(ダブル
クリックでOK)
2. 横軸 x、縦軸を y
(および z )とし、
散布図を
2
y = 2x + 3
用いること
z = x3 - 75x
のグラフを作成する
3. data2.xls に保存する
スキルアップタイム4
スキルアップタイム3 までできた人は、
演習問題14.5 からできるところまで.
プログラミング入門II
第3回レポート(必須)
課題:本日のスキルアップタイム 1と2と3
提出期限:2011年1月21日12:50
提出場所:ネットワーク実験室(1)の入口近くの箱
今回のレポートでは以下の項目をいれること.
表紙は不要
1. 学籍番号、氏名
2. 問題番号
レポートのファイルは
3. ソースリスト
保存しておくこと
4. 実行結果とグラフ
5. 感想(5行以上書く)
本日のパズル
次のプログラムは何を出力するか
#include <stdio.h>
int i=0;
void workover(int i)
{
i = (i%i) * ((i*i)/(2*i) + 4);
printf("%d\n",i);
}
int reset(int i)
{
if (i <= 2) i = 5; else i = 0;
return i;
}
main()
{
int i=5;
reset( i/2 ); printf("%d\n",i);
reset( i=i/2 ); printf("%d\n",i);
i = reset( i/2 ); printf("%d\n",i);
workover(i);
printf("%d\n",i);
}
1
2
3
4
5