「C言語練習」 2-2.c   ・前へ   ・次へ
/* 二次元配列、頻度(得点)分布   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;
}



(前に戻る)   ・次へ