第9回演習問題


問1(基礎): XYZ構造体
struct XYZ{
int x;
long y;
double z;
};
へのポインタを受け取り,その各メンバに値を設定する関数
 void setxyz(struct XYZ *xyz, int x, long y, double z)
を作成せよ.main()ではキーボードから3つの値(int型の値,long型の値,double型の値)の入力を受け付け,setxyz()を呼び出してそれらの値を構造体に設定し,その構造体の各メンバの値を表示せよ.

問2(基礎):gstudent構造体
struct gstudent {
char name[20]; /*氏名*/
int height; /*身長*/
float weight; /*体重*/
long schols; /*奨学金*/
};
この各メンバに値を設定し,その構造体を返す関数
 struct gstudent set_gstudent(char name[], int height, float weight, long schols){ }
を作成し,main()において適当な値を設定せよ.また,gstudent構造体へのアドレスが与えられたとき,そのメンバの値を表示する関数
 void show_gstudent(struct gstudent *gs){ }
を作成し,main()において設定した内容を1行で表示せよ.
表示例:Mike 165 72.0 70000

問3(応用):問2のgstudent構造体の配列変数とその値を用意して,最も身長が高い学生のメンバを表示するプログラムを書け.

問4(応用):次のプログラムを作成せよ.
・x座標およびy座標のペアとして構成されるPOINT構造体(テンプレート)を定義せよ.
・2つの座標p1(x,y),p2(x,y)の入力を受け付け,それぞれ構造体に代入せよ.
・2つの座標p1,p2間の距離を求めるプログラムを書け.

なお,2つの座標が(x1,y1),(x2,y2)であるとき,その座標間の距離はルート((x2-x1)の二乗 + (y2-y1)の二乗)で求めることができる.
ルートの計算は
double sqrt(double x);
というライブラリ関数で計算できます.その際
#include<math.h>
が必要になり,コンパイル時,-lm というオプションも必要になります.
例: gcc distance.c -lm

問5(応用):
(1)問2の構造体の配列を利用して,身長で昇順にソートするプログラムを書け.例えば,

氏名   身長 体重  奨学金
Sachi  162  46.7 20000
Hiro   170  50.2 100
Sadako 175  60.5 60000
Sato   178  61.0 30000

という風にソートされたものを表示すること.


(2)(1)で与える構造体の各値をファイルから与えるプログラムを作成せよ.
./a.exe gstudent.dat
という形式でプログラムを起動することでgstudent.datから構造体の各値を取り込み,身長順にソートしてファイルを更新するプログラムに改良せよ.gstudent.datのデータ内容は例えば以下のようになっており,各データの間はタブで区切られている(プログラムでは\tを用いると良い).

Sadako  175  60.5  60000
Hiro    170  50.2  100
Sato    178  61.0  30000
Sachi   162  46.7  20000


(3)(2)で作成したプログラムをさらに改良し,氏名,身長,体重,奨学金のそれぞれで昇順にソートし,その後にファイルを更新するかどうかをユーザが選択できるプログラムを作成せよ.

出力例:
./a.exe gstudent.dat
ソート
氏名(1),身長(2),体重(3),奨学金(4): 2 <- ユーザ入力
氏名   身長 体重  奨学金
--------------------------
Sachi  162  46.7 20000
Hiro   170  50.2 100
Sadako 175  60.5 60000
Sato   178  61.0 30000
--------------------------

ファイルに書き込みますか? Yes(1),No(2): 0 <- ユーザ入力
書き込みました.


ヒント:バブルソートのプログラムを少し改良すればよい.構造体同士は丸ごと代入できることに注意.

問6(応用):対戦型のじゃんけんゲームを作成せよ.
まずユーザと対戦相手のデータを格納するplayer構造体を作成せよ.データ構造は[name,hp,win,lose,draw,score]からなっている.nameは名前,hpは負けると一つ減り0になるとゲームオーバ,win,lose,drawはそれぞれ勝ち,負け,引き分けのときに1増え,scoreは勝った場合に1,引き分けの場合0.5増える.name,hp以外の値は初期値を0とする.この構造体を利用してユーザとコンピュータがじゃんけんをし,hpが0になったほうが負けとなるようにプログラムを作成すること.

問7(発展):問6のプログラムを利用して,さらに高度な対戦型じゃんけんゲームを作成せよ.
(1)問6のプログラムを拡張して敵を3人以上作成し,ユーザが敵3人と一人ずつじゃんけんをして全員に勝ち抜けばクリアとなるようなプログラムを作成せよ.その時hpは一試合が終わる毎に元に戻るものとする.

(2)(1)のプログラムをさらに拡張して,敵を3人から5人の間でランダムに作成するようにせよ.また,ユーザと敵全員でじゃんけんゲームのトーナメント戦を行い(組み合わせはランダムに決定され,コンピュータ同士の対戦も自動的に行う),全試合が終了した時にscore,winでそれぞれPlayerを並び替えて表示せよ.今回の場合もhpは一試合が終わる毎に元に戻るものとする.
余裕があれば,ユーザのデータのうちwin,lose,draw,scoreの値を全試合が終わった後にファイルに出力せよ.その時,元々ファイルに出力されているそれぞれの値に合計して出力すること.

- 以下チャレンジ問題(特に構造体を使わなくても良い) -

問8(発展) コマンドライン引数から文字列を1つ読み込み,その文字列の全ての並べ替え(順列)を表示するプログラムを作成せよ.

実行例:
$./a.exe USA
USA
UAS
AUS
ASU
SAU
SUA

与えられる文字列の長さは任意であるが,実行時間が長くなるので上限(例えば5など)を与えても良い.また,重複文字を含む文字列を与えたときにはエラーを表示するようにせよ(USS, Nakamura など).


問9(発展)問8の続きとして,コマンドライン引数から2つの文字列を読み込み,2つ目の文字列が1つめの順列を辞書順で並べたときの何番目に当たるかを出力するプログラムを作成せよ.

実行例:
$ ./a.exe USA ASU
AUSはUSAの順列の 2番目にあたります.
$ ./a.exe USA USB
USBはUSAの順列に含まれません.

masa-n@cs.kobe-u.ac.jp
(C) Masahide Nakamura, Kobe University