/* 関数 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;
}