/* 二次元配列、頻度(得点)分布 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;
}