情報処理4レポート課題(2)の解答例

更新:2007年9月29日


  1. 次のプログラムfile2.cを改訂して,test.datにはsin(1.0)を, test2.datにはcos(1.0)を書き込むようにして下さい.
    file2.c
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    
    int main(void){
    	FILE *fp;
    	fp=fopen("test.dat", "w");
    	if(fp==NULL){
    		printf("File Can't Open\n");
    		exit(1);
    	}
    	fprintf(fp, "%f\n", sin(1.0));
    	fclose(fp);
    	return 0;
    }
    
    ただし、次の2通りのプログラムを作成してください。
    1. ファイルへのポインタを二つ(例えばfp1とfp2)用意してそれぞれをtest.datとtest2.datに用いる。
    2. ファイルへのポインタを一つだけ用意して、初めにtest.datをオープンしてsin(1.0)を書き込んでクローズし、次にtest2.datをオープンしてcos(1.0)を書き込んでクローズする。

    file2_1.c
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    
    int main(void){
    	FILE *fp1, *fp2;
    
    	fp1=fopen("test.dat", "w");
    	if(fp1==NULL){
    		printf("File Can't Open\n");
    		exit(1);
    	}
    
    	fp2=fopen("test2.dat", "w");
    	if(fp2==NULL){
    		printf("File Can't Open\n");
    		exit(1);
    	}
    
    	fprintf(fp1, "%f\n", sin(1.0));
    	fprintf(fp2, "%f\n", cos(1.0));
    
    	fclose(fp1);
    	fclose(fp2);
    
    	return 0;
    }
    
    file2_2.c
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    
    int main(void){
    	FILE *fp;
    
    	fp=fopen("test.dat", "w");
    	if(fp==NULL){
    		printf("File Can't Open\n");
    		exit(1);
    	}
    	fprintf(fp, "%f\n", sin(1.0));
    	fclose(fp);
    
    	fp=fopen("test2.dat", "w");
    	if(fp==NULL){
    		printf("File Can't Open\n");
    		exit(1);
    	}
    	fprintf(fp, "%f\n", cos(1.0));
    	fclose(fp);
    	return 0;
    }
    
  2. 今まで作成してきたプログラムなどの内で、何か画面表示しているものを選んで 適当なテキストファイルに出力するように書き換えて下さい。 ただし、指定したテキストファイルが存在する場合には上書きされることに注意して下さい。
    レポート課題(1)の1を題材にしました。
    vector_subtract_file.c
    #include<stdio.h>
    
    void subtract(double *lhs, double *rhs, int size, double *result);
    
    int main(void){
    	double a[7], b[7], c[5], d[5];
    	int i;
    	double a_sub_b[7], c_sub_d[5];
    	FILE *fp;
    
    	a[0]=0.1; a[1]=0.2; a[2]=0.3; a[3]=0.4; a[4]=0.5; a[5]=0.6; a[6]=0.7;
    	b[0]=1.1; b[1]=2.2; b[2]=3.3; b[3]=4.4; b[4]=5.5; b[5]=6.6; b[6]=7.7;
    
    	c[0]=0.5; c[1]=0.6; c[2]=0.7; c[3]=0.8; c[4]=0.9;
    	d[0]=11.0; d[1]=22.1; d[2]=33.2; d[3]=44.3; d[4]=55.4;
    
    	fp=fopen("vector_subtract.dat", "w");
    	if(fp==NULL){
    		printf("File can't open.\n");
    		exit(1);
    	}
    
    	fprintf(fp, "a:\n");
    	for(i=0;i<7;i++){
    		fprintf(fp, "a[%d]=%f\n", i, a[i]);
    	}
    
    	fprintf(fp, "b:\n");
    	for(i=0;i<7;i++){
    		fprintf(fp, "b[%d]=%f\n", i, b[i]);
    	}
    
    	subtract(a, b, 7, a_sub_b);
    
    	fprintf(fp, "a_sub_b:\n");
    	for(i=0;i<7;i++){
    		fprintf(fp, "a_sub_b[%d]=%f\n", i, a_sub_b[i]);
    	}
    
    	fprintf(fp, "c:\n");
    	for(i=0;i<5;i++){
    		fprintf(fp, "c[%d]=%f\n", i, c[i]);
    	}
    
    	fprintf(fp, "d:\n");
    	for(i=0;i<5;i++){
    		fprintf(fp, "d[%d]=%f\n", i, d[i]);
    	}
    
    	subtract(c, d, 5, c_sub_d);
    
    	fprintf(fp, "c_sub_d:\n");
    	for(i=0;i<5;i++){
    		fprintf(fp, "c_sub_d[%d]=%f\n", i, c_sub_d[i]);
    	}
    
    	return 0;
    }
    
    void subtract(double *lhs, double *rhs, int size, double *result){
    	int i;
    	for(i=0;i<size;i++){
    		result[i]=lhs[i]-rhs[i];
    	}
    	return;
    }
    
    単純に「printfをfprintfに書き換え」で済まそうとすると、 ファイルがオープンできなかったエラーメッセージさえもファイルに書き込もうと することになるので気をつけて下さい。

以下は,幾つかの考察・感想に対するコメントです.
1-1の回答でfcloseの位置を
        fp1=fopen("test.dat", "w");
        if(fp1==NULL){
                printf("File Can't Open\n");
                exit(1);
        }

        fp2=fopen("test2.dat", "w");
        if(fp2==NULL){
                printf("File Can't Open\n");
                exit(1);
        }

        fprintf(fp1, "%f\n", sin(1.0));
        fclose(fp1);
        fprintf(fp2, "%f\n", cos(1.0));
        fclose(fp2);
        fp1=fopen("test.dat", "w");
        if(fp1==NULL){
                printf("File Can't Open\n");
                exit(1);
        }

        fprintf(fp1, "%f\n", sin(1.0));
        fclose(fp1);

        fp2=fopen("test2.dat", "w");
        if(fp2==NULL){
                printf("File Can't Open\n");
                exit(1);
        }

        fprintf(fp2, "%f\n", cos(1.0));
        fclose(fp2);
に書き換えて実行しても結果が変わらなかったのはよかったのでしょうか?
fp1, fp2それぞれについて,オープン,書き込み,クローズの順序が保たれていれば, 問題ありません.
問題1でfp2の方もオープンできない時のプログラムを書き込んで良いのか迷いました。
fp2の方もオープンできないときのプログラムを書き込んで下さい.
ポインタが一つの時はオープンできない時のプログラムも一つでいいので楽でした。
いいえ,ポインタが一つのときでも,オープンできないときのプログラムは2つ書かなくてはなりません. オープンできないときの処理は宣言したポインタの数で決まるのでなく, fopen関数の数で決まるのです. fopen関数を呼び出す毎に,オープンできないときの処理を記述して下さい.
どちらの方が実行時間が短いとかはあるのだろうか。 2つめの方が使用領域は少ないと思うが、1の方がプログラムはすっきりしていると思う。
その疑問は良いですね. 同じ内容を複数のファイルに書き込むのならば, 複数のポインタを用いた方が実行時間は短く済みます. 2つ目の方が若干,使用領域が少ないですが無視できる程度です. 但し,複数のファイルを同時に扱っていないので, デバグし易いと思います.
オープンしてクローズしてという作業を繰り返しているのにtest.datがtest2.datを開いた後でも動くということです。クローズしても 書き込んだファイルには残るということでいいのでしょうか?
ええと,質問の意図が今一つ分からないので,プログラム例を示してくれると嬉しいです.
(i)の方では、ポインタ変数を2つ用意し、それぞれの変数を用いて1つのファイルを書き換えるプログラムを書けば完成です。「それぞれの変数を用いてそ れぞれのファイルを書き換える」なので、変数ごとにプログラムを書いたのですが、ファイルオープン・領域確保・書き換え・ファイルクローズと項目ごとに 分けて書いた方が良かったのでしょうか?
(ii)との違いを明確にするには,(i)では 二つのファイルをオープン(とエラー処理),各ファイルに書き込み,二つのファイルをクローズの順にした方が良かったかも知れません((ii)ではそのようには記述できないので).
「ファイルを開けないとき」の操作がよくわかりませんでした。 先生のパソコンでは、"[kanzawa@oa201 ~/Info4]"となってましたが、私の所は "bash-2.05b"となっていて、cdとかよくわからなかったんですけど…;
cdなどのコマンドがあまり分かっていなくても実行できるように, Web資料を書き直したので時間を見つけて再現しておいて下さい.
課題1の2通り目の方法で
       FILE *fp;
        fp=fopen("test.dat", "w");
         if(fp==NULL)
        {
                printf("File Can't Open\n");
                exit(1);
        }
        FILE *fp;
        fp=fopen("test2.dat", "w");
         if(fp==NULL)
        {
                printf("File Can't Open\n");
                exit(1);
        }
でできるのか試してみたかったが時間がなくてできなかった。
上のプログラムはコンパイルできないでしょう. 同じ名前のfpを複数回宣言できないからです.
1つ目のファイルについてはもっとも簡潔な形のプログラムだが、2つ目のファイルはまだより簡略化する余地がありそうだ。 NULLでの表示できない場合の部分を1つにまとめられないかとも考えたが、
これ以上に簡略化する余地はありません. NULLでの表示できない場合の部分はfopenの呼び出し1回につき1回必要なので まとめることはできません.
ファイルを"オープン"や"クローズ"などの概念が分からず
概念は「オープン=処理準備」,「クローズ=処理後片付け」です. 実際に何が行われているかについては当講義の範囲を越えています.
自分はプログラムを考えるのは好きだが、今日 のやつやgdbなどが難しく嫌いなので、どのように勉強していったらいいのですか。
うーん,難しい=嫌いならば,好きになって簡単に思うようになるか, しんどいけれど簡単に思うようになるまで頑張って好きになるしかないと思います. 将来,プログラミング関連の職業につく場合でも, プログラムを考えるだけで済むということはないと思うので.
fprintfの場合%dでコンマを入れて計算式を入れて出るかやってみたんですができなかったのでその方法をしりたいです
doubleのときは%fを使って下さい.
通信工学科はソフトとハード両方できる学科だと考えていますが、どっちも面白そうで正直迷っています。 研究室やら何やらを考えるとそろそろ決めなくてはいけないような気がして・・・ 何かアドバイスを頂けたら幸いです。
ソフトとハードという側面から各研究室を分類すると, 「ソフトもハードも扱う研究室」, 「ソフトをより深く扱う結果ハードには(あまり)触れない研究室」, 「ハードをより深く扱う結果ソフトには(あまり)触れない研究室」 になります.自分の興味に応じて志望を狭めていけば良いでしょう. まずは,各先生方に御研究内容を聞いてみてはいかがでしょうか.
疲れました・・・ パソコンのように疲れない体になりたいです
パソコンだって疲れます(経年劣化によるメモリアクセスエラーやハードディスククラッシュ).
「適当なテキストファイルに出力するように書き換えて」というのは、過去に作った"./a.out"で実行結果を表示していたプログラムを、"cat text.dat"で表示させるように書き換えるということで合ってるのでしょうか?
平たく云うとそうです.
なぜ#includeが必要なのかわからなかった。
exit関数を使うからです.
ファイルオープンしてから変数をint定義しようとすると
警告: ISO C90 forbids mixed declarations and code
とエラーが出るのですがどういう意味でしょうか?
ISO C90というC言語の規格では, 変数の宣言を必ず関数の先頭にまとめておかなければならないということです.
プログラム中にscanfがあった場合はどのように行えば結果を出力することが出来るのだろうか。
scanf関数があってもプログラミング方法は同じです.
今回選んだプログラムがprintfが一つだけのパターンだったので、printfが二つ以上なるとどうなるんでしょうか。
同じです.
rand関数で作った乱数a,bをファイルに書き込むプログラム……のはずが何故だか、何度実行してみてもbの値が0.00000のまま変わらなかった
a,bをintで宣言したら%dを用いて下さい.

何かありましたら、 まで。