/* 関数 2-1.c */ #include <stdio.h> #include <stdlib.h> #include <math.h> /* 「一連の同じ計算」をprogram中で何度も行う場合や「複雑な処理」を行う場合には、それら の操作を一つの纏まりとして本体のprogramから切り離して処理すれば、programがすっきりと した形になる。こういう目的の為に、C言語では関数を自分で作る事が出来る。作った関数は、 当然main()の外に置くが、main()の前に置く事も後に置く事も出来る。前に置く場合は、関数を そのまま記述すれば良い。後に置くと、main()でその関数を呼び出した時に未定義(見た事が ない!)となるので、関数の型だけを前以ってmain()の前に書いておく。こうして置けばエラー は出ない。これを関数のprototype宣言(proto=初めの, type=型)という。小さな関数の場合を 除き、prototype宣言してある方が分かり易い。ここでは、関数をprototype宣言しておく事に する。 関数は、関数名(引数1,引数2,,,) { }の形で書く。main()が関数に渡す変数(=引数)は、 必要数だけカンマ ,で区切って( )内に書き、{ }の中に処理内容を記述する。関数は、ある値を 得る為に(そうでない関数もあるが)一連の演算を行い、得られた値をreturnでmain()に返す。 返せる値は一つだけである。 関数で用いる変数(引数以外)は中で宣言する。変数は関数毎に独立しており、main()で使う 変数と同名の変数を宣言し、その値を変えてもmain()の変数値には影響しない。引数名も同様 に自由であり、その型だけ分かっていれば良い。 従って、関数は引数の型を明示すると共に、関数名にも型名を付けて(関数の返す値が何型か を示す為)書く事になる。 下が、関数のprototype宣言。関数の返す値がfloatなので関数名にfloatを付けている。 引数の前にも型が必要。また、宣言時には関数名の最後に;が要る。 */ float f_mean(int n,float sum); float f_sd(int n,float sum,float s2); main() { int n; float sum,s2,d; float mean,sd; char fname[50]; FILE *fin; printf("* File data の平均と標準偏差 [関数使用]\nFile名を入力:"); gets(fname); putchar('\n'); fin=fopen(fname,"r"); // fileを開ける if (fin==NULL) {printf("File がありません!\n\nEnd\n"); exit(1);} sum=0;s2=0;n=0; while (! feof(fin)) { fscanf(fin,"%f",&d); sum+=d; s2+=d*d; n++; printf("%3d:%.2f ",n,d); if (n%5==0) putchar('\n'); } fclose(fin); // fileを閉じる。 mean=f_mean(n,sum); sd=f_sd(n,sum,s2); // 平均と偏差を関数で求める /* 関数を使う時はこう書く。文末に;が必要。先ず、f_mean()という関数にdata数 nと 総和 sumを渡して計算を頼み、その結果をmeanという変数に代入している。次に、nと sumと 平方和 s2をf_sd()という関数に渡して、その結果をsdに代入している。引数の型は予め宣言 してあるので、nをint、sum,s2をfloatと判断する。関数本体は、main()の後に書いてある。 */ printf("\n(n=%d) sum=%d mean=%.2f sd=%.2f",n,sum,mean,sd); printf("\nEnd\n"); return 0; } /* ここからが関数。f_mean()では、計算式自体をreturnで返している。非常に簡単だが、 先ずは練習 */ float f_mean(int n,float sum) { return (sum/n); } float f_sd(int n,float sum,float s2) { s2=s2-sum*sum/n; s2=s2/(n-1); s2=sqrt(s2); return s2; }