ページ 1 / 1
無題
Posted: 2008年11月18日(火) 22:37
by 初心者
n人の学生の名前と英語,国語,数学の点数を読み込み,各人の3科
目の合計点,また各教科の平均点と標準偏差を計算して出力するプログラムを
作れという問題で下記のように作りました。
linuxとgccをつかってます。
実行できるのですがもっとコンパクトなプログラムにできないでしょうか?
最近関数を習ったのでそれを使うのではないかとおもうのですがよくわから
ないので教えてもらえるとありがたいです。
forの部分とかまとめられますか?
#include<stdio.h>
#include<math.h>
#define N 50
main()
{
int eng[N], jap[N], math[N], sum, n=0, i;
char name[N][12];
double SUM, sum1, sum2, sum3, ave1, ave2, ave3, vari, s_devi;
while(scanf("%s %d %d %d",&name[n][0],&eng[n],&jap[n],&math[n]) != EOF)
{
sum=0;
sum = eng[n]+jap[n]+math[n];
sum1 += eng[n];
sum2 += jap[n];
sum3 += math[n];
printf("name , sum : %-12s %4d\n",name[n], sum);
n++ ;
}
ave1 = sum1/n;
ave2 = sum2/n;
ave3 = sum3/n;
for(SUM=0,i=0; i<n; i++)
{
SUM += (eng-ave1)*(eng-ave1);
}
vari = SUM/n;
s_devi = sqrt(vari);
printf("English\naverage = %.2f\nstandard deviation = %.2f\n\n",ave1,s_devi);
for(SUM=0,i=0; i<n; i++)
{
SUM += (jap-ave2)*(jap-ave2);
}
vari = SUM/n;
s_devi = sqrt(vari);
printf("japanese\naverage = %.2f\nstandard deviation = %.2f\n\n",ave2,s_devi);
for(SUM=0,i=0; i<n; i++)
{
SUM += (math-ave3)*(math-ave3);
}
vari = SUM/n;
s_devi = sqrt(vari);
printf("math\naverage = %.2f\nstandard deviation = %.2f\n\n",ave3,s_devi);
}
Re:無題
Posted: 2008年11月18日(火) 23:57
by ムンバ
Re:無題
Posted: 2008年11月19日(水) 00:10
by ムンバ
ちなみに
n人の学生の名前と英語,国語,数学の点数を読み込み,各人の3科
目の合計点,また各教科の平均点と標準偏差を計算して出力するプログラムを
作れという問題で下記のように作りました。
linuxとgccをつかってます。
で検索しても、上記と同じ様な結果(1件マイナス)が出ました。<by yahoo
どうしてなんでしょうか?^^;
Re:無題
Posted: 2008年11月19日(水) 02:17
by Dixq (管理人)
まず投稿前に規約をお読みになり、コードはタグを使い、トピには題名をつけて下さいね。
コードは変数名が重複している部分が多いですね。
ある変数をセットで使うなら構造体が便利です。
もし構造体についてご存じなければググって下さい。
コードはなるべく変えないように修正しました。
sum0, sum1, sum2は配列にして3回ループにすればさらに省けますね。
#include<stdio.h>
#include<string.h>
#include<math.h>
/* 登録人数最大数 */
#define N 50
/* 生徒のスコアデータ */
typedef struct{
int SubScore[3]; //教科別スコア
char Name[64]; //名前
double Average; //平均
}StudentData_t;
/* 教科別スコアデータ */
typedef struct{
char Name[12]; //教科名
double Average; //平均
double StdDev; //標準偏差
}SubScoreData_t;
int main(){
int n=0, i , s;
int sum;
double sum0, sum1, sum2;
double Val, SubSum;
StudentData_t StudentData[N] ={0,};
SubScoreData_t SubScoreData[3] ={0,};
/* 名前代入 */
strcpy(SubScoreData[0].Name, "English");
strcpy(SubScoreData[1].Name, "Japanese");
strcpy(SubScoreData[2].Name, "Math");
/* 初期化 */
sum0 = sum1 = sum2 = 0;
/* 代入しながらループ */
while( scanf("%s %d %d %d",
StudentData[n].Name,
&StudentData[n].SubScore[0],
&StudentData[n].SubScore[1],
&StudentData[n].SubScore[2] ) != EOF )
{
/* 3教科の合計 */
sum = StudentData[n].SubScore[0] + StudentData[n].SubScore[1] + StudentData[n].SubScore[2];
/* 各教科のスコアの加算 */
sum0 += StudentData[n].SubScore[0];
sum1 += StudentData[n].SubScore[1];
sum2 += StudentData[n].SubScore[2];
printf("name , sum : %-12s %4d\n", StudentData[n].Name, sum);
n++ ;
}
/* 平均の計算 */
SubScoreData[0].Average = sum0 / n;
SubScoreData[1].Average = sum1 / n;
SubScoreData[2].Average = sum2 / n;
/* 3教科分ループ */
for(s=0; s<3; s++)
{
/* 人数分ループ */
for(SubSum=0,i=0; i<n; i++)
{
SubSum += (StudentData.SubScore - SubScoreData.Average)
* (StudentData.SubScore - SubScoreData.Average) ;
}
Val = SubSum / n ;
SubScoreData.StdDev = sqrt(Val);
printf("%s\naverage = %.2f\nstandard deviation = %.2f\n\n",
SubScoreData.Name, SubScoreData.Average, SubScoreData.StdDev);
}
return 0;
}
Re:無題
Posted: 2008年11月19日(水) 02:19
by Dixq (管理人)
>ムンバさん
以前そのURLにその類の質問があったのでしょう。
その後規約違反か何かで削除されたのでしょう。
タイムラグで検索データベースに残ってただけじゃないでしょうか。
Re:無題
Posted: 2008年11月19日(水) 09:58
by ムンバ
おはようございます。
そういう事でしたか。すみません、余計な事を。^^;
質問があったのですが、もう少し考えてみます。w
また、宜しくお願いします。
すみません
Posted: 2008年11月19日(水) 14:04
by 初心者
構造体について調べてよくわからなかったので
大学の先生に質問したら構造体というのは使わないで作れといわれました。
プログラムを見せたら、
もっとまとめられるといわれましたが詳しく教えてくれませんでした。
構造体を使わないでまとめられませんか?
Re:すみません
Posted: 2008年11月19日(水) 14:17
by Mist
ん~、こういうことかな。
eng[N], jap[N], math[N]
を
seiseki[3][N]
とする。
seiseki[0] 英語
seiseki[1] 国語
seiseki[2] 数学
これでプログラム後半の標準偏差のところを
int kyouka;
for (kyouka = 0; kyouka < 3; kyouka++) {
// 標準偏差の計算を行う
}
とすればかなり短くなると思います。
Re:すみません
Posted: 2008年11月19日(水) 14:28
by non
もしくは、点数の配列はそのままで、
標準偏差を計算する関数を作って、3回呼び出すのかも。
同じような処理が3回ですからね。
Re:すみません
Posted: 2008年11月19日(水) 14:36
by 御津凪
> 最近関数を習ったので
とありましたので関数にまとめたものを作ってみました。
void show_ave_sdiv( const int* points, int n, const char* coursename ){
double ave, pt, ssum, sdiv;
int i,sum;
for(i = 0;i < n;++i){
sum += points;
}
ave = sum / (double)n;
for(i = 0,ssum = 0;i < n;++i){
pt = points - ave;
ssum += pt*pt;
}
sdiv = sqrt(ssum / n);
printf("%s\naverage = %.2f\nstandard deviation = %.2f\n\n",coursename,ave,sdiv);
}
教科の各点数の配列、人数、教科名を引数とし、
その教科の平均点と標準偏差を計算、出力する関数です。
コンパイルチェックはしていませんので注意。
# 利用する場合はちゃんと理解してからじゃないと、先生に聞かれたときが大変です。
Re:すみません
Posted: 2008年11月19日(水) 14:48
by Dixq (管理人)
う~ん、授業以上のことを知ってるならそれで作ってもいいと思いますが・・。
こうなるとポインタ使うなconst使うなとか言われそうですね。
とりあえず上にも書いたとおり、
同じような変数が3つあるので配列にしてループさせるだけでいいと思いますよ。
Re:すみません
Posted: 2008年11月19日(水) 15:02
by バグ
試しに、なんでもかんでも関数化してみました(^_^;)
#include<stdio.h>
#include<math.h>
#define N 5
/* プロトタイプ宣言 */
int calcSum(int eng, int jap, int math);
double calcAvg(int* score, int count);
double calcStandardDeviation(int *score, int count);
/* メイン関数 */
int main()
{
char name[N][12];
int eng[N], jap[N], math[N], i;
for (i = 0; i < N; ++i)
{
/* 文字列の入力 */
scanf("%s %d %d %d", name, &eng, &jap, &math);
/* 入力データと合計値の表示 */
printf("name , sum : %-12s %4d\n\n", name, calcSum(eng, jap, math));
}
/* 計算結果の表示 */
printf("English\naverage = %.2f\nstandard deviation = %.2f\n\n", calcAvg(eng, i), calcStandardDeviation(eng, i));
printf("Japanese\naverage = %.2f\nstandard deviation = %.2f\n\n", calcAvg(jap, i), calcStandardDeviation(jap, i));
printf("Math\naverage = %.2f\nstandard deviation = %.2f\n\n", calcAvg(math, i), calcStandardDeviation(math, i));
return 0;
}
/* 3教科の合計値の計算 */
int calcSum(int eng, int jap, int math)
{
return eng + jap + math;
}
/* 平均値の計算 */
double calcAvg(int* score, int count)
{
int i, sum = 0;
for (i = 0; i < count; ++i)
{
sum += *(score + i);
}
return (double)(sum) / (double)(count);
}
/* 標準偏差の計算 */
double calcStandardDeviation(int *score, int count)
{
int i;
double sum = 0.0, avg = calcAvg(score, count);
for (i = 0; i < count; ++i)
{
sum += pow(*(score + i) - avg, 2.0);
}
return sqrt(sum / (double)count);
}
Re:すみません
Posted: 2008年11月19日(水) 15:09
by non
なるべく初心者さんがわかりやすいように変更をすくなくして、標準偏差だけを関数にしました。
double StandardDeviation(int n,int ten[/url],double ave)
{
double sd=0;
int i;
for(i=0; i<n; i++) {
sd += (ten-ave)*(ten-ave);
}
sd = sqrt(sd/n);
return sd;
}
関数呼び出しは
printf("English\naverage = %.2f\nstandard deviation = %.2f\n\n",ave1,StandardDeviation(n,eng,ave1));
Re:すみません
Posted: 2008年11月19日(水) 15:25
by バグ
よくよく見ると、私の投稿のcalcSum関数って、全く意味ないですね…(苦笑)
Re:
Posted: 2008年11月19日(水) 21:43
by 初心者
皆さんありがとうございました^^
あとは自分でやってみようとおもいます。
またお願いします。