7. ファイルいままでは プログラムを実行したとき その結果を画面で確認していました 簡単なものならそれでもいいのですか 複雑な結果は画面で見るだけでなく ファイルに保存できればよいでしょう ここでは このファイルについて説明します 使う関数のプロトタイプは次のとおりです FILE *fopen(const char *filename, const char *mode); ファイルを読み書きできるようにする ( このことをオープンするという ) mode でわたす文字列の意味は次のとおり r 読み込み専用にオープン w 書き込み用に作成 その名前のファイルがすでに存在する場合は, 上書き a 追加 ファイルの最後で書き込み用にオープンするか, ファイルが存在しなければ書き込み用に作成 r+ 既存のファイルを更新 ( 読み込みと書き込み ) 用にオープン w+ 新しいファイルを更新 ( 読み込みと書き込み ) 用に作成 その名前のファイルがすでに存在する場合は, 上書き a+ 追加用にオープン ファイルの最後で更新用にオープンするか, ファイルが存在しなければ作成 int fclose(file *stream); ファイルを読み書きを終了する ( このことをクローズするという ) int fprintf(file *stream, const char *format[, argument,...]); ファイル stream に書き出す printf と同じ使い方 int fscanf(file *stream, const char *format[, address,...]); ファイル stream から読み込む scanf と同じ使い方 char *fgets(char *s, int n, FILE *stream); ファイル stream から文字列を改行まで もしくは n-1 文字 読み込む int feof(file *stream); ファイル stream の最後に到達しているかを調べる関数 ( 終わりに達していれば真 ) 基本的にはファイルをオープンする 読み書きする ファイルをクローズするの順序で行うことになります 46
ex47.c /* ファイルを用いた例 */ FILE *input; /* オープンした結果を保存するポインタ変数 */ char buffer[100]; /* ファイルから内容を読み込むための場所 */ input = fopen("f:ex47.c","r"); /* ex47.c を読み込み専用でオープン */ if(input == NULL) /* オープンに失敗したとき input は NULL になる */ printf("error! ex47.c not found n"); else for(i = 0; i < 5; i++) fgets(buffer, 100, input); /* 1 行ずつ読み込み */ printf("%d 行目 :%s", i + 1, buffer); /* 1 行ずつ表示 */ fclose(input); /* クローズ */ return (0); 実行すれば ex36.c の内容が最初の 5 行だけ出てくるでしょう すべての行を書き出すためには次のようにします ex48.c /* ファイルを用いた例 */ FILE *input; /* オープンした結果を保存するポインタ変数 */ int i = 0; char buffer[100]; /* ファイルから内容を読み込むための場所 */ input = fopen("f:ex47.c","r"); /* ex47.c を読み込み専用でオープン */ if(input == NULL) /* オープンに失敗したとき input は NULL になる */ printf("error! ex47.c not found n"); else fgets(buffer, 100, input); while(!feof(input)) /* ファイルの最後に到達してないとき繰り返し */ printf("%2d 行目 :%s", ++i, buffer); fgets(buffer, 100, input); fclose(input); /* クローズ */ return (0); 47
では次はファイルに書き出す例を行ってみましょう ex49.c /* 成績表 ( 一人分を書き出す ) */ #define IDLENGTH 7 /* 学籍番号の長さ */ #define NUMLESSON 3 /* 科目数 */ /* 成績管理用の構造体の定義 */ struct student char idnumber[idlength + 1]; /* 学籍番号 */ int point[numlesson]; /* 点数 (NUMLESSON 科目 ) */ double mean; ; void inputstudent(struct student *, int); void printstudent(struct student); int fprintstudent(char *, struct student); struct student a; inputstudent(&a, 1); printstudent(a); i = fprintstudent("f: bcc2 out.txt", a); return(i); /* 入力の関数 平均の計算も行う */ void inputstudent(struct student *x, int n) int i, sum = 0; printf("%d 人目 : n 学籍番号 : ", n); scanf("%7s", x->idnumber); for(i = 0; i < NUMLESSON; i++) printf(" 第 %d 科目 : ", i + 1); scanf("%d", &(x->point[i])); sum += x->point[i]; x->mean = (double)sum / NUMLESSON; 48
/* 表示用関数 */ void printstudent(struct student x) printf("%10s:", x.idnumber); for(i = 0; i < NUMLESSON; i++) printf("%4d", x.point[i]); printf(": %7.2f n", x.mean); /* ファイル出力関数 */ int fprintstudent(char *fname, struct student x) FILE *output; if((output = fopen(fname, "a")) == NULL) /* ファイルをオープンして output に代入し 失敗していたら */ printf("error! Can't Open n"); return (-1); fprintf(output, "%10s ", x.idnumber); for(i = 0; i < NUMLESSON; i++) fprintf(output, "%4d", x.point[i]); fprintf(output, " %6.2f n", x.mean); fclose(output); return(0); 実行してみたら マイコンピュータから out.txt を見てみましょう 画面と同じ物が表示されるでしょう ここでは追加用にオープンしていますから 1 度実行するたびごとに 1 行増えていきます 5 回以上実行して 5 行以上のデータを入力しておきましょう このデータを読み込み 処理するプログラムを作成します ex50.c /* 成績表 */ #define IDLENGTH 7 /* 学籍番号の長さ */ #define NUMLESSON 3 /* 科目数 */ #define MAX 20 /* 成績管理用の構造体の定義 */ struct student char idnumber[idlength + 1]; /* 学籍番号 */ int point[numlesson]; /* 点数 (NUMLESSON 科目 ) */ double mean; ; 49
int readstudent(char *, struct student *); void printstudent(struct student); void exchange(struct student *, struct student *); void sort(struct student *, int); struct student data[max]; int i, n; n = readstudent("f: bcc2 out.txt", data); sort(data, n); for(i = 0; i < n; i++) printstudent(data[i]); return(0); /* データの読み込み関数 */ int readstudent(char *fname, struct student *x) int i = 0, j; FILE *input; if((input = fopen(fname,"r")) == NULL) printf("error! Can't Open n"); return (-1); while(!feof(input)) fscanf(input,"%7s", x[i].idnumber); for(j = 0; j < NUMLESSON; j++) fscanf(input, "%d", &x[i].point[j]); fscanf(input, "%lf", &x[i].mean); i++; fclose(input); return(i); /* 表示用関数 */ void printstudent(struct student x) printf("%10s:", x.idnumber); for(i = 0; i < NUMLESSON; i++) printf("%4d", x.point[i]); printf(": %7.2f n", x.mean); 50
/* 値を交換する関数 */ void exchange(struct student *x, struct student *y) struct student t; t = *x; *x = *y; *y = t; /* 整列 ( バブルソート )*/ void sort(struct student *x, int size) int i, j; for(i = size - 1; i > 0; i--) for(j = 0; j < i; j++) if (x[j].mean > x[j + 1].mean) exchange(&x[j], &x[j + 1]); 問題 7.1 http://hakuto.mis.ous.ac.jp/~yanagi/aprog2006/ からデータをダウンロードしてください これはルイス キャロルの不思議の国のアリスの第 1 章である この文章の単語の中で 先頭のアルファベットで何が一番多いか調べなさい 問題 7.2 次のようなファイルがあります 岡山空港の月曜日の時刻表で 順に会社名 便名 出発時刻 到着 時刻 目的地のリストである ANA 652 730 840 Tokyo ANA 654 1000 1115 Tokyo ANA 656 1520 1630 Tokyo ANA 658 1725 1840 Tokyo ANA 660 1945 2100 Tokyo JAL 1680 730 830 Tokyo JAL 1682 1050 1205 Tokyo JAL 1684 1625 1740 Tokyo JAL 1688 1855 2010 Tokyo ANA 379 1210 1400 Sapporo JAC 3690 1040 1205 Kagoshima JAC 3694 1825 1950 Kagoshima JTA 011 920 1200 Okinawa KAL 762 945 1125 Soeul CES 528 1330 1440 Shanghai COA 920 1055 1535 Guam このファイルを読み込み 出発順に並び替えて出力するプログラムを作成しなさい ただし データは構造体を定義して使うこと 51