前提・実現したいこと
C言語に関する質問です。以下にコードを記載しました。
以下のプログラムを起動してファイルに書き込まれた各教科の点数から最大、最小、平均、標準偏差を計算したいです。
また、在籍番号や成績の順番で照準に並べ替えることもしたいと思っています。
ファイルに書き込まれたデータを扱う手段があまりわかりません。
調べたところ、事前に人数や点数が定まっている場合のやり方は見つけられたのですが。。。
アドバイスいただきたいです。
該当のソースコード>
C
1#include <stdlib.h> 2#include <stdio.h> 3#include <string.h> 4 5#define NAME_LEN 64 6#define NUMBER 10 7 8typedef struct{ 9 char num[10]; /*在籍番号*/ 10 char name[NAME_LEN]; /*名前*/ 11 double math; /*数学*/ 12 double phy; /*物理*/ 13 double eng; /*英語*/ 14} Student; 15 16/*データを入力してファイルに書き込み*/ 17void data_input(Student a[]){ 18 FILE *fp; 19 int i; 20 if ((fp=fopen("score.dat","w"))==NULL) /*オープン*/ 21 printf("\aファイルをオープンできません。\n"); 22 else{ 23 for(i=0;;i++){ 24 int flag; 25 printf("%d人目のデータを入力しますか(YES-1/NO-0):",i+1); 26 scanf("%d",&flag); 27 if(flag==0) 28 break; 29 printf("Num:");scanf("%s",a[i].num); 30 printf("Name:");scanf("%s",a[i].name); 31 printf("Math:");scanf("%lf",&a[i].math); 32 printf("Phy:");scanf("%lf",&a[i].phy); 33 printf("Eng:");scanf("%lf",&a[i].eng); 34 fprintf(fp,"%-10s %-10s %5.1f %5.1f %5.1f \n",a[i].num,a[i].name,a[i].math,a[i].phy,a[i].eng); 35 } 36 fclose(fp); 37 } 38} 39 40float gpa(int average){ 41 if(average<=60) 42 return 0; 43 if(average>=61 && average<=70) 44 return 1.0; 45 if(average>=71 && average<=80) 46 return 2.0; 47 if(average>=81 && average<=90) 48 return 3.0; 49 if(average>=91 && average<=100) 50 return 4.0; 51 return 0; 52} 53 54// 数学の合計の計算 55double sum_math(Student a[], int person){ 56 int i; 57 double total = 0.0; 58 for(i=0; i<person; i++){ 59 total += a[i].math; 60 } 61 return total; 62} 63// 物理の合計の計算 64double sum_phy(Student a[], int person){ 65 int i; 66 double total = 0.0; 67 for(i=0; i<person; i++){ 68 total += a[i].phy; 69 } 70 return total; 71} 72// 英語の合計の計算 73double sum_eng(Student a[], int person){ 74 int i; 75 double total = 0.0; 76 for(i=0; i<person; i++){ 77 total += a[i].eng; 78 } 79 return total; 80} 81 82// 数学の平均の計算 83double ave_math(Student a[], int person){ 84 double total = sum_math(a, person); 85 return total/person; 86} 87// 物理の平均の計算 88double ave_phy(Student a[], int person){ 89 double total = sum_phy(a, person); 90 return total/person; 91} 92// 英語の平均の計算 93double ave_eng(Student a[], int person){ 94 double total = sum_eng(a, person); 95 return total/person; 96} 97 98// 数学の分散の計算 99double var_math(Student a[], int person) { 100 int i; 101 double A = ave_math(a, person); 102 double v = 0.0; 103 for (i=0; i<person; i++) 104 v += (a[i].math - A) * (a[i].math - A); 105 return v/person; 106} 107 108// 物理の分散の計算 109double var_phy(Student a[], int person) { 110 int i; 111 double A = ave_phy(a, person); 112 double v = 0.0; 113 for (i=0; i<person; i++) 114 v += (a[i].phy - A) * (a[i].phy - A); 115 return v/person; 116} 117// 英語の分散の計算 118double var_eng(Student a[], int person) { 119 int i; 120 double A = ave_eng(a, person); 121 double v = 0.0; 122 // 分散を計算 123 for (i=0; i<person; i++) 124 v += (a[i].eng - A) * (a[i].eng - A); 125 return v/person; 126} 127 128// 数学の標準偏差の計算 129double std_math(Student a[], int person) { 130 return sqrt(var_math(a, person)); 131} 132 133// 標準偏差の計算 134double std_phy(Student a[], int person) { 135 return sqrt(var_phy(a, person)); 136} 137// 標準偏差の計算 138double std_eng(Student a[], int person) { 139 return sqrt(var_eng(a, person)); 140} 141 142/*ファイルを読み込んでデータを出力*/ 143void data_output(Student a[]){ 144 FILE *fp; 145 int i; 146 int person = 0; 147 int average = 0; 148 int total = 0; 149 int math_max,math_min,phy_max,phy_min,eng_max,eng_min; 150 151 if ((fp=fopen("score.dat","r"))==NULL) /*オープン*/ 152 printf("\aファイルをオープンできません。\n"); 153 else{ 154 i=0; 155 while(fscanf(fp,"%s%s%lf%lf%lf",a[i].num,a[i].name,&a[i].math,&a[i].phy,&a[i].eng)==5){ 156 printf("%-10s %-10s %5.1f %5.1f %5.1f \n",a[i].num,a[i].name,a[i].math,a[i].phy,a[i].eng); 157 i++; 158 person++; 159 } 160 math_max = math_min = a[0].math; 161 phy_max = phy_min = a[0].phy; 162 eng_max = eng_min = a[0].eng; 163 for(i=1;i<person;++i){ 164 if (math_max < a[i].math) 165 math_max = a[i].math; 166 if (math_min > a[i].math) 167 math_min = a[i].math; 168 if (phy_max < a[i].phy) 169 phy_max = a[i].phy; 170 if (phy_min > a[i].phy) 171 phy_min = a[i].phy; 172 if (eng_max < a[i].eng) 173 eng_max = a[i].eng; 174 if (eng_min > a[i].eng) 175 eng_min = a[i].eng; 176 } 177 /* 最高点と最低点の表示 */ 178 printf("最高点 数学:%d 物理:%d 英語:%d\n", math_max,phy_max,eng_max); 179 printf("最低点 数学:%d 物理:%d 英語:%d\n", math_min,phy_min,eng_min); 180 for(i=0;i<person;i++){ 181 total=(a[i].math+a[i].phy+a[i].eng);/*平均を計算*/ 182 average=(a[i].math+a[i].phy+a[i].eng)/3; /*平均を計算*/ 183 printf("%-10s %-10s 合計:%3.1d 平均:%5.1f → GPA:%5.1f\n",a[i].num,a[i].name,total,average,gpa(average)); 184 } 185 186 printf("math 合計:%5.1f 平均:%5.1f 分散:%5.1f 標準偏差:%f\n",sum_math(a,person),ave_math(a,person),var_math(a,person),std_math(a,person)); 187 printf("phy 合計:%5.1f 平均:%5.1f 分散:%5.1f 標準偏差:%f\n",sum_phy(a,person),ave_phy(a,person),var_phy(a,person),std_phy(a,person)); 188 printf("eng 合計:%5.1f 平均:%5.1f 分散:%5.1f 標準偏差:%f\n",sum_eng(a,person),ave_eng(a,person),var_eng(a,person),std_eng(a,person)); 189 fclose(fp); 190 } 191} 192 193void swap_Student(Student *x,Student *y){ 194 Student temp=*x; 195 *x=*y; 196 *y=temp; 197} 198 199/*昇順*/ 200void sort_by_num(Student a[], int n){ 201 int i,j; 202 for(i=0;i<n-1;i++){ 203 for(j=n-1;j>1;j--){ 204 if (a[j-1].num>a[j].num) 205 swap_Student(&a[j-1],&a[j]); 206 } 207 } 208} 209/*降順*/ 210void sort_by_num_2(Student a[], int n){ 211 int i,j; 212 for(i=0;i<n-1;i++){ 213 for(j=n-1;j>1;j--){ 214 if (strcmp(a[j-1].num,a[j].num)<0) 215 swap_Student(&a[j-1],&a[j]); 216 } 217 } 218} 219 220int main(void){ 221 Student std[NUMBER]; 222 int flag; 223 do{ 224 printf("ファイル書き込み-1 / ファイル読み込み-2 / 終了-0 :"); 225 scanf("%d",&flag); 226 if(flag==1) 227 data_input(std); 228 else if(flag==2) 229 data_output(std); 230 }while(flag != 0); 231 return 0; 232} 233 234
やってみたこと
色々と書き換えてここまできました。
各教科の平均は関数を用いて記述できましたが、各個人の平均を関数で表す方法が思い浮かばなかったため、無理やり?計算しました。また、学籍番号を用いたソートのように、各個人の平均やGPAを用いたソートを行いたいのですが、構造体を使っていないため?かstrcmp(a[j-1].num,a[j].num)<0の部分の書き方がわかりません。