/* 二次元配列、頻度(得点)分布 2-2.c */ #include <stdio.h> #include <stdlib.h> #include <math.h> float f_mean(int n,float sum); // 前回と同じく関数を使って見る。prototype宣言。 float f_sd(int n,float sum,float s2); main() { int i,j,n,rank[11],d[500][2]; // data数に500確保 float sum,s2; float mean,sd; char name[500][11],fname[50],fname2[50]; /* 二次元配列は上の様に書く。一つのsampleが幾つものdataを持つ場合(例えば、名前、点数、 偏差値)、それぞれに異なる変数名を与えるより、同じ名前で扱う方が処理し易い事がある。上で は、各sampleの数値data格納場所を二つ確保。文字列はそもそも配列で扱うので、多くのdataを 扱う場合は二次元配列にならざるを得ない。前の[ ]がsample(=data)数、後の[ ]に必要な文字 数(+1)を確保する。 */ FILE *fin,*fout; // fileを扱う宣言 printf("* 成績の得点分布 * (100点満点 10点刻み) と偏差値計算\n\nFile名を入力:"); gets(fname); fin=fopen(fname,"r"); // 入力fileを開ける if (fin==NULL) {printf("File がありません!\n\nEnd\n"); exit(1);} printf("成績\n"); for (j=0;j<=10;j++) rank[j]=0; sum=0;s2=0;n=0; while (! feof(fin)) { fscanf(fin,"%s %d",name[n],&d[n][0]); // 文字と数値を同時に読み込む sum+=d[n][0]; s2+=d[n][0]*d[n][0]; rank[d[n][0]/10]+=1; // ここで区分け n++; printf("%3d ",d[n-1][0]); if (n%15==0) putchar('\n'); } fclose(fin); // 入力fileを閉じる。 /* このfileには、次の様な形でdataが納まっている。違う形のdata fileであれば、その様に 入力箇所を手直しする。 name1 ten1 name2 ten2 ..... ... 点数を区間幅で割れば何番目の区画に入るかが分かるので、その区画に納める数を 1増やす。 全dataに付いてこれを行い、度数分布を求める。data数は nで数えている。*/ rank[9]+=rank[10]; // 満点を最高rankに含める。こうせずとも良い。 mean=f_mean(n,sum); sd=f_sd(n,sum,s2); // 関数で計算 printf("\n(n=%d) mean=%.2f sd=%.2f\n",n,mean,sd); //------------ 得点分布を表示 ------------- printf("\n点数:"); for (i=0;i<10;i++) printf("%3d- ",i*10); printf("\n-------------------------------------------------------\n人数: "); for (i=0;i<10;i++) printf("%3d ",rank[i]); printf("\n (%) "); for (i=0;i<10;i++) printf("%3d ",100*rank[i]/n); printf("\n累積: "); for (i=0,j=0;i<10;i++) {j+=rank[i]; printf("%3d ",j);} printf("\n (%) "); for (i=0,j=0;i<10;i++) {j+=rank[i]; printf("%3d ",100*j/n);} //------------- 表示終わり ------------- /* 上の for ()の中にi=0とj=0(jの初期化)を並べて書いている。カンマ(,)で繋げば、初期条件 をこの様にも書ける。*/ for (i=0;i<n;i++) d[i][1]=10*(d[i][0]-mean)/sd+50; // 偏差値計算 printf("\n\n偏差値と得点分布をFileに書き込みます。\nFile名を入力:"); gets(fname2); fout=fopen(fname2,"w"); // 出力fileを開ける //-------------- 以下fileに出力 ------------- for (i=0;i<n;i++) fprintf(fout,"%-10s %3d %3d\n",name[i],d[i][0],d[i][1]); // 名前、点数、偏差値を書き込んだ後、得点分布を書き込む。%-桁数sで文字列を左詰表示。 fprintf(fout,"\n点数:"); for (i=0;i<10;i++) fprintf(fout,"%3d- ",i*10); fprintf(fout,"\n-------------------------------------------------------\n人数: "); for (i=0;i<10;i++) fprintf(fout,"%3d ",rank[i]); fprintf(fout,"\n (%) "); for (i=0;i<10;i++) fprintf(fout,"%3d ",100*rank[i]/n); fprintf(fout,"\n累積: "); for (i=0,j=0;i<10;i++) {j+=rank[i]; fprintf(fout,"%3d ",j);} fprintf(fout,"\n (%) "); for (i=0,j=0;i<10;i++) {j+=rank[i]; fprintf(fout,"%3d ",100*j/n);} fprintf(fout,"\n"); //-------------- file出力終わり --------------- fclose(fout); // 出力fileを閉じる。 printf("\n書き込みました。\n\n分布パターンを表示します。\n"); for (i=0;i<10;i++) { printf("%3d:",i+1); for (j=1;j<=rank[i];j++) { printf("-"); } putchar('\n'); } printf("\nEnd\n"); return 0; } /* ----- 以下関数 ----- */ 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; }