ページ 11

配列について

Posted: 2014年9月18日(木) 10:59
by NKS
初めまして、投稿させていただきます。
c言語の課題で配列で成績処理をするプログラムを作っています。
内容は、点数を入力していき、その合計点と平均点を出力して、
優:100~80点
良:79~70点
可:69~60
不可:60点未満
の基準で 優 良 可 不可 と判断し、それぞれの人数の合計を
出力するプログラムを作っています。
プログラムを作ってコンパイルし、実行したたところ、
優 良 可 不可 のカウントがきちんとされていません。
合計点と平均点の出力はきちんと出るのですが、
その部分だけカウントされません。
どこをどのように直したらカウントされるようになるのかを教えてください。

コード:

#include<stdio.h>

#define NUM 100

int main(void)
{
	int i,j,tmp;
	int sum = 0;
	int ten[NUM];
	int yu,ryo,ka,hu;
	
	printf("成績処理を行います。終了するときは999を入力してください。\n");
	yu = 0;
	ryo = 0;
	ka = 0;
	hu = 0;
	i=0;
	while(i<NUM){
		printf("No.%d: ",i+1);
		scanf("%d",&ten[i]);    //点数の入力
		if(ten[i] == 999){   //999が入力されると終了
			break;
		}else if(ten[i] >= 0 && ten[i] <= 100){ //0~100点以内が入力されれば合計に加算
			sum += ten[i];
			i++;
		}else{               //そうでなければもう一回入力
			printf("正しい数値を入力してください。\n");
		}
	  for(j=0;j<NUM;j++)
	  if(ten[i] < 60){      //60点未満なら不可の人数に加算
		hu++;
	  }else if(ten[i]<=69){
		ka++;        //69点以下なら可に加算
	  }else if(ten[i]<=79){    
		ryo++;       //79点以下なら良に加算
	  }else{
		yu++;        //それ以外なら優に加算
	}
	}
	
	printf("%d人の処理結果\n",i);
	printf("合計点:%d\n",sum);
	printf("平均点:%.2f\n",(double)sum/i);
	printf("「優」の数%d人\n",yu);
	printf("「良」の数%d人\n",ryo);
	printf("「可」の数%d人\n",ka);
	printf("「不可」の数%d人\n",hu);
	
	return 0;
}

Re: 配列について

Posted: 2014年9月18日(木) 11:17
by みけCAT
・コード中の全角スペースを全て消すか、半角スペースに置換してください。
・29行目のfor文が不要(蛇足)なので、消してください。
・25行目でi++;しているので、30~34行目の判定で正しいデータが利用できていません。
 30行目、32行目、34行目のtenを全てten[i-1]にしてください。
・コードのインデントが乱れています。適切なインデントにすることを推奨します。

Re: 配列について

Posted: 2014年9月18日(木) 11:21
by NKS
返信ありがとうございます。
課題ではfor文を使って処理せよとのことなのですが、for文を使用する場合、どうしたらいいでしょうか?

Re: 配列について

Posted: 2014年9月18日(木) 11:25
by みけCAT
NKS さんが書きました:返信ありがとうございます。
課題ではfor文を使って処理せよとのことなのですが、for文を使用する場合、どうしたらいいでしょうか?
一番単純な方法は、while(i<NUM)をfor(;i<NUM;)に書き換えることです。

真面目にやるならば、読み込んだデータをその場で加算やカウントするのではなく、
読み込みが終了してからfor文を用いて加算やカウントを行います。

Re: 配列について

Posted: 2014年9月18日(木) 11:53
by NKS
完成しました!
ありがとうございます!!
またよろしくお願いします。

Re: 配列について

Posted: 2014年9月18日(木) 11:56
by NKS
すみません、なぜ30、32、34行目のtenをten[-1]にしたらできたのか解説お願いします。

Re: 配列について

Posted: 2014年9月18日(木) 12:05
by みけCAT
NKS さんが書きました:すみません、なぜ30、32、34行目のtenをten[-1]にしたらできたのか解説お願いします。

まず、ten[-1]にしてもできないはずです。範囲外アクセスになります。

例えば、20行目でi=1で、10が入力されたとします。
すると、ten[1]に10が代入されます。
21行目の条件10 == 999は偽なので、次に23行目が実行されます。
23行目の条件10 >= 0 && 10 <= 100は真なので、次に24行目と25行目が実行されます。
25行目の効果で、i=2になります。ten[2]はまだ値を設定していないので、不定です。
その後30行目が実行されます。この時点でi=2であり、tenすなわちten[2]は不定です。
32行目、34行目の判定でも同様です。
ここで、30行目でtenの代わりにten[i-1]にすると、これはten[2-1]すなわちten[1]なので、
先ほど入力した10との比較が行われます。

オフトピック
この解説を書いている時、
0~100位外の点数が入力されるとカウントがおかしくなりそうであることに気がつきました。

Re: 配列について

Posted: 2014年9月18日(木) 16:29
by NKS
詳しくおしえていただきありがとうございます。
101と100以上の数字を入力したときカウントが加算されおかしくなりました。
そこの対策も良ければ教えていただけないでしょうか?

Re: 配列について

Posted: 2014年9月18日(木) 16:33
by みけCAT
NKS さんが書きました:詳しくおしえていただきありがとうございます。
101と100以上の数字を入力したときカウントが加算されおかしくなりました。
そこの対策も良ければ教えていただけないでしょうか?

コード:

printf("正しい数値を入力してください。\n");
の次の行にcontinue; (今回のループの処理を打ち切り、ループのブロックの最終行の次の処理へジャンプする)を入れてください。

Re: 配列について

Posted: 2014年9月18日(木) 16:57
by NKS
できました!
ありがとうございます、また機会があればよろしくお願いします。

Re: 配列について

Posted: 2014年9月18日(木) 17:12
by みけCAT
NKS さんが書きました:できました!
ありがとうございます、また機会があればよろしくお願いします。
おめでとうございます。
完成したコードを提示していただけると助かります。

Re: 配列について

Posted: 2014年9月19日(金) 00:32
by NKS
了解です。
こちらが完成したプログラムです。

コード:

#include<stdio.h>

#define NUM 100

int main(void)
{
	int i,tmp;
	int sum = 0;
	int ten[NUM];
	int yu,ryo,ka,hu;
	
	printf("成績処理を行います。終了するときは999を入力してください。\n");
	yu = 0;									//初期値の設定
	ryo = 0;
	ka = 0;
	hu = 0;
	i=0;
	while(i<NUM){
		printf("No.%d: ",i+1);
		scanf("%d",&ten[i]);
		if(ten[i] == 999){  //999が入力されたら終了
			break;
		}else if(ten[i] >= 0 && ten[i] <= 100){ //もし0~100点が入力されたら加算
			sum += ten[i];
			i++;       //次の人の点数
		}else{
			printf("正しい数値を入力してください。\n");
			continue; //今回のループの処理を打ち切りループのブロックの最終行の次の処理へ
		}
	  if(ten[i-1] < 60){
		hu++;		//60点未満なら不可にカウント
	
	  }else if(ten[i-1]<=69){
		ka++;		//69点以下なら可にカウント
		
	  }else if(ten[i-1]<=79){
		ryo++;		//79点以下なら良にカウント
		
	  }else{
		yu++;		//それ以上は優にカウント
	}
	}
	
	printf("%d人の処理結果\n",i);
	printf("合計点:%d\n",sum);
	printf("平均点:%.2f\n",(double)sum/i);
	printf("「優」の数%d人\n",yu);
	printf("「良」の数%d人\n",ryo);
	printf("「可」の数%d人\n",ka);
	printf("「不可」の数%d人\n",hu);
	
	return 0;
}

Re: 配列について

Posted: 2014年9月19日(金) 00:35
by みけCAT
ありがとうございます。
NKS さんが書きました:課題ではfor文を使って処理せよとのことなのですが
という条件があったはずですが、結局for文を使わなくても大丈夫だったのでしょうか?

Re: 配列について

Posted: 2014年9月19日(金) 00:42
by NKS
そうでした。
for文を使ってプログラムする課題でした。
すみません、ありがとうございます。
for文を使用するといたらどこにどういう文を追加したらよろしいでしょうか?

Re: 配列について

Posted: 2014年9月19日(金) 00:56
by みけCAT
18行目の while(i<NUM) を for(;i<NUM;) に書き換えるだけで、for文を使ったプログラムになります。

Re: 配列について

Posted: 2014年9月19日(金) 01:06
by NKS
すみません、書き込むの忘れてました。
データ入力はwhile文でデータ処理はfor文を使うとのことです。
要望が多くてすみません。

Re: 配列について

Posted: 2014年9月19日(金) 08:12
by みけCAT
NKS さんが書きました:すみません、書き込むの忘れてました。
データ入力はwhile文でデータ処理はfor文を使うとのことです。
要望が多くてすみません。
では、まずデータが既に与えられている状態で、for文を使ったデータ処理プログラムを書くことはできますか?

コード:

#include<stdio.h>

#define NUM 100

int main(void)
{
	int i = 10,tmp;
	int sum = 0;
	int ten[NUM] = {59, 59, 59, 60, 79, 80, 100, 65, 0, 23};
	int yu,ryo,ka,hu;
	
	// ここにfor文を使って成績処理を行うプログラムを書く
	
	printf("%d人の処理結果\n",i);
	printf("合計点:%d\n",sum);
	printf("平均点:%.2f\n",(double)sum/i);
	printf("「優」の数%d人\n",yu);
	printf("「良」の数%d人\n",ryo);
	printf("「可」の数%d人\n",ka);
	printf("「不可」の数%d人\n",hu);
	
	return 0;
}

Re: 配列について

Posted: 2014年9月19日(金) 16:40
by NKS
これで正しいかはわかりませんが作ることができました。

コード:

#include<stdio.h>
 
#define NUM 100
 
int main(void)
{
    int i = 10;
    int sum = 0;
    int ten[NUM] = {59, 59, 59, 60, 79, 80, 100, 65, 0, 23};
    int yu,ryo,ka,hu;
    
	yu = 0;
	ryo = 0;
	ka = 0;
	hu = 0;
    for(i = 0;i <= 9;i++){// ここにfor文を使って成績処理を行うプログラムを書く
		if(ten[i] < 60){
			hu++;
			sum += ten[i];
		}else if(ten[i] <= 69){
			ka++;
			sum += ten[i];
		}else if(ten[i] <= 79){
			ryo++;
			sum += ten[i];
		}else{
			yu++;
			sum += ten[i];
		}
    }
    
    printf("%d人の処理結果\n",i);
    printf("合計点:%d\n",sum);
    printf("平均点:%.2f\n",(double)sum/i);
    printf("「優」の数%d人\n",yu);
    printf("「良」の数%d人\n",ryo);
    printf("「可」の数%d人\n",ka);
    printf("「不可」の数%d人\n",hu);
    
    return 0;
}

Re: 配列について

Posted: 2014年9月19日(金) 17:53
by みけCAT
for文の前後でiの値が変わらないようにしてください。
すなわち、for文ではiではなく別のループ変数を使用し、0から(i-1)までのループを回します。

それができたら、iの初期化をi=10からi=0に戻し、No: 12の入力処理(sum,hu,ka,ryo,yuの更新を除く)をその上に追加すればできるはずです。

Re: 配列について

Posted: 2014年9月19日(金) 21:11
by NKS
了解です。やってみます。
ありがとうございました。