第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
© Copyright 2024 ExpyDoc