質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

4回答

5807閲覧

ファイルを読み込んで計算

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

1グッド

2クリップ

投稿2019/06/30 00:34

編集2019/06/30 16:22

前提・実現したいこと

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の部分の書き方がわかりません。

DrqYuto👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pepperleaf

2019/06/30 01:29

それなりに動いていると思いますが、何が問題なのでしょうか? 読込んだデータは、std[]に入っているので、それを参照すれば、計算もできると思います。 また、コードにインデントが無いので、読みずらいです。
退会済みユーザー

退会済みユーザー

2019/06/30 04:55

インデントを加えました。 iが変動するため、それを参照する書き方がわかりません。また、関数を扱うとエラーが生じてしまいます。
episteme

2019/06/30 06:26 編集

> ファイルに書き込まれたデータを扱う手段があまりわかりません。 あまりわからん とは如何なる意味か? 何がわからん? キーボードから入力するのと大差ないが。
guest

回答4

0

最大、最小、平均、標準偏差の計算するのに、全データを配列に保持する必要ないですよ?

投稿2019/06/30 07:25

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

majiponi

2019/06/30 07:45

…まあそうなんですけど、理由まで書かないと我々文系プログラマにはすぐには伝わらないと思いますよ? 具体的に言えば、標準偏差なら各教科の、点数の平方の平均から平均点の平方を減じた後、正の平方根をとることで標準偏差を算出できる、というのは、確かに現行の指導要領では高校数学で教えますが、習ってない世代にはすぐには伝わらないと思いますよ?
episteme

2019/06/30 08:40

んー...そーか わからんか... # 統計に関わる数学は文系には必須ちゃうん? (むしろ理系以上に)
episteme

2019/06/30 08:51

わからんとすると、ここでの問題は「データ数が未知のとき、可変長の集合を実装できるか」なのよね。 ファイルからの入力とかあんま関係ない。ってこと、質問者は理解してるかしら? # 実際この問題は(ビギナには)かなり手強い。メモリ管理を避けられないから。
退会済みユーザー

退会済みユーザー

2019/06/30 16:14

回答ありがとうございます。 平均や標準偏差の計算は行えました。 学籍番号の構造体の.numを扱い、ソートが行うことができました。しかし、平均やGPAではソートを行う手段がわかりません。知識が乏しく申し訳ありません。
guest

0

次のプログラムで分からないところは自分でよく調べて、
それでも分からないところがあるときは、質問してください。

C

1#include <stdio.h> // printf, scanf, puts 2#include <stdlib.h> // malloc, free 3#include <string.h> // strcmp 4#include <math.h> // sqrt 5 6#define NAME_LEN 64 7#define NUMBER 10 8 9typedef struct { 10 int num; /* 在籍番号 */ 11 char name[NAME_LEN]; /* 名前 */ 12 double math; /* 数学 */ 13 double phy; /* 物理 */ 14 double eng; /* 英語 */ 15} Student; 16 17void data_input(Student a[]) 18{ 19 FILE *fp = fopen("score.dat","w"); 20 if (fp == NULL) { printf("\aファイルをオープンできません。\n"); return ; } 21 for (int i = 0; i < NUMBER; i++) { 22 int flag; 23 printf("%d人目のデータを入力しますか(YES-1/NO-0):", i + 1); 24 scanf("%d", &flag); 25 if (flag == 0) break; 26 printf("Num:"); scanf("%d", &a[i].num); 27 printf("Name:"); scanf("%s", a[i].name); 28 printf("Math:"); scanf("%lf", &a[i].math); 29 printf("Phy:"); scanf("%lf", &a[i].phy); 30 printf("Eng:"); scanf("%lf", &a[i].eng); 31 fprintf(fp, "%-10d %-10s %5.1f %5.1f %5.1f\n", 32 a[i].num, a[i].name, a[i].math, a[i].phy, a[i].eng); 33 } 34 fclose(fp); 35} 36 37double gpa(double average) 38{ 39 return (average > 60 && average <= 100) ? (int)(average - 51) / 10 : 0; 40} 41 42void print_index(Student a[], int person, Student *index[]) 43{ 44 for (int i = 0; i < person; i++) { 45 Student *p = index[i]; 46 printf("%-10d %-10s %5.1f %5.1f %5.1f \n", 47 p->num, p->name, p->math, p->phy, p->eng); 48 } 49} 50 51void sort_by_num(Student *index[], int person) 52{ 53 for (int i = 0; i < person - 1; i++) { 54 Student *p = index[i]; 55 for (int j = 1; j < person; j++) { 56 Student *q = index[j]; 57 if (p->num > q->num) { 58 index[i] = q; 59 index[j] = p; 60 } 61 } 62 } 63} 64 65void sort_by_name(Student *index[], int person) 66{ 67 for (int i = 0; i < person - 1; i++) { 68 Student *p = index[i]; 69 for (int j = 1; j < person; j++) { 70 Student *q = index[j]; 71 if (strcmp(p->name, q->name) > 0) { 72 index[i] = q; 73 index[j] = p; 74 } 75 } 76 } 77} 78 79void data_output(Student a[]) 80{ 81 FILE *fp = fopen("score.dat","r"); 82 if (fp == NULL) { printf("\aファイルをオープンできません。\n"); return; } 83 int i; 84 for (i = 0; fscanf(fp, "%d%s%lf%lf%lf", &a[i].num, a[i].name, 85 &a[i].math, &a[i].phy, &a[i].eng) == 5; i++) { 86 printf("%-10d %-10s %5.1f %5.1f %5.1f \n", a[i].num, a[i].name, 87 a[i].math, a[i].phy, a[i].eng); 88 } 89 fclose(fp); 90 91 int person = i; 92 double math_max, math_min, phy_max, phy_min, eng_max, eng_min; 93 math_max = math_min = a[0].math; 94 phy_max = phy_min = a[0].phy; 95 eng_max = eng_min = a[0].eng; 96 for (i = 1; i < person; i++) { 97 if (math_max < a[i].math) math_max = a[i].math; 98 if (math_min > a[i].math) math_min = a[i].math; 99 if (phy_max < a[i].phy) phy_max = a[i].phy; 100 if (phy_min > a[i].phy) phy_min = a[i].phy; 101 if (eng_max < a[i].eng) eng_max = a[i].eng; 102 if (eng_min > a[i].eng) eng_min = a[i].eng; 103 } 104 printf("最高点 数学:%5.1f 物理:%5.1f 英語:%5.1f\n", 105 math_max, phy_max, eng_max); 106 printf("最低点 数学:%5.1f 物理:%5.1f 英語:%5.1f\n", 107 math_min, phy_min, eng_min); 108 109 double math_sum = 0, phy_sum = 0, eng_sum = 0; 110 double math_sum2 = 0, phy_sum2 = 0, eng_sum2 = 0; 111 for (i = 0; i < person; i++) { 112 double total = a[i].math + a[i].phy + a[i].eng; /* 合計を計算*/ 113 double average = total / 3; /* 平均を計算*/ 114 printf("%-10d %-10s 合計:%3.1f 平均:%5.1f → GPA:%5.1f\n", 115 a[i].num, a[i].name, total, average, gpa(average)); 116 math_sum += a[i].math; math_sum2 += a[i].math * a[i].math; 117 phy_sum += a[i].phy; phy_sum2 += a[i].phy * a[i].phy; 118 eng_sum += a[i].eng; eng_sum2 += a[i].eng * a[i].eng; 119 } 120 double math_ave = math_sum / person; 121 double phy_ave = phy_sum / person; 122 double eng_ave = eng_sum / person; 123 124 double math_var = (math_sum2 - math_sum * math_ave * 2) / person 125 + math_ave * math_ave; 126 double phy_var = (phy_sum2 - phy_sum * phy_ave * 2) / person 127 + phy_ave * phy_ave; 128 double eng_var = (eng_sum2 - eng_sum * eng_ave * 2) / person 129 + eng_ave * eng_ave; 130 131 printf("math 合計:%5.1f 平均:%5.1f 分散:%5.1f 標準偏差:%f\n", 132 math_sum, math_ave, math_var, sqrt(math_var)); 133 printf("phy 合計:%5.1f 平均:%5.1f 分散:%5.1f 標準偏差:%f\n", 134 phy_sum, phy_ave, phy_var, sqrt(phy_var)); 135 printf("eng 合計:%5.1f 平均:%5.1f 分散:%5.1f 標準偏差:%f\n", 136 eng_sum, eng_ave, eng_var, sqrt(eng_var)); 137 138 Student **index = (Student **)malloc(sizeof(Student *) * person); 139 if (index == NULL) return; 140 for (int i = 0; i < person; i++) index[i] = &a[i]; 141 sort_by_num(index, person); 142 puts("--- sort by num ---"); 143 print_index(a, person, index); 144 sort_by_name(index, person); 145 puts("--- sort by name ---"); 146 print_index(a, person, index); 147 free(index); 148} 149 150int main(void) 151{ 152 Student std[NUMBER]; 153 int flag = 0; 154 do { 155 printf("ファイル書き込み-1 / ファイル読み込み-2 / 終了-0 :"); 156 scanf("%d", &flag); 157 if (flag == 1) 158 data_input(std); 159 else if (flag == 2) 160 data_output(std); 161 } while (flag != 0); 162 return 0; 163} 164

まだ直したいところがいっぱいあるけど。

追記

各個人の平均やGPAを用いたソートを行いたいのですが、

それなら、Student構造体の中に、平均や GPA を記録するメンバを追加しないとだめでしょう。

投稿2019/07/02 08:56

編集2019/07/02 12:38
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

学籍番号を用いたソートのように、各個人の平均やGPAを用いたソートを行いたいのですが、構造体を使っていないため?かstrcmp(a[j-1].num,a[j].num)<0の部分の書き方がわかりません。

a[j-1]の平均 と a[j]の平均 とを比べればいいんだから、

C

1int mean(Student s) { 2 return sのmath,phy,engを加えて3で割った値 3}

を用意して、if ( mean(a[j-1]) < mean(a[j]) ) ... ってやればよくね?

投稿2019/07/01 22:28

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

関数の返り値として、正常に読み込めたデータ数、もしくは書き込めたデータ数を返し、それを全体の人数として処理してはいかがですか?

追記1:元々意図していたことが伝わらなかったようなのでコード例を載せます。

C

1int data_input(Student a[]){ 2 ... 3 if ((fp=fopen("score.dat","w"))==NULL){ 4 printf("\aファイルをオープンできません。\n"); 5 return 0; 6 } 7 else{ 8 ... 9 fclose(fp); 10 return i; 11 } 12} 13 14void data_output(Student a[], int person){ 15 FILE *fp; 16 int i; 17 int average = 0; 18 ... 19} 20 21int main(void){ 22 ... 23 int nStudents = 0; 24 do{ 25 ... 26 if(flag==1) 27 nStudents = data_input(std); 28 else if(flag==2) 29 data_output(std, nStudents); 30 }while(flag != 0); 31 return 0; 32}

追記2:strcmp関数の仕様を調べ、それと類似するインターフェースを持つ関数を定義して差し替えれば解決します。

C

1// 使用側 2if (avecmp(&a[j-1], &a[j])<0) 3 swap_Student(&a[j-1],&a[j]); 4 5// 関数定義 6int avecmp(const void* p, const void* q){ 7 const Student *a = p, *b = q; 8 9 // 平均の大小は、科目数が同じ場合合計の大小と一致する 10 double diff = (a->math + a->phy + a->eng) - (b->math + b->phy + b->eng); 11 if(diff < 0) return -1; 12 if(diff > 0) return 1; 13 return 0; 14}

要するに、関数の内部でgpaなり平均を計算して、それを比較すればいいのです。

事後課題:qsortという関数を調べてみてください。謎仕様のインターフェースの意図が分かると思います。

投稿2019/06/30 06:32

編集2019/06/30 22:41
majiponi

総合スコア1720

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/07/01 00:42 編集

ソースコードを書き換えてみました。このようなことでよろしいのでしょうか。。 追記 そのように記述すればいいのですね!返り値を勘違いしておりました。 int data_input(Student a[])の return で エラー文、Void function 'data_input' should not return a value がでで動いてくれません。
majiponi

2019/07/02 11:28

data_inputの前のvoidはintに書き換えましたか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問