質問: cを習い始めてまだ一ヶ月ほどの者です。 学籍番号、身長、体重をメンバとしてもつstruct student_data を定義し、学生の情報を入力するとともに、身長、体重の最高値・最低値を学籍番号とともに表示するプログラムを作成する課題が出ています。なお、生徒の最大数は 10とし、学籍番号として負の数が入力されたら入力を終了する というものです。課題について、ヒントをください。 以下のコードは書き途中コードなのですが長ったらしくて汚いうえに構造体の使い方も間違っているみたいです。 ポインタも構造体も習ったばかりで、何が間違っているかも分からないほどなので読みにくいかと思いますがご教授いただけましたらありがたいです。 ``` #include struct student_data{ int num, h, w; }; int main(){ struct student_data *p[10]; int i, a=0, b=0, c=0, d=0; printf("Input student number, height, weight:"); for(i=0;;i++){ scanf("%d %d %d", p[i]->num, p[i]->h, p[i]->w); if(p[i]->num<0){ break; }else if(i>=1){ if(p[i]->h-a->h>0){ p[i]->a; }else{ p[i]->a; } } } for(i=0;;i++){ if(i>=1){ if(p[i]->h-c->h<0){ p[i]->c; }else{ p[i]->c; } } } for(i=0;;i++){ if(i>=1){ if((p[i]->h)-(b->h)<0){ p[i]->b; }else{ p[i]->b; } } } for(i=0;;i++){ if(i>=1){ if(p[i]->w-d->w<0){ p[i]->d; } }else{ p[i]->d; } } printf("Tallest student number is %d (%d)\n", a.num, a.h); return 0; } ```
回答: 「短く実行できる形」にするには、`for`ループを1つだけにすることです。 なお、質問の文言にある課題の表示内容に限って言えば、構造体を使う必要はありません。 ポインタも目に見える形ではほとんど使う必要はありません。 ちなみに質問の元のソースは、コメントにも指摘されている以下の理由で、きつい言い方になりますが、ほぼすべてが考慮するに値しない内容です。 * 学生情報構造体の配列宣言が、ポインタの配列になっていて、実際のデータ用領域が確保されていない。 かつ領域が確保されていないのに使われている。(下記理由でビルドも通らないが、ビルドできたとしてもメモリアクセス違反で異常終了する) * 内容の不明な`int`の `a`,`b`,`c`,`d` という名前の変数が宣言されていて、かつプログラム上は構造体へのポインタだったり、構造体のメンバー扱い? だったりして整合性が取れていない。 (そのため、まずビルドが正常に出来ない) * 3つの`for`ループのどれも終了条件が指定されていない。 * 各`for`ループの中の`if`文の判定条件や、その真偽時両方の処理が意味不明。 課題なので実際のプログラムソースは提示しない方が良いでしょう(けれどほとんど提示しているも同然ですが)から、以下の内容を元にプログラムを組んでみてください。 * 入力データ数の最大値(10)は定数マクロとして定義しておく。 * 学生情報構造体の配列は、ポインタではなく、実際の領域を持った構造体の配列として宣言する。 * 以下を合わせて13個の変数を用意する(課題内容に応じて`int`だけではなく`double`(身長?・体重?)も) + ループカウンタ + 有効な入力データ数(初期値は10) + 学籍番号・身長・体重の入力用で3個 + 身長・体重の最高値/最低値およびそれぞれに対応する学籍番号で8個 それぞれの値は、あり得ない数値で初期化しておく(学籍番号および最高値は-1,最低値は999999等) * `for`ループで以下の処理を行う + `for`の継続/終了条件(ループカウンタが10未満は継続,10以上は終了)は指定しておく + 入力ガイドのプロンプト表示`printf` + 学籍番号・身長・体重の入力用変数をパラメータにした入力値の読み取り`scanf` + 負の学生番号入力による終了判定を行い、途中終了の場合は有効な入力データ数を更新してループ脱出 + 入力データのそれぞれを学生情報構造体の配列に格納 + 身長・体重の最高値/最低値が更新されるか判定を行い、更新されるならば、その数値と学籍番号を入れ替える * `for`ループを終了して、有効なデータが1個以上あれば、課題の身長・体重の最高値/最低値およびそれぞれに対応する学籍番号を表示する`printf`