- ベストアンサー
C言語 構造体でつまずいています
以下、番号と点数を入力して構造体配列に入力し、番号に0が入力されたら、入力処理をやめ、平均点を表示するプログラムです。 今のコードでは、最初から番号に0を入力すると、0除算になりエラーになります。どうすれば良いのでしょうか? #include <stdio.h> #define MAX 50 //配列の要素数を定義 int count=0; //グローバル変数 struct data { //構造体の定義 int num; //メンバの宣言 int ten; }; void nyuryoku(struct data *); //プロトタイプ宣言 float heikin(struct data *); //プロトタイプ宣言 void main() { struct data score[MAX]; //構造体の宣言 printf("**学生番号/点数入力**\n"); printf("\n"); nyuryoku(score); //nyuryoku関数呼び出し printf("\n**以上%d名の平均点:%0.1f点**\n",count,heikin(score)); //heikin関数の戻り値表示 } //nyuryoku関数 //機能:構造体配列にデータを入力する void nyuryoku(struct data *pd) //仮引数pdに構造体ポインタが渡る { int i; for(i=0;i<MAX;i++){ printf("学生番号>>"); scanf("%d",&pd->num); if(pd->num==0){ //学生番号に0を入力するとループを抜ける break; } printf("点 数>>"); scanf("%d",&pd->ten); count++; //人数のカウント pd++; //構造体配列を一つずらす } } //heikin関数 //機能:構造体配列の点数の平均を計算、戻り値として返す float heikin(struct data *pd) //仮引数pdに構造体ポインタが渡る { int i; int sum=0; float ave=0; for(i=0;i<MAX;i++){ if(pd->num==0){ break; } else{ sum+=pd->ten; //点数を加算 pd++; } } ave=(float)sum/count; //平均値を求める return(ave); //平均値を戻り値として返す }
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
countが0かどうかを判定すれば良いでしょう if (count > 0) { printf("\n**以上%d名の平均点:%0.1f点**\n",count,heikin(score)); } とか heikin( )関数内でcountをチェックするとか
その他の回答 (2)
- yama5140
- ベストアンサー率54% (136/250)
>まだ私も初心者です。 ・これだけ書ければ、「初心者」ではないと・・。 ★総じて、「判り易い」ソースと思いました。 ------------------------------------------------ ☆暇な年寄りが、僭越にもちょっと添削させて頂きました。 ・「骨組み」はそのままで、◆は、やや(?)変更。 ・後は、同じ「学生番号」が入れられた時の処理? → 構造体を「ポインタ」で扱うより、「配列の添え字」での 方が簡単そう。 例)sScore[ i ].iTen #include <stdio.h> #define MAX 50 // 配列の要素数を定義 int igCount = 0; // グローバル変数 typedef struct{ // 構造体の定義 int iNum; // メンバの宣言 int iTen; }DATA; void Nyuryoku( DATA * ); // プロトタイプ宣言 float Heikin( DATA * ); // プロトタイプ宣言 void main() { DATA sScore[MAX]; // 構造体の宣言 printf( "**学生番号/点数入力**\n\n" ); Nyuryoku( sScore ); // Nyuryoku関数呼び出し // Heikin関数の戻り値表示 printf( "\n**以上 %d 名の平均点:%0.1f点**\n", igCount, Heikin( sScore ) ); } void Nyuryoku( DATA *pScore ) // 機能:構造体配列にデータを入力する // 仮引数pScoreに構造体ポインタが渡る { int i; for( i = 0; i < MAX; i++ ){ printf( "学生番号(0:終了)>>" ); scanf( "%d", &pScore->iNum ); if( 0 == pScore->iNum ) break; // 学生番号に0を入力するとループを抜ける printf( "点 数>>" ); scanf( "%d", &pScore->iTen ); igCount++; // 人数のカウント pScore++; // 構造体配列を一つずらす } } float Heikin( DATA *pScore ) // 機能:構造体配列の点数の平均を計算、戻り値として返す // 仮引数pScoreに構造体ポインタが渡る { int i; int iSum = 0; float dAve; // 初期化不要 if( 0 == igCount ) return( -99.9 ); // ◆ご質問主旨 for( i = 0; i < igCount; i++ ){ // ◆ MAX → igCount iSum += pScore->iTen; // 点数を加算 pScore++; } dAve = (float)iSum / (float)igCount; // 平均値を求める return( dAve ); // 平均値を戻り値として返す } 注:インデントに全角空白を用いています。 タブに一括変換して下さい。
はっきりいって、相当にダメなプログラムですね。 アマチュアの手習いだと思って、指導します。 ダメなところ。 a)nyuryoku を抜けた状態での状態管理が出来ていない。 しいていえば、countがそうなのであろうが、これが、グローバル変数である必要はない。nyuryokuでの状態管理として、もっとも大事なのは、有効なレコードが、何件いれられたかであるから、それを、返り値としてかえす。 b)学生番号入力ゼロは、入力終了の入力なので、breakではなく、終了処理を書いて、returnする。 c)mainで、nyuryokuの返り値を、処理して、構造体トップアドレスと有効データ数を、heikinに渡すようにする。そして、heikinでは、有効データ数のチェックなどの論理は含まない。 もちろん、ゼロ除算は、今は、count==0で、nyuryokuを抜けているから。
お礼
ありがとうございました。 言われると納得できるんですが、まだ私も初心者です。