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