joho1-2017の日記

joho1-2017の日記

情報処理実習1の解説ブログです.皆さんが課題を解く時の助けになれば幸いです.

構造体と共用体

今週は構造体と共用体について学習しました.
構造体を利用することで,コードが読みやすくなるといったメリットがあります.
構造体と共用体の違いは,授業中の説明にあった通り,メモリを各メンバで共有するかどうかにあります.例えば各メンバがそれぞれdouble型の配列であるような場合に,環境によっては構造体のメモリを確保できずに,実行できないかもしれません.
共用体については,授業課題を解く上で,しばらく使う機会はないかと思いますが,コードを読んだ時に,何をしているのかがわかる程度には覚えておいてください.
以下,課題の解説です.

1. ファイル【3d_points.csv】には個数不明の3次元座標点が記述されている.但し最大個数は 10^4以下とする.これらの重心座標を計算し表示するプログラムを作成せよ.また,座標点の個数も併せて表示すること.main関数は下記の通りとする.

int main(int argc, char* argv[])
{
    Point p[N]; 

    int size = load(p, argv[1]);
    if(!size){ 
        printf("データがありません\n"); 
        return -1; 
    }
    printf("座標点の数は %d です.\n",size); 

    Point cent_p = calc(p,size); 
    printf("重心点の座標は\n(%f %f %f)\nです.\n",cent_p.x, cent_p.y, cent_p.z); 
    return 0; 
} 

まず構造体の定義は,三次元点群なので,メンバ変数にはdouble型のx, y, zを用意すればいいですね.csvファイルからの読み込みは前回の課題2が参考になるかと思います.double型なのでprintfだと%fでscanfでは%lfとすればよかったですね.読み込みの際に個数をカウントする必要がありますが,これはループの回った回数(breakした時点でのcounterの値)をみるといいでしょう.重心の計算は授業中のQ12-5と同様です.


問題は同じですが,5組はデータの個数が50個と決まっていますね.つまり,個数のカウントはしなくても解くことができます.関数は,先生が授業ページに載せているような形で作ってもらえれば問題ないと思います.
ファイル 【3d_points.csv】には,50個の3次元座標値が,カンマ区切りで記述されている.ダウンロードして,エディタで開いてみよ.ダブルクリックするとExcelが起動する.

まず,
(1)float または double 型 3 つの変数で 3 次元座標を表す構造体 Point を定義し
(2)ファイルから50個のデータを読み込む関数 load を作成
(3)これらの重心座標を返す calc 関数を用い
重心位置を画面に表示するプログラムを作成せよ.

ヒント:ファイル内には1行あたり,カンマ区切りで実数が3つ並んでいるので, fscanf(fp, "%f,%f,%f", &..., &..., &...);とすれば,1行分の値3つの読み込みができる.
double 型の場合は,%lf を使用すること.


2. ファイル【rugby_matchup.csv】には各行に明治大学のチーム名(A or B),対戦相手,得点,失点が記されている. このファイルを読み込み,これら各要素に加え勝敗(Win,Lose,Draw)を格納する構造体を作成し,チーム名を入力するとそのチームの結果を全て表示するプログラムを作成せよ.

//実行例 
Which team? 
team=A 
   Tsukuba :  41 vs  21 => Win 
    Aoyama :  80 vs   0 => Win 
   Meigaku : 106 vs   0 => Win 
      Keio :  40 vs  17 => Win 
    Teikyo :   6 vs  31 => Lose 
    Waseda :  24 vs  37 => Lose 
      Joho :  31 vs  31 => Draw 

メンバを,チーム名,対戦相手,得点,失点,勝敗の5つとして,構造体を定義します.読み込み部分は[課題1]とほとんど同じですが,勝敗の部分は得点と失点の大小関係から与える必要があります.実行時にキーボードから入力されたチーム名を格納するのは,scanfを使えばいいですね.もう何度も登場しているので大丈夫でしょう.あとは読み取ったチーム名と同じチーム名のデータだけを表示してあげれば完成です.for文で構造体の配列を順に見ていけば実現できそうです.
最後に表示の際のbreakの判定ですが,例えば,csvファイルから読み取り,構造体の配列にデータを格納していくときに,どれかメンバの最後の値を-1に設定しておけば,for(int i=0; data.some[i]+1; i++)として終了の判定ができます.


3. 5人分の名前(char型),身長[cm](float型),体重[kg](float型)の順に記述された ファイル【health_data.csv】を読み込み,以下の要件を満たすプログラムを作成しなさい.
・名前,身長,体重,BMI指数を格納することのできる構造体を作成する.
・health_data.csvから読み込んだ値を用いてそれぞれのBMI指数を計算した後作成した構造体に格納する.
・「名前,身長,体重,BMI指数」の順番で各生徒のデータを書き出す.

//実行例
Name    Height Weight BMI
Aida    170.6  70.7   24.3 
Iijima  158.3  90.9   36.3 
Uehara  167.8  64.0   22.7 
Eguchi  193.1  50.2   13.5 
Ono     173.4  70.6   23.5

この問題は[課題2]と同様にcsvファイルから読み込み,BMI = (Weight) / (Height) / (Height) として格納してあげれば良さそうです.表示も[課題2]と同様にできそうです.
いずれの課題も表示がしっかりそろうように,printfのフォーマットを工夫してください.

課題の解説は以上です.

来週の授業はいままでのおさらい(模擬テスト)となります.それまでに,今までの授業でやった内容を各自でしっかり復習しておくようにしてください.シラバスにある通り,期末テストの点数が成績評価の大部分を占めています.来週のおさらいを効率的に活用するためにも,わからない部分がある人は,ブログでの質問やオフィスアワー等を利用して早めに解決するようにしてください.
それでは,課題提出頑張ってください.