身につくC言語-演習問題8回目 解答と解説-

問題は1問しかありませんでしたが、結構難しかったと思います。

じっくりと読み解いていってください。

最初に手で計算してみてください。

すると、国語の最高点数は「94」最低点数は「54」平均は「67.4」
数学の最高点数は「99」最低点数は「43」平均は「77.4」
国語と数学の合計点が一番高い人は出席番号「4」の人で94+99で「193」です。

ソースコード

main.cに全部まとめたコード


#include<stdio.h>
#define HITO 5

typedef struct {
	int max;
	int min;
	double avg;
}Sub;

Sub Main_Subject(Sub subject,int tensu[HITO]);
int Maxof(int tensu[HITO]);
int Minof(int tensu[HITO]);
double Avgof(int tensu[HITO]);
int Best_Tensu(int No,int tensu[3][HITO]);

int main(void)
{
	int tensu[3][HITO]={	{1,2,3,4,5},
							{64,55,70,94,54},
							{90,43,68,99,87}	};
	int No;
	Sub jpn;
	Sub math;
	
	jpn=Main_Subject(jpn,tensu[1]);
	math=Main_Subject(math,tensu[2]);
	No=Best_Tensu(No,tensu);
	
	printf("国語:%d,%d,%f\n",jpn.max,jpn.min,jpn.avg);
	printf("数学:%d,%d,%f\n",math.max,math.min,math.avg);
	printf("出席番号:%d,合計点数=%d\n",No,(tensu[1][No-1]+tensu[2][No-1]));
	
	return 0;
}
	
Sub Main_Subject(Sub subject,int tensu[HITO])
{
	subject.max=Maxof(tensu);
	subject.min=Minof(tensu);
	subject.avg=Avgof(tensu);
	
	return subject;	
}
int Maxof(int tensu[HITO])
{
	int i;
	int max=tensu[0];
	for(i=0;i<HITO;i++)
	{
		if(max<tensu[i])
		{
			max=tensu[i];
		}
	}
	return max;	
}

int Minof(int tensu[HITO])
{
	int i;
	int min=tensu[0];
	for(i=0;i<HITO;i++) { if(min>tensu[i])
		{
			min=tensu[i];
		}
	}
	return min;
}
double Avgof(int tensu[HITO])
{
	double sum=0;
	int i;
	for(i=0;i<HITO;i++)
	{
		sum+=tensu[i];
	}
	return sum/HITO;
}

int Best_Tensu(int No,int tensu[3][HITO])
{
	int sum[HITO];
	int best=0;
	int i,j;
	for(i=0;i<5;i++)
	{
		sum[i]=tensu[1][i]+tensu[2][i];
	}
	
	for(i=0;i<5;i++)
	{
		if(best<sum[i])
		{
			best=sum[i];
			No=i+1;
		}
	}
	return No;
}

かなり長いですが、少しずつ読み解いていきましょう。

 

まずは最初のインクルードの場所です。


#include
#define HITO 5

ここでは単純にstdio.hをインクルードしています。

 

HITOを5と置き換えて定数としています。

 

ですので、このプログラム中で
int a=HITO;
というようにすると、aには5が代入されます。

 


次は構造体です。

 


typedef struct {
	int max;
	int min;
	double avg;
}Sub;

typedefでSubという名前を付けています。

 

Subの中身は、英語や数学の最高点を格納するmax、最低点を格納するmin、平均を格納するavgです。

 


関数プロトタイプ宣言が続きます。

 


Sub Main_Subject(Sub subject,int tensu[HITO]);
int Maxof(int tensu[HITO]);
int Minof(int tensu[HITO]);
double Avgof(int tensu[HITO]);
int Best_Tensu(int No,int tensu[3][HITO]);

Main_Subjectからは構造体が返されています。

 

ということは、カラのSub型と、tensu[5]を渡すことで、最高点と最低点と平均を取得する関数を作成すればいいのです。

 

文字だけでは難しいのでイラストを描いてみます。

 

こんな感じのイメージを持っておくと理解しやすいです。


メイン関数はなるべくすっきりさせた方がいいです。


int main(void)
{
	int tensu[3][HITO]={	{1,2,3,4,5},
							{64,55,70,94,54},
							{90,43,68,99,87}	};
	int No;
	Sub jpn;
	Sub math;
	
	jpn=Main_Subject(jpn,tensu[1]);
	math=Main_Subject(math,tensu[2]);
	No=Best_Tensu(No,tensu);
	
	printf("国語:%d,%d,%f\n",jpn.max,jpn.min,jpn.avg);
	printf("数学:%d,%d,%f\n",math.max,math.min,math.avg);
	printf("出席番号:%d,合計点数=%d\n",No,(tensu[1][No-1]+tensu[2][No-1]));
	
	return 0;
}

ここで重要なのは、No、jpn、mathというのはそれぞれ何型なのかということです。

 

jpnとmathはSub型、Noはint型です。

 

tensu[][]は番号と国語の点数と数学の点数の配列です。

 

こんな感じ。

 

 

配列のどこに何があるのかをしっかりと意識してください。

 

その次のprintf3つは結果の出力用です。

 


次は、main関数から呼ばれる、Main_Subjectを詳しく見ていきます。

 


Sub Main_Subject(Sub subject,int tensu[HITO])
{
	subject.max=Maxof(tensu);
	subject.min=Minof(tensu);
	subject.avg=Avgof(tensu);
	
	return subject;	
}

ここの3つの関数を呼び出すという内容自体は簡単ですが、難しいのは引数です。(ここで引数はSub subjectとint tensu[HITO])

 

このMain_Subjectの内容を日本語で表してしまうと、

 

「5つの整数の、最大値と最小値と平均を取得しますよ。」

 

ということです。

 

例えば、main関数の「jpn=Main_Subject(jpn,tensu[1]);」をもう一度見てみましょう。

 

ここで引数はjpnとtensu[1]です。

 

tensu[1]というのは、上の画像を見てもらうとよくわかると思いますが5人の国語の点数ですよね。

 

それの最大値と最小値と平均を取得すると言うことです。

 

その次の「math=Main_Subject(math,tensu[2]);」というのは、tensu[2]が引数ですので、5人の数学の点数が渡され、mathに代入されるわけです。

 


簡単に最大値を取得するといっても、プログラムは勝手に最大値を取得してくれません。

 

もう少し詳しくプログラムを書く必要があります。


int Maxof(int tensu[HITO])
{
	int i;
	int max=tensu[0];
	for(i=0;i<HITO;i++)
	{
		if(max<tensu[i])
		{
			max=tensu[i];
		}
	}
	return max;	
}

これは、以前もやったと思いますが、5つの整数を順に比較していくプログラムです。

 

if文でいちばん大きい値を探していきます。

 

maxに代入された値がMain_Subjectに帰っていきます。


int Minof(int tensu[HITO])
{
	int i;
	int min=tensu[0];
	for(i=0;i<HITO;i++) { if(min>tensu[i])
		{
			min=tensu[i];
		}
	}
	return min;
}

Minofも同じような理屈です。

 

 


平均はMaxofやMinofよりも簡単です。


double Avgof(int tensu[HITO])
{
	double sum=0;
	int i;
	for(i=0;i<HITO;i++)
	{
		sum+=tensu[i];
	}
	return sum/HITO;
}

気を付けるところは、引数がint型の配列で、戻り値がdouble型だというところくらいです。

 


ここは、Main_Subectから呼び出される関数ではなく、main関数から直接呼び出されます。(上記の画像を参照)

 

Maxof,Minof,Avgofよりは難しいでしょう。



int Best_Tensu(int No,int tensu[3][HITO])
{
	int sum[HITO];
	int best=0;
	int i,j;
	for(i=0;i<5;i++)
	{
		sum[i]=tensu[1][i]+tensu[2][i];
	}
	
	for(i=0;i<5;i++)
	{
		if(best<sum[i])
		{
			best=sum[i];
			No=i+1;
		}
	}
	return No;
}

Maxofでは5つの整数しか引数ではありませんでしたが、Best_Tensuでは5×3つの整数を引数とします。(出席番号も、国語の点数も数学の点数も全部が引数ということです。)

 

今回はsum[5]という新しく作った変数に、それぞれの国語と数学の点数の合計を格納し、比較するという方法をとりました。

 

sumに5人の国語と数学の合計を格納したら、Maxofと同じ要領で最大値を探していきます。

 

そのときに、for文でiを使うと思います。

 

iは0~4の値をとっていきます。

 

ということは、最大値をとったときのiの値が「出席番号-1」の値をとります。

 

なので、No=i+1;と書いています。

 


最後はheader.hを作成するだけです。

 

さっき作成したプログラムから


#define HITO 5

typedef struct {
	int max;
	int min;
	double avg;
}Sub;

Sub Main_Subject(Sub subject,int tensu[HITO]);
int Maxof(int tensu[HITO]);
int Minof(int tensu[HITO]);
double Avgof(int tensu[HITO]);
int Best_Tensu(int No,int tensu[3][HITO]);

を取り出して貼り付けます。

 

取り出したさっきのプログラムの#include stdio.h の下にinclude”header.h”を追加するだけです。

 


これで詳しく説明できたと思います。

 

もう一つ補足するとすれば「printf(“出席番号:%d,合計点数=%d\n”,No,(tensu[1][No-1]+tensu[2][No-1]));」の部分でしょうか。

 

とくに(tensu[1][No-1]+tensu[2][No-1])という部分が難しいと感じるでしょう。

 

実際にNoに値を入れて考えてみると簡単です。

 

ここでのNoは「4」なので(tensu[1][3]+tensu[2][3])となります。

 

上の画像をみて確かめてください。

 

出席番号4の生徒の国語の点数と数学の点数をさしています。

 

これを足しているということは出席番号4の人の合計点数をえることができます。

 

5000文字近くなってしまいましたが、これで説明は終わりです。

 

答えは

国語:94,54,67.400000
数学:99,43,77.400000
出席番号:4,合計点数=193

となれば正解です。