プロが教える店舗&オフィスのセキュリティ対策術

C言語で、番号・名前・国数英の点数を入力したら、それぞれの平均点と最高得点者(番号と名前)、合計の平均点と最高得点者(番号と名前)を表示するプログラムを作っています。
ここまで作ったのですが、合計の平均点と最高得点者、また、番号を表示させるにはどのようなプログラムにしたらいいでしょうか?
#include<stdio.h>

//教科の名前と短縮名
char *SubjectName[][2]={
{"国語","国"},
{"数学","数"},
{"英語","英"}
};

//教科の数(3)
#define SUBJECT_COUNT (sizeof(SubjectName)/sizeof(SubjectName[0]))

//教科の名前
typedef struct{
int id;//学籍番号
char name[40];//名前
int score[SUBJECT_COUNT];//点数(国、数、英)
}Student;

#define DATA_MAX 100
#define max(a,b) (a>b?a:b)
//データ数の最大、大きい方の値を返すマクロ

int main(void) {
int n;//生徒数
Student students[DATA_MAX];//最大100人まで
int subject_max[SUBJECT_COUNT];//各教科の最高得点
int subject_sum[SUBJECT_COUNT]={0};//各教科の合計点数
int i,j;

do{
printf("人数(最大%d人):",DATA_MAX);
scanf("%d",&n);
}while(n < 0 || n >= 100);

printf("\n番号、名前、各教科の点数を半角空白を開けて入力してください。\n\n");
printf("No 名前");
for(i=0;i<SUBJECT_COUNT;i++)printf(" %s",SubjectName[i][1]);
printf("\n------------------\n");

for(i=0;i<n;i++){//生徒数分
scanf("%d%39s", &students[i].id,students[i].name);//学籍番号と名前の入力
for(j=0;j<SUBJECT_COUNT;j++)scanf("%d",&students[i].score[j]);//各教科の点数の入力
if(i==0){
//一人目の時、各教科の最高得点を一人目の点数にする
for(j=0;j<SUBJECT_COUNT;j++)
subject_max[j]=students[i].score[j];
}else{
//二人目以降の時、各教科の最高得点を求める
for(j=0;j<SUBJECT_COUNT;j++)
subject_max[j]=max(subject_max[j],students[i].score[j]);
}
//各教科の合計点数に生徒の点数を加算
for(j=0;j<SUBJECT_COUNT;j++)subject_sum[j]+=students[i].score[j];
}

printf("\n教科 平均点 最高得点者\n");
printf("---------------------------\n");
for(i=0;i<SUBJECT_COUNT;i++){//教科数分
printf("%s %.2f ",SubjectName[i][0],(double)subject_sum[i]/n);
for(j=0;j<n;j++){//全生徒分
if(subject_max[i]==students[j].score[i]){
//最高得点と同じ点数の生徒の時
printf("%s ",students[j].name);
}
}printf("\n");
}

return 0;
}

〈実行例〉
人数(最大100人):3

番号、名前、各教科の点数を半角空白を開けて入力してください。

No 名前 国 数 英
------------------
10 山田 79 42 60
20 佐藤 79 62 80
30 山田 60 99 70

教科 平均点 最高得点者
---------------------------
国語 72.67 山田 佐藤
数学 67.67 山田
英語 70.00 佐藤

質問者からの補足コメント

  • つらい・・・

    すみません。間違えて山田が2人いてわかりずらいので30番は田中とします。

    No 名前 国 数 英語
    ---------------------
    10 山田 79 42 60
    20 佐藤 79 62 80
    30 山田 60 99 70

    教科 平均点 最高得点者
    ------------------------------
    国語 72.67 10:山田 20:佐藤
    数学 67.67 30:田中
    英語 70.00 20:佐藤
    ------------------------------
    合計 163.6 30:田中

    このような表示にしたいです。
    考えたのですがうまくできませんでした、、。

      補足日時:2022/05/22 18:57
  • すみません。いろいろ指定があってこのようなプログラムになってしまいました、、。
    本文のほうに補足しましたので、もしよろしければどのようにプログラムを修正したらよいか教えていただきたいです。

    No.1の回答に寄せられた補足コメントです。 補足日時:2022/05/22 19:00

A 回答 (4件)

生徒分の配列を用意


生徒ごとの合計点を計算し配列に格納
配列から合計値を算出し人数で割る → 合計点平均
配列から最大値を算出 → 合計点最大
配列から合計点最大に等しい要素を探す → 配列の位置(複数)
生徒配列から位置が同じ情報をとる → 最高得点者の学籍番号と名前
    • good
    • 0

補足ありがとうございました。


合計の平均は210.33ではないでしょうか。
    • good
    • 0

提示された実行例と同じ入力がされた場合、どのような出力結果を


期待していますか。それを提示してください。
それが提示されれば、No1のかたも、回答しやすくなるかと。
    • good
    • 1

分からん。


仕様がハッキリせんからなんとも言いようがないですね。
どういう形式で出力したいのか、ってのがサッパリ分からんので。

Tipsとしては、まず「main関数が大きすぎ」。
色々機能を盛りたいのなら、main関数一本槍で書くには負担が大きすぎます。
事実、混乱してるでしょ(笑)?
ここで一機能、そしてそのオチ、ってのが決まってるのなら、部分部分を関数化して小さな処理に分けるのがセオリー。

それから、最大値、最小値を求めたいのなら、ぶっちゃけ、stdlib.hのqsortを使った方が手間は少ないかな。

【C言語】qsort関数の使い方:
https://daeudaeu.com/c-qsort/

ガンガン、データを並べ替えて、その結果から目的のデータをピックアップしていった方が紛れはないと思います。

そんなトコかしらん。

頑張って下さい。
この回答への補足あり
    • good
    • 1

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング