2. ファイル処理 2.1 ファイル処理の基本いままでは プログラムを実行したとき 入力はキーボードから入れていました また その結果を画面で確認していました 簡単なものならそれでもいいのですが 複雑な入力はファイルから読み込んだり 結果は画面で見るだけでなくファイルに保存できればよいでしょう ここでは ファイル処理について説明します 使う関数のプロトタイプは次のとおりです 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 の最後に到達しているかを調べる関数 ( 終わりに達していれば真 ) 基本的には ファイルをオープンする 読み書きする ファイルをクローズする の順序で行う ことになります 24
ex19.c /* ファイルを用いた例 */ int i; input = fopen("ex19.c","r"); /* ex19.c を読み込み専用でオープン */ /* オープンに失敗したとき input は NULL になる */ printf("error! ex19.c not found. n"); for(i = 0; i < 5; i++) { fgets(buffer, 100, input); /* 1 行ずつ読み込み */ printf("%d 行目 :%s", i + 1, buffer); /* 1 行ずつ表示 */ return (0); 実行すれば ex19.c の内容が最初の 5 行だけ出てくるでしょう すべての行を書き出すためには次 のようにします ex20.c /* ファイルを用いた例 */ int i = 0; input = fopen("ex20.c","r"); /* ex80.c を読み込み専用でオープン */ /* オープンに失敗したとき input は NULL になる */ printf("error! ex20.c not found. n"); while(!feof(input)) { /* ファイルの最後に到達してないとき繰り返し */ printf("%2d 行目 :%s", ++i, buffer); fgets(buffer, 100, input); return (0); 25
では次は fscanf 関数と fprintf 関数を使ってファイルを読み出し 書き出す例を行ってみまし ょう まず プログラムを保存するフォルダと同じところに入力用のデータファイルを作成します http://hakuto.mis.ous.ac.jp/~yanagi/aprog2016/ からデータ (alice.txt) をダウン ロードしてください これはルイス キャロルの不思議の国のアリスの第 1 章です ex21.c /* ファイルの読み書き */ void find_a(file *in, FILE *out); FILE *output; /* オープンした結果を保存するポインタ変数 */ /* alice.txt を読み込み専用でオープン */ input = fopen("alice.txt", "r"); /* output.txt を書き込み専用でオープン */ output = fopen("output.txt", "w"); printf("error! alice.txt が見つかりません n"); else if(output == NULL) { printf("error! output.txt が開けません n"); find_a(input, output); fclose(output); /* クローズ */ void find_a(file *in, FILE *out) { int i = 0; while(!feof(in)) { fscanf(in, "%s", buffer); i++; if(buffer[0] == 'A') { fprintf(out, "%s %d 語目 n", buffer, i); 26
問題 2.1 alice.txt の文章の単語の中で 先頭のアルファベットで何が一番多いか調べなさい ただし 大文字小文字は区別せずに数えるように作成しなさい ex22.c /* 単語の先頭のアルファベットのうち最多のもの */ char find_max(file *in); int nmax(int x[], int len); /* alice.txt を読み込み専用でオープン */ input = fopen("alice.txt", "r"); printf("error! alice.txt が見つかりません n"); printf(" 最も多いのは %c です n", find_max(input)); return(0); char find_max(file *in) { int [26]; char i, ; while(!feof(in)) { fscanf(in, "%s", buffer); return('a' + (char)nmax(, 26)); int nmax(int x[], int len) { int i, imax; imax = 0; for(i = 1; i < len; i++) { if(x[imax] < x[i]) { imax = i; return(imax); 27
2.2 ファイル処理と構造体 構造体のデータは多いので 毎回キーボードで入力するのは面倒です そこで ファイルから読み 込んで構造体に値を代入することを考えてみます まずは データファイルをプログラムと同じフォ ルダに用意しましょう student.txt I00I000 80 85 90 以下数人分入力する最後の行は改行しないで終わること このデータを読み込んで 平均点を追加してファイルに書き出すプログラムを作成してみます ex23.c /* 成績表 */ /* 成績管理用の構造体の定義 */ typedef struct student { char idnumber[8]; /* 学籍番号 */ int math, eng, jpn; /* 点数 ( 数学, 英語, 国語 ) */ double mean; /* 平均点 */ student; /* プロトタイプ宣言 */ void input_student(file *input, student *x); void print_student(file *input, student x); FILE *output; /* オープンした結果を保存するポインタ変数 */ student data; /* データの構造体 */ /* student.txt を読み込み専用でオープン */ input = fopen("student.txt", "r"); /* output.txt を書き込み専用でオープン */ output = fopen("output.txt", "w"); printf("error! alice.txt が見つかりません n"); else if(output == NULL) { printf("error! output.txt が開けません n"); while(!feof(input)) { input_student(input, &data); /* データの入力 */ print_student(output, data); /* データの出力 */ return(0); 28
/* 入力用関数 */ void input_student(file *input, struct student *x) { fscanf(input, "%7s %d %d %d", x->idnumber, &x->math, &x->eng, &x->jpn); x->mean = (double)(x->math + x->eng + x->jpn) / 3; /* 出力用関数 */ void print_student(file *output, struct student x) { fprintf(output, "%10s: %3d %3d %3d %6.2f n", x.idnumber, x.math, x.eng, x.jpn, x.mean); printf( "%10s: %3d %3d %3d %6.2f n", x.idnumber, x.math, x.eng, x.jpn, x.mean); 問題 2.2(ex24.c) 問題 1.5 の三角形の構造体とプログラムを利用して triangle.txt 1 2 3 2 3 4 3 4 5 4 5 6 のようなファイルから 1 2 3 三角形はできない 2 3 4 鈍角三角形 3 4 5 直角三角形 4 5 6 鋭角三角形 のようなファイルを作成するプログラムを作成しなさい 29