210 likes | 314 Views
構造体,ファイル入出力. 2007 年 1 月 26 日 科学科プログラミング. 構造体とは. 複数のデータを一つのまとまりとして定義したもの 例えば、個人データを整理することを考えてみる 項目として、以下の3つを一人分のデータとしてみる 名前 メールアドレス 内線番号 名前は、 文字列 メールアドレスも 文字列 内線番号は、 4桁の整数 と定義しよう. これらの各々を 「一つの」データとみる。 つまり、 グリーンのカード1枚が一つのデータとみる。. Itoh Yukihiro itoh@inf.shizuoka.ac.jp
E N D
構造体,ファイル入出力 2007年1月26日 科学科プログラミング
構造体とは • 複数のデータを一つのまとまりとして定義したもの • 例えば、個人データを整理することを考えてみる項目として、以下の3つを一人分のデータとしてみる 名前 メールアドレス 内線番号 名前は、 文字列 メールアドレスも 文字列 内線番号は、 4桁の整数 と定義しよう
これらの各々を 「一つの」データとみる。 つまり、 グリーンのカード1枚が一つのデータとみる。 Itoh Yukihiro itoh@inf.shizuoka.ac.jp 1474 Hiromasa Nakatani nakatani@inf.shizuoka.ac.jp 1482
新しい「型」の定義(構造体定義) • 一つのデータが複数のデータのまとまり 個々のデータの型も文字列と文字列と様々 • そんなデータは、既存の型では入りきらない 新しい「型」を定義する
構造体定義の方法 新しく定義する「型」の名前 構造体タグ名 struct parsonal_data { char name[20]; char address[50]; int num; }; ひとまとまりのデータを構成する 個々メンバの型と要素の名前 struct タグ名 { メンバ1 [型 変数(配列)名] メンバ2 [型 変数(配列)名] ・・・ }; 一般的には
構造体定義と変数宣言 • ここまでは、あくまでも「型」の定義 • int型、float型、char型などと共に、parsonal_data型 が使えるようになっただけ • 整数型の変数を使うためには、変数宣言が必要だったのと同様に, • parsonal_data型の「構造体変数」を宣言しないと使えない
struct parsonal_data { char name[20]; char address[50]; int num; }; 構造体変数の宣言 struct parsonal_dataitoh; “itoh”という名前の構造体変数が用意される つまり, itoh.name という文字列 itoh.address という文字列 itoh.num という整数 が一まとまりになった変数が用意される
構造体の型定義と宣言を同時にする struct parsonal_data { char name[20]; char address[50]; int num; } itoh, nakatani;
構造体の型定義と宣言を同時にし,更に初期値を設定構造体の型定義と宣言を同時にし,更に初期値を設定 struct parsonal_data { char name[20]; char address[50]; int num; } itoh={ “YUKIHIRO ITOH”, “itoh@inf.shizuoka.ac.jp”, 1474 };
構造体への値の代入・参照 struct parsonal_dataitoh, nakatani; int call; char initial; strcpy(itoh.name, “YUKIHIRO ITOH”); strcpy(itoh.address, “itoh@inf.shizuoka.ac.jp”); itoh.num=1474; call=itoh.num; initial=itoh.name[0];
構造体はそのまま代入可能 struct parsonal_dataitoh, clone; strcpy(itoh.name, “YUKIHIRO ITOH”); strcpy(itoh.address, “itoh@cs.inf.shizuoka.ac.jp”); itoh.num=1474; clone = itoh;
構造体の配列 struct parsonal_dataprogsatff[4]; さっきの itoh みたいな構造体が4つ並んだ配列 仮に、progstaff[0]に 伊東先生のデータが入っていたとすると、 prog_staff[0].name“YUKIHIRO ITOH” prog_staff[0].address[0]“itoh@inf.shizuoka.ac.jp”
構造体のメンバにポインタもかける R I I T Y U K O I H char add_list[100][50]; struct parsonal_data { char name[20]; char *add_ptr; int num; } itoh={ “YUKIHIRO ITOH”, add_list[0], 1474 }; ・・・ ポインタ add_ptr 1474 num add_list add_list[0] ・・・
ファイルの入出力 • ファイルを開く (fopen) • ファイルを読む (fscanf) • ファイルに書く (fprintf) • ファイルを閉じる (fclose) いずれの操作もファイルポインタ(ファイル変数)という特殊なポインタを通じて行う
ファイルポインタの用意 FILE *ファイル変数; 例えば、 FILE *fp1;
"w" ファイルのオープン fopen("ファイル名", "モード") fopenはオープンされたファイルを指すポインタを返す エラーの場合にはNULLを返す <ポインタをファイルポインタに格納する方法> FILE *fp1; fp1 = fopen("foo.txt", "r" ); if (fp1 == NULL) { printf(“Cannot open file ‘%s’.\n”, “foo.txt”); exit(1); } 読み込み(read)モード "r" 書き込み(write)モード "w"
ファイルの読み込み fgets fgets(文字列, 文字列サイズ, ファイルポインタ) 例えば、 #define BUFLEN 1024 char buf[BUFLEN]; fgets(buf, BUFLEN, fp1); stdinだと標準入力(キーボード)から取得
ファイルの読み込み fscanf fscanf(ファイルポインタ,書式, パラメータ) sscanfとほとんど同じ! 違いは、 sscanf 文字列を対象とする fscanf ファイルを対象とする
ファイルへの書き込み fprintf(fp1, "%d", a);
ファイルのクローズ fclose int f; f = fclose(fp1); if (f != 0) { printf("Cannot close file '%s'.\n", "foo.txt"); exit(1); }
ファイルの最後 EOF(End of File) 1度オープンしたファイルからデータを複数回読み出す場合,2回目以降は,以前に読み終わった次の場所から読み出す! ファイル 最初に読んだところ 2回目に読んだところ 3回目に読んだところ ファイルの最後まで読み終わって,終端まで来たときに, 1文字ずつ読み出す関数は文字の代わりに EOF という コードを返す(教科書p.215のプログラム例) (int getchar(void), int fgetc(FILE *fp) など) 文字列を読み出す関数は,NULLを返す (char *fgets など)