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); 基本的にはファイルをオープンする 読み書きする ファイルをクローズするの順序で行うことになります 72
ex82.c /* ファイルを用いた例 */ int main(void) { FILE *input; /* オープンした結果を保存するポインタ変数 */ int i; char buffer[100]; /* ファイルから内容を読み込むための場所 */ input = fopen("ex82.c","r"); /* ex82.c を読み込み専用でオープン */ if(input == NULL) { /* オープンに失敗したとき input は NULL になる */ printf("error! ex82.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); /* クローズ */ 実行すれば ex82.c の内容が最初の 5 行だけ出てくるでしょう すべての行を書き出すためには次のようにします ex83.c /* ファイルを用いた例 */ int main(void) { FILE *input; /* オープンした結果を保存するポインタ変数 */ int i = 0; char buffer[100]; /* ファイルから内容を読み込むための場所 */ input = fopen("ex82.c","r"); /* ex82.c を読み込み専用でオープン */ if(input == NULL) { /* オープンに失敗したとき input は NULL になる */ printf("error! ex82.c not found\n"); else { fgets(buffer, 100, input); while(!feof(input)) { /* ファイルの最後に到達してないとき */ printf("%2d 行目 :%s", ++i, buffer); fgets(buffer, 100, input); fclose(input); /* クローズ */ 73
では 書き出す例をやってみましょう ex84.c FILE *output; /* オープンした結果を保存するポインタ変数 */ int maxnum, x, i, prime, count = 0; printf(" 調べる整数を入れてください :"); scanf("%d", &maxnum); printf("%d 以下の素数は次の通りです \n", maxnum); output = fopen("prime.txt","w"); /* prime.txt を書き込み専用でオープン */ if(output == NULL) { /* オープンに失敗したとき input は NULL になる */ printf("error! prime.txt cannot open.\n"); else { for(x = 2; x <= maxnum; x++) { prime = 1; for(i = 2; (prime == 1) && (i * i <= x); i++) { if(x % i == 0) { prime = 0; if(prime == 1) { printf("%d ", x); fprintf(output, "%d\n", x); count++; fclose(output); /* クローズ */ printf("\n 以上 %d 個あります \n", count); こうすると 見つけた素数の結果が 画面に表示されると同時に prime.txt というファイルに保存されます 74
8 総合演習 練習問題 8.1 乱数を用いて 0~19 までの適当な数字を配列に入れる この中のもののうち 最も個数の多い ものを探す関数 findmax を作成しなさい ex85.c #include <stdlib.h> #define NUMMAX 100 #define RANDMAX 20 int find(int *x, int m, int n); int datax[nummax]; int i, n, c; printf(" 乱数の種の整数を入力してください : "); scanf("%d", &n); srand(n); for(i = 0; i < NUMMAX; i++) { datax[i] = rand() % RANDMAX; c = find(datax, RANDMAX, NUMMAX); printf(" 最も多かったのは %d です \n", c); return(0); int find(int *x, int m, int n) { int c, max, ; for( ; ; ) { c = 0; for( ; ; ) { if( ) { c++; if( ) { max = c; ; return( ); 75
練習問題 8.2 文字列を入力してもらい アルファベットを与えられた文字列を前の文字に変更した文字列を作 成するプログラムをポインタのみを用いた作成しなさい ただし A, a についてはそれぞれ Z, z に変更することにする ( 大文字 A は大文字 Z に 小文字 a は小文字 z に ) アルファベット以外は そのままにすること 配列は宣言のとき以外は使ってはならない ex86.c /* 前の文字の文字列を作る関数 */ void prev(char *from, char *to); char string[81], prev_string[81]; printf(" 文字列を入力してください : "); scanf("%80s", string); /* 最大 80 文字まで読み込む */ printf("%s\n", string); printf(" 変換するとにすると \n"); prev(string, prev_string); printf("%s\n", prev_string); /* 前の文字にする */ void prev(char *from, char *to) { 練習問題 8.3 整数の素因数分解をするプログラムを作成します まず そのための構造体を作成します ある素数とそのベキ数を保存する構造体を次のように定義します struct factor { int prime; /* 素数 */ int power; /* べき数 */ ; 例えば 360 = 2^3 3^2 5 なので 3つの構造体 {2,3, {3,2, {5,1 で表すことができます この構造体を利用してプログラムを完成させなさい 76
ex87.c /* 素因数分解 */ struct factor { int prime; /* 素数 */ int power; /* べき数 */ ; void print_result(int, struct factor[]); int factor_step(int, int, struct factor *); struct factor list[100]; int num, x, i = 0, j; printf(" 素因数分解する自然数を入力してください \n"); scanf("%d", &num); x = num; /* num の値を保存するために */ if(x % 2 == 0) { /* 2 を因数に持つならば */ x = factor_step(x, 2, &list[i++]); for(j = 3; x > 1; j += 2) { /* 3 以上の奇数だけを調べる */ if(x % j == 0) {/* 2 を因数に持つならば */ x = factor_step(x, j, &list[i]); i++; list[i].prime = 0; /* 終わりの記号として素数の値を 0 とする */ print_result(num, list); return(0); /* 結果の表示 1 乗の場合は ^1 は表示しないように */ void print_result(int x, struct factor y[]) { int i; printf("%d = %d", x, y[0].prime); if(y[0].power!= 1) { printf("^%d", y[0].power); for(i = 1; y[i].prime!= 0; i++) { printf(" %d", y[i].prime); if(y[i].power!= 1) { printf("^%d", y[i].power); printf("\n"); 77
/* 引数 x: もとの整数 y: 割れる素数 z のメンバ prime に素数 power にベキ乗の数を入れる戻り値は x をその素数のベキ乗数で割ったもの */ int factor_step(int x, int y, struct factor *z) { 練習問題 8.4 最後の値を返す関数 last_value を作成せよ ex81.c /* 簡単なリスト処理 */ struct data { int value; struct data *next; ; void print_data(struct data *s); int last_value(struct data *s); struct data x[4], *start; start = &x[0]; x[0].value = 10; x[0].next = &x[1]; x[1].value = 20; x[1].next = &x[2]; x[2].value = 30; x[2].next = &x[3]; x[3].value = 40; x[3].next = NULL; print_data(start); printf(" 最後の値は %d\n", last_value(start)); return(0); /* データの表示 */ void print_data(struct data *s) { for( ; s!= NULL; s = s->next) { printf("%d ", s->value); printf("null\n"); int last_value(struct data *s){ for( ;!= NULL; ); return(s->value); 78