教えていただきたいのですが、C言語で名前と点数を入力して合計と平均を求めるというプログラムを作ったのですが、
main関数の中で情報入力、合計と平均の計算をしているのでそれぞれ入力関数、合計を求める関数、平均を求める関数というものを作ってmain関数をすっきりとさせたいのですがどうすればいいですか?
#include <stdio.h>
typedef struct{
char name[15];
int jpn;
int eng;
int math;
int sum;
} stdent;
typedef struct{
double sum;
double jpn;
double eng;
double math;
} Score;
void maxmin(stdent *, int);
main()
{
int i, n;
n = 5;
stdent person[n];
Score average;
average.jpn = 0;
average.eng = 0;
average.math = 0;
average.sum = 0;
for(i = 0; i < n; i++)
{
printf("Student No.%d \n",i + 1);
printf("Name? ");
scanf("%s", person[i].name);
printf("Japanese? ");
scanf("%d", &(person[i].jpn));
printf("English? ");
scanf("%d", &(person[i].eng));
printf("Math? ");
scanf("%d", &(person[i].math));
printf("\n");
person[i].sum = person[i].jpn + person[i].eng + person[i].math;
average.jpn += person[i].jpn;
average.eng += person[i].eng;
average.math += person[i].math;
average.sum += person[i].sum;
}
average.jpn /= n;
average.eng /= n;
average.math /= n;
average.sum /= n;
printf(" 名前 国語 英語 数学 \n");
printf("------------------------------------\n");
for(i = 0; i < n; i++)
{
printf("%8s %3d %3d %3d %3d\n", person[i].name, person[i].jpn, person[i].eng, person[i].math, person[i].sum);
}
printf("------------------------------------\n");
printf("平均 %.1lf %.1lf %.1lf %.1lf\n\n", average.jpn,average.eng,average.math,average.sum);
return 0;
}
No.3ベストアンサー
- 回答日時:
こんな感じでどうでしょうか?
=== ここからソース ==============================================
// Seiseki.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//
#include "stdafx.h"
// 配列の要素数を計算するマクロです
// 毎回sizeof()で書くより
// プログラムがわかりやすくなります
#define ARRAY_OF(a) (sizeof (a) / sizeof (a[0]))
// 人数を定義します
#define STUDENT_COUNT5
// 成績を格納する領域です
// 構造体配列でも作れますが、教科を通じての合計を取るのであれば
// 2次元配列のほうが適しています
// 各教科のインデックス
#define JAPANEASE0// 国語
#define ENGLISH1// 英語
#define MATHEMATICS2// 数学
// 各教科名を格納しておきます
// 各教科のインデックス順に並んでいなければなりません
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といった教科と結びついた変数でなく
配列を使うのです。
配列を使うことで具体的な教科を隠し、
単なる得点データへと抽象化します。
抽象化することで教科と分離されたので
教科が変更になっても
(例えば 国語の代わりに理科を入れる)
変更は最小限で済みます
教科ごとの集計関数などは全く影響を受けず、
プログラム的にもスッキリします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語(構造体) 3 2022/07/05 20:08
- C言語・C++・C# C言語 プログラミング 4 2022/05/22 11:53
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# c言語でユーザ関数を利用して複素数のべき乗と絶対値の数列を計算するプログラムが作りたいです。 3 2023/01/29 22:13
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# C言語階乗の総和を求める 2 2023/03/04 23:31
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
printf で二進表示を行いたい。
-
10個出力で改行したいのですが...
-
コマンドラインに出力した文字...
-
ブラックジャック
-
C言語で、「自然数nを入力し、n...
-
error C2143: 構文エラー : ';'...
-
scanfに文字が入力されたときに...
-
4の倍数を論理演算で表す。。
-
縦の棒グラフ
-
パスカルの三角形についてのCプ...
-
(C言語)めちゃくちゃな値にな...
-
ピラミッド表示プログラム。
-
C言語 ツェラーの公式を使った...
-
CTRL+Dでループを抜けるには
-
勝率をプログラムに
-
Visual Sutdio 2017 でのC言語...
-
%P と %X の違い
-
printf( " %2d", p * q );
-
C言語 プログラミング ごめんな...
-
printf()文の書式
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
10個出力で改行したいのですが...
-
既約分数の表示プログラム
-
printf で二進表示を行いたい。
-
8人分のテストの点数を入力し、...
-
printf( " %2d", p * q );
-
strcmp
-
CTRL+Dでループを抜けるには
-
4の倍数を論理演算で表す。。
-
%P と %X の違い
-
【C言語教えてください】sin波...
-
c言語でAからZまでを表示する...
-
cshの文字列操作(0埋め)
-
万年カレンダーのC言語プログラ...
-
コマンドラインに出力した文字...
-
scanfに文字が入力されたときに...
-
コンパイルエラーについて
-
ホームページをC言語で作りたい...
-
改行について 1行に何個かづ...
-
台形の面積を求めるプログラム
-
なぜgccはstdio.hをインクルー...
おすすめ情報