選手のデータは、2種類ある。1つは、名前、生年月日、国籍、優勝回数などの基本的なデータで、すべての選手について記載されている。もう1つは、前回の演習で扱ったスコアテーブルである。
今回の演習では、これら2種類のデータをロードして、ネームカードの配列変数に格納する部分のコーディングを行う。
データとサブルーチンの関係を図に示す。
この図には、前者のデータが f1_pilot_info.txt、後者のデータが f1_score_table.txt という名称で記されている。前者のデータをロードするプログラムは、load_pilot_info というサブルーチンであり、後者のデータをロードするプログラムは、load_score_table というサブルーチンである。ロードしたネームカードを単純に表示するプログラムは、prac1001 や prac1002 である。
load_pilot_info では、ネームカードの配列を新規に作成し、データを格納する。
load_score_table では、既に作成されたネームカードに、f1_score_table.txt から読み込んだデータを追加する。
まず、f1_pilot_info.txt の形式を確認しておこう。
このファイルは、タブ区切りテキストである。文字コードは euc コードである。タブ区切りテキストは、Excel などの表計算アプリケーションで読み書きができる。
表の形式であるので、各列について説明する。列は、左の列から順に、「ドライバー番号」、「日本語名」、「英語名」、「短縮名」、「ファイル名」、「チーム名」、「ポールポジションの回数」、「ファステストラップの回数」、「優勝回数」、「総得点数」、「生年月日」、「国籍」、「身長」、「体重」を表わす。
ここのファイルを使おう:⇒f1_pilot_info.txt (ここのファイルは、自動抽出したので、誤りがあるかもしれない…。ちなみに、抽出プログラム一式は、Info.tgzである。暇があったら見て下さい。なお、tgz ファイルの解凍は、tar -zxf Info.tgz である。)
ここのサブルーチンでは、(1)ファイルのオープン, (2)ネームカードの配列の確保, (3) ファイルのロードと配列への格納, (4) ファイルのクローズ, (5) 結果のリターン を行う。
このうち (3) については、タブ区切テキストの処理をしなければならない。そこで、次の3つのサブルーチンを作成し、tabstr.c とする。
・指定番目のセルへのポインタの検出 【関数名】char *tabstr_skip(char *line, int n) 【引 数】line ... タブ区切りされた文字列 n ... 抽出したいセルの番目 【返り値】セルの文字列の先頭へのポインタ。 指定したセルの番目が不適切であった場合 NULL を返す。 【方 式】タブの出現回数が指定数未満の間、非タブ文字を読み飛ばす。 ・境界記号までの文字列のコピー 【関数名】void tabstr_get_cell(char *src, char *dst, int sz) 【引 数】src ... コピー元 dst ... コピー先 sz ... コピー先の文字列の領域サイズ。sz - 1 文字(バイト)までコピー可能。 【返り値】なし 【方 式】境界記号(\t, \n, \0)が検出されるか、コピー先の領域を越える直前までの間 文字のコピーを繰り返す。 ・指定番目のセルのコピー 【関数名】void tabstr_get_cell_at(char *src, int n, char *dst, int sz) 【引 数】src ... コピー元 n ... コピーしたいセルの番目 dst ... コピー先 sz ... コピー先の文字列の領域サイズ。sz - 1 文字までコピー可能。 【返り値】なし 【方 式】tabstr_skip と tabstr_get_cell を用いて実現する。 tabstr_skip が NULLを返す場合 dst の先頭に '\0' を代入する。 |
準備済みのファイル tabstr.c には、肝心なところで、行の順序がランダムに置き換えられている。正しく動作するように、行の順序を修正せよ。
準備済みのファイル load_pilot_info.cは、上述の処理(1)〜(5)を行うように作られている。しかし、選手の画像ファイルの取り込みができていない。適切なところにプログラムコードを追加せよ。
次のファイルを使用して動作確認ができる。
実行方法は、次のとおりである。
以下に実行結果を示す。
1: F.アロンソ (01_Fernando_Alonso.pgm) 2: L.ハミルトン (02_Lewis_Hamilton.pgm) 3: G.フィジケラ (03_Giancarlo_Fisichel.pgm) 4: H.コバライネン (04_Heikki_Kovalainen.pgm) 5: F.マッサ (05_Felipe_Massa.pgm) 6: K.ライッコネン (06_Kimi_Raikkonen.pgm) 7: J.バトン (07_Jenson_Button.pgm) 8: R.バリチェッロ (08_Rubens_Barrichello.pgm) 9: N.ハイドフェルド (09_Nick_Heidfeld.pgm) 10: R.クビサ (10_Robert_Kubica.pgm) 10: S.ベッテル (10_Sebastian_Vettel.pgm) 11: R.シューマッハ (11_Ralf_Schumacher.pgm) 12: J.トゥルーリ (12_Jarno_Trulli.pgm) 14: D.クルサード (14_David_Coulthard.pgm) 15: M.ウェーバー (15_Mark_Webber.pgm) 16: N.ロズベルグ (16_Nico_Rosberg.pgm) 17: A.ブルツ (17_Alexander_Wurz.pgm) 18: V.リウッツィ (18_Vitantorio_Liuzzi.pgm) 19: S.スピード (19_Scott_Speed.pgm) 20: A.スーティル (20_Adrian_Sutil.pgm) 21: C.アルバース (21_Christijan_Albers.pgm) 22: 佐藤琢磨 (22_Takuma_Sato.pgm) 23: A.デビッドソン (23_Anthony_Davidson.pgm) |
基本的には、この部分のプログラムは前回の演習で作成した。今回の演習で異なる部分は、f1_score_table.txt から取り込んだデータを、ネームカードの配列に追加するところである。
スコアテーブルから取り込んだデータは、名前をみて、ネームカードの配列のしかるべきところに追加されなければならない。そこで、次のサブルーチンを追加する。
・同名の人物を配列から検索 【関数名】int find_same_person( NameCard **ncarray, NameCard *nc ) 【引 数】ncarray ... ネームカードの配列 nc ... 検索のキーとなるネームカード 【返り値】同名の人物についての配列番号 【方 法】ncarray の先頭から順に、名前の文字列比較により、検索する。 もし、検索で見付からない場合はエラー終了。 |
準備済みのファイル load_score_table.cには、上記の find_same_person の部分の行がランダムに入れ替えられている。正しく動作するように修正せよ。また、スコアテーブルの情報をネームカードの配列にコピーするところで、合計得点のコピーができていないので、それができるように修正せよ。
次のファイルを使用して動作確認ができる。
実行方法は次のとおりである。
以下に実行結果を示す。
1: F.アロンソ (01_Fernando_Alonso.pgm) RANK: 2 TOTAL: 48 2: L.ハミルトン (02_Lewis_Hamilton.pgm) RANK: 1 TOTAL: 58 3: G.フィジケラ (03_Giancarlo_Fisichel.pgm) RANK: 6 TOTAL: 13 4: H.コバライネン (04_Heikki_Kovalainen.pgm) RANK: 8 TOTAL: 12 5: F.マッサ (05_Felipe_Massa.pgm) RANK: 3 TOTAL: 39 6: K.ライッコネン (06_Kimi_Raikkonen.pgm) RANK: 4 TOTAL: 32 7: J.バトン (07_Jenson_Button.pgm) RANK: 0 TOTAL: 0 8: R.バリチェッロ (08_Rubens_Barrichello.pgm) RANK: 0 TOTAL: 0 9: N.ハイドフェルド (09_Nick_Heidfeld.pgm) RANK: 5 TOTAL: 26 10: R.クビサ (10_Robert_Kubica.pgm) RANK: 7 TOTAL: 12 10: S.ベッテル (10_Sebastian_Vettel.pgm) RANK: 16 TOTAL: 1 11: R.シューマッハ (11_Ralf_Schumacher.pgm) RANK: 15 TOTAL: 2 12: J.トゥルーリ (12_Jarno_Trulli.pgm) RANK: 10 TOTAL: 7 14: D.クルサード (14_David_Coulthard.pgm) RANK: 12 TOTAL: 4 15: M.ウェーバー (15_Mark_Webber.pgm) RANK: 14 TOTAL: 2 16: N.ロズベルグ (16_Nico_Rosberg.pgm) RANK: 11 TOTAL: 5 17: A.ブルツ (17_Alexander_Wurz.pgm) RANK: 9 TOTAL: 8 18: V.リウッツィ (18_Vitantorio_Liuzzi.pgm) RANK: 0 TOTAL: 0 19: S.スピード (19_Scott_Speed.pgm) RANK: 0 TOTAL: 0 20: A.スーティル (20_Adrian_Sutil.pgm) RANK: 0 TOTAL: 0 21: C.アルバース (21_Christijan_Albers.pgm) RANK: 0 TOTAL: 0 22: 佐藤琢磨 (22_Takuma_Sato.pgm) RANK: 13 TOTAL: 4 23: A.デビッドソン (23_Anthony_Davidson.pgm) RANK: 0 TOTAL: 0 |
まずは、練習1と練習2を完成させる。修正した個所を全て、henkou.c というファイルにコピーせよ。コピーは、関数の単位とせよ。henkou.c をプリントアウトして、変更した行に下線を引き、提出せよ。