• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:質問ですが)

C言語で名前と点数を入力して合計と平均を求めるプログラム

このQ&Aのポイント
  • C言語を使用して名前と点数を入力し、合計と平均を求めるプログラムを作成する方法について教えてください。
  • main関数をすっきりさせるために、情報入力関数、合計を求める関数、平均を求める関数を作成する方法について教えてください。
  • 作成したC言語プログラムで入力した名前と点数を表形式で表示し、平均点も同時に表示する方法について教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • BLK314
  • ベストアンサー率55% (84/152)
回答No.3

こんな感じでどうでしょうか? === ここからソース ============================================== // Seiseki.cpp : コンソール アプリケーションのエントリ ポイントを定義します。 // #include "stdafx.h" // 配列の要素数を計算するマクロです // 毎回sizeof()で書くより // プログラムがわかりやすくなります #define ARRAY_OF(a) (sizeof (a) / sizeof (a[0])) // 人数を定義します #define STUDENT_COUNT 5 // 成績を格納する領域です // 構造体配列でも作れますが、教科を通じての合計を取るのであれば // 2次元配列のほうが適しています // 各教科のインデックス #define JAPANEASE 0 // 国語 #define ENGLISH 1 // 英語 #define MATHEMATICS 2 // 数学 // 各教科名を格納しておきます // 各教科のインデックス順に並んでいなければなりません static char* SubjectName[] = {"国語", "英語", "数学"}; // 個人の成績用構造体です // 各教科毎に別のフィールドにせず // 配列にしたほうが // 合計や平均をとる関数がすっきりします #define MAX_NAME_LENGTH 15 // 氏名の最大長です struct student { char Name[MAX_NAME_LENGTH + 1]; // 氏名 int Score[ARRAY_OF (SubjectName)]; // 各教科の得点 }; // データ格納域 // 2次元配列です // 1次元目で生徒を識別します // 2次元目で科目を識別します static struct student person[STUDENT_COUNT]; // 合計を求める汎用関数です // int型専用です static int GetTotalInt(int Data[], int Count) { int s = 0; int i; for (i = 0; i < Count; ++i) { s += Data[i]; } return s; } // 合計を求める汎用関数です // doble型専用です static double GetSumDoble(double data[], int Count) { int i; double s = 0; for (i = 0; i < Count; ++i) { s += data[i]; } return s; } // 指定教科の合計点を求めます static int GetSubjectsTotal(int SubjectNo) { int s = 0; // 合計用 int i; // 生徒用 for (i = 0; i < ARRAY_OF(person); ++i) { s += person[i].Score[SubjectNo]; } return s; } // 指定教科の平均点を求めます static double GetSubjectsAverage(int SubJectNo) { return GetSubjectsTotal(SubJectNo) * 1.0 / (ARRAY_OF(person)); } // 成績を入力させる関数です void InputData() { int i; // 生徒数分データを入力させます // ARRAY_OFにより人数を計算しているので // 生徒数が変わっても、 // ここは全く変更の必要がないことに注目してください for (i = 0; i < ARRAY_OF (person); ++i) { int j; printf("Student No.%d \n", i + 1); printf("Name? "); scanf("%s", person[i].Name); // 各教科の得点を入力させます // 各教科の得点を配列にしたことで // ARRAY_OFによる教科数の計算が可能になりました // 教科の名称をテーブル化したことで // 教科に増減・変更があっても // ここの部分は全く変更を受けません for (j = 0; j < ARRAY_OF (person[0].Score); j++) { printf("%s? ", SubjectName[j]); scanf("%d", &(person[i].Score[j])); } } } // 成績を表示します static void DisplayScore() { int i; double Ave[ARRAY_OF (SubjectName)]; // 教科毎の平均値格納用 printf("名前 "); // 教科名を列挙します for (i = 0; i < ARRAY_OF (SubjectName); i++) { printf("%s ", SubjectName[i]); } printf("\n"); // 生徒の成績を合計とともに表示します for (i = 0; i < ARRAY_OF (person); i++) { int j; // 氏名を表示します printf("%15s ", person[i].Name); // 教科別の得点を表示します for (j = 0; j < ARRAY_OF (person[0].Score); j++) { printf("%3d ", person[i].Score[j]); } // 合計を表示し改行します printf("%3d\n", GetTotalInt(person[i].Score, ARRAY_OF (person[0].Score))); } // 各教科の平均点を表示します // 平均の合計を取りやすくするため、一旦配列に格納します printf("平均 "); for (i = 0; i < ARRAY_OF (person[0].Score); i++) { Ave[i] = GetSubjectsAverage(i); printf("%.1f ", Ave[i]); } // 平均の合計を表示します printf("%.1f", GetSumDoble(Ave, ARRAY_OF(Ave))); } int main(int argc, _TCHAR* argv[]) { // 成績を入力させます InputData(); // 結果を表示します DisplayScore(); return 0; } ===================== ここまで ソース ===================== ポイントは 各関数の役割分担を明確にすること 各関数に必要以上の知識を持ちこませないこと 各関数には役割にふさわしい名前をつけること です。 例えば、教科毎の合計を求める関数では 各人のデータが分かればよいのです。 具体的な教科名を知る必要性は全くないです。 そのためには、jpn, engといった教科と結びついた変数でなく 配列を使うのです。 配列を使うことで具体的な教科を隠し、 単なる得点データへと抽象化します。 抽象化することで教科と分離されたので 教科が変更になっても (例えば 国語の代わりに理科を入れる) 変更は最小限で済みます 教科ごとの集計関数などは全く影響を受けず、 プログラム的にもスッキリします。

takoppachi
質問者

お礼

ありがとうございます。 これを参考にしてがんばってみます。

その他の回答 (2)

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.2

main関数とは別の関数を作って、main関数からその関数を呼び出す、 という形のコードをこれまでに書かれたことはありますか?

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

ハードコピーにマーカーで「ここはデータを入力してるところ」とか「ここで計算してる」とか書いて, それぞれを関数に切り出せばいいだけだと思う.

関連するQ&A