質問: ((g->c_test) + (g->k_test)) / 2 * 0.6 + (g->kadai); /* 1名の最終成績を計算 */ return; } void Print(struct Student *g) { printf("%s %s %d %d %d %f\n", g->name, g->no, g->c_test, g->k_test, g->kadai, (double)g->seiseki); /* 1名表示 */ return; } ``` 分からない点 ・seisekiはint型なのに0.6をかけたらdouble型にならないのでしょうか。 ・標準入力が終了したら..とありますがそのあとどんな処理をするべきでしょうか。 ・メモリを確保..とありますが100回繰り返したら結局100名分の構造体配列を用意するのと一緒なのではないのでしょうか。
回答: 本題の前にいくつか。 > > `main()` > > > `int main(void)`と書くことがC言語規格書で定められています。 > > `struct Student { ... }; > > > C++だとこれでいいのですが、Cだと普通`typedef struct tag_student { ... } Student;`と書くように思います。 > > `void Print( struct Student *g ){` > > > 引数の型が`struct Student *`となっていますが、`const struct Student *`とするべきです。なぜなら`Print`関数は引数`g`が指す領域を書き換えません。`const`をつけないことは可読性を下げます。まあ課題の指定でこうなっているのだとは思いますが。 > > `gets` > > > 利用してはいけません。すこしググればわかりますが、`gets`はどうやっても安全に利用することができません。`fgets`か`gets_s`を利用してください。 今回の課題では文字列の入力を受けてさらにパースする作業が必要になります。このとき`sscanf`を使ってしまいがちですが、安全に数値へ変換することはできないので、`errno`に気を使いつつ地道に`strtol`系関数を呼ぶことになります。 C言語で安全に標準入力から数値を取得 - Qiita ・・・ということまで課題を出す側がわかって事前に指導していればいいのですが、9割9分9厘教師はC言語を理解していないので、まあ`sscanf`を使うことになるんだろうなとは思います。やつらいい加減C言語で標準入力をやるのはラスボスに挑むに等しいと理解してくれないだろうか・・・。 > > seisekiはint型なのに0.6をかけたらdouble型にならないのでしょうか > > > 鋭いです。まず `((g->c_test) + (g->k_test)) / 2` の結果は`int`型ですが、 `((g->c_test) + (g->k_test)) / 2 * 0.6` の結果は`double`で、 `((g->c_test) + (g->k_test)) / 2 * 0.6 + (g->kadai)` もやはり`double`です。 これを`g->seiseki`に代入するときに`int`への暗黙変換が行われます。暗黙変換の詳細なルールは複雑怪奇極まるので深く突っ込まないことをおすすめします。 > > 標準入力が終了したら..とありますがそのあとどんな処理をするべきでしょうか。 > > > 課題の答えになるのでヒントだけ。 `break`があることから、EOFだったらなにかして、ループを抜ける、という処理だとわかります。ループを抜けたあと、結果を表示するループに入るわけですが、このときループ回数を司っている変数`num`に注目してください。 > > メモリを確保..とありますが100回繰り返したら結局100名分の構造体配列を用意するのと一緒なのではないのでしょうか。 > > > 配列もmallocによる確保もメモリー確保には違いありませんが、どこにメモリー確保されるかが異なります。 C++のメモリーの話とストレージの有効期間の話をしようか - Qiita ですがいい着眼点です。 > > `struct Student *pg[NUM]; /* 学生NUM名まで*/` > > > 課題の指定でこうなっているのだとは思いますが、わざわざ構造体を`malloc`するのはこの場合冗長極まるでしょう。`struct Student pg[NUM]`でよかった。 `malloc`のようなメモリー確保は基本的に時間がかかるのです。今回のような小さなプログラムでは問題になりませんが、深いループの中でのメモリー確保は時として高速化の妨げとなることもあります。