* 第7回 ファイルと構造体 [#j1a8a996]
- ''基本課題''は,必ず授業時間中に終わらせること。
- ''★印の付いている問題''は,担当教員に見せて確認の印(またはサイン)を得ること。
- ''応用課題''は,終わらなかったら次週(1週間後の午前11:00)までの宿題とする。
- ''他人のコピーと判断されたものは正当な提出と認めない。''その場合,2人のコピーなら2分の1の点数,3人のコピーなら3分の1の点数(以下同様)とする。
- プログラムのファイル名は,「問題番号.c」とすること。
-- 例: a1.c, ax3.c
- [[プログラムの提出のしかた>../提出]]をよく読むこと。
-- 提出URL http://vilab.org/upload/clab-upload.html
** 基本課題 [#p1ff9ff2]
- 今日は基本課題は3題である。
- ''15時になっていなくても基本課題が終わった時点で終了してよい。''
*** ファイル [#s1f1264c]
''g1)''★ まず,「kansou.txt」というファイルにこの授業の感想を書いて準備しておく。そして,そのファイルの中身(=感想)を表示するプログラムを作って結果を確かめなさい。 ''※感想を書いたファイルも提出してください。''
- ヒント: ファイルから1文字(1バイト)ずつ読み込み,すぐに画面に1文字ずつ出力すればよい。
- 参考 http://rina.jpn.ph/~rance/c_language/p15.html
> 【ポイント】 C言語でファイルに対する読み書きを行うには,''ファイルポインタ''というものを用いる。fopen()でファイルを開き,処理が終わったらfclose()でファイルを閉じる。
FILE *fp; /* ファイルポインタ */
/* 途中省略 */
fp = fopen("ファイル名", "モード"); /* ファイルを開く */
if (fp == NULL) {
/* fopen失敗のときのエラー処理 */
}
/* ファイルを使った処理 */
fclose(fp); /* ファイルを閉じる(後始末) */
> 【ポイント】 ファイルから1文字読み込むには,getc()関数を用いる。画面に1文字書き込むにはprintf()を用いてもいいが,putchar()が高速である。下記に関連する関数のプロトタイプ宣言を示す。
#include <stdio.h>
FILE* fopen(char *fname, char *mode):
void fclose(FILE *fp);
int getc(FILE *fp);
int putchar(int ch);
''g2)''★ ユーザが新しく入力したファイル名のファイルを作成し,そのファイルに1以上1000以下の17の倍数をすべて書き込むプログラムを作成しなさい.※つまり,ファイル名はプログラム実行時に,キーボードから読み込むようにする。
> 【ポイント】 標準ライブラリ関数fprintf()とfscanf()を用いれば,画面やキーボードに対するprintf(), scanf()と同じようにファイルに対してテキストの入出力が可能である。
#include <stdio.h>
int fprintf(FILE *fp, char *format, ...);
int fscanf(FILE *fp, char *format, ...);
*** 構造体 [#gc4ee455]
''g3)''★ x座標,y座標からなる構造体pointを定義し,その変数を3つ作成しなさい。キーボードから三角形の3つの頂点の座標を読み込み,三角形の重心の座標を求め表示しなさい。
struct point {
double x;
double y;
};
- 参考: http://www.geisya.or.jp/~mwm48961/koukou/bunten05.htm
- http://www005.upp.so-net.ne.jp/h-masuda/cl/CKiso/ck0601.html
>【ポイント】 構造体は任意のデータ型の変数を複数まとめた''新しいデータ型''であり,配列では実現できない複雑なデータ構造を実現するためのものである。例えば,年(int year),月(int month),日(int day)からなる構造体は以下のように定義できる。
struct date {
int year, month, day;
};
この構造体struct dateは(intやdoubleと同じような)新しいデータ型になり,その変数は例えば次のようにして定義することができる。
struct date d1;
struct date d2, d3;
こうして定義したd1は1つの変数(構造体変数)であるが,その中にint year, int month, int dayという3つの変数(メンバ)を持っている。このように関連する変数をまとめて確保するための仕組みが構造体である。構造体変数の中のそれぞれのメンバを読み書きするには,メンバアクセス演算子「.」を用いて''「構造体変数名.メンバ名」''とすればよい。下記にいくつか例を示す。
d1.year = 2007;
m = d1.month;
scanf("%d", &d1.day);
** 応用課題 [#a54978d0]
''gx1)'' コマンドラインで与えられたファイル名のファイルの内容を画面に表示するC言語のプログラムを作成しなさい(UNIXのcat,Windowsのtype)。このプログラムを実行するためには,「コマンドプロンプト」からプログラムを実行しなければならない。
>【ポイント】 プログラム実行時のコマンドラインの引数は,メインの引数として取得することができる。
int main(int argc, char *argv[]);
このargcに,コマンドライン引数の個数,argvにそれぞれの引数の文字列が得られる。
int main(int argc, char *argv[])
{
int i;
for (i = 0; i < argc; i++)
printf("%s\n", argv[i]);
}
''gx2)'' ユーザが指定したファイル名の英文テキストファイルを開き,そこに含まれている単語の平均長(平均文字数)を求めるプログラムを作成しなさい。ただし,単語の定義は,アルファベット(A〜Z,a-z)が連続している文字列とする。
- ヒント:アルファベットが途切れる(アルファベット以外の文字を読み込む)たびに,単語数を1ずつ増やしいく。全部のアルファベットの文字数を単語数で割ると,1単語あたりの文字列が計算できる。
''gx3)'' まず,商品名(文字列),価格(整数),数量(整数)をメンバとする構造体を定義する。次に,構造体を要素とする長さ10の配列を作成し,中身を適当な値で初期化する。キーボードから整数を読み込み,その価格以下のデータを探してすべて表示するプログラムを作成しなさい。
struct item {
char name[20];
int price;
int quantity;
};
struct item item_list[10] = { /* 初期化 */ };
''gx4)'' ''g3)''の構造体変数へのポインタを引数にとり,キーボードからその変数に(1点の)座標値を読み込む関数 read_point と,同様にポインタを引数にとり,画面に座標値を表示する関数 write_point を作成しなさい。そして,三角形の頂点の座標を read_point で読み込み,重心を計算してからそれを write_point で表示するプログラム(main)を作成しなさい。
''gx5)'' まず,氏名(文字列),年齢(整数),身長(実数)からなる構造体を定義しなさい。そして,その構造体の配列に10人分のデータをキーボードから読み込み,それをheight.txtファイルに格納するプログラム(gx5a.c)を作成しなさい。また,その10人分のデータを読み出して表示するプログラム(gx5b.c)も作成しなさい。
** 発展課題 [#cf84ffa2]
- 発展課題には''提出期限を設けない''ので,前回までの発展課題でやっていないものも含めて,どれでも自分の面白いと思うものをやってよい。
''gz1)'' 最後の課題である。''fz1)''と''bz1)''を組み合わせて,RPGを作成してみなさい。しかし,それだけでは肝心の''「経験値」''と''「レベルアップ」''がないのでそれらを実現するとよいだろう。