プログラミング入門2 第11回 構造体 芝浦工業大学情報工学科 青木 義満 構造体 5人分のサッカー選手データ char int int name[5][256]; assist[5]; score[5]; 全てのデータを関数に渡して,処理する場合 void func( char name[ ][256], int assist[ ], int score[ ] ) void func( char name[ ][256], int *assist, int *score) 選手 ・氏名 ・所属チーム ・得点 ・アシスト ・年俸 ・・・・・ データをひとまとめにして 効率良くデータを管理・処理したい 構造体の必要性! プログラミング入門2 2 構造体とは? 多人数の学生の身体検査のデータ char name[5][256]; int height[5]; double weight[5]; 1人目のデータ /* 5人分の学生の名前 */ /* 5人分の学生の身長 */ /* 5人分の学生の体重 */ 2人目のデータ name[0][256] name[1][256] height[0] height[1] weight[0] weight[1] 各配列は独立していて,それぞれの関連性がわかりにくい 個人のデータを“カード”でまとめて表し,そのカードを人数分用意 プログラミング入門2 3 構造体とは? 重要 構造体とは,ひとまとまりのデータを集めたデータ構造である 名前 芝浦 義満 1枚のカード 名前 芝浦 次郎 身長 168cm 名前 芝浦 太郎 身長 165cm 体重 70kg 身長 176cm 体重 55.5kg 名前 char 型 身長 int 型 体重 体重 64.5kg double 型 複数の型のデータを ひとまとめにして扱う! プログラミング入門2 4 構造体の宣言 ~自分で新しい“型”をつくる 構造体を宣言することは,意味のあるデータをひとまと まりにした,新しい変数の“型“を自分で作ることである 1枚のカードをどう作るか? 宣言の方法 type(型)を define(定義) 構造体 typedef struct 手順 ①どんなデータをひとまとめにして 扱うかを決定 ②構造体の名前(変数の型)を決定 { char name[256]; int height; double weight; 中括弧でくくって ひとまとめに } student ; 構造体のメンバーという 構造体の名前(型名) ※int, double などと同じ役割 ※セミコロン忘れずに! プログラミング入門2 5 構造体データの使い方 変数(オブジェクト)の宣言 int x; student aoki; int型のオブジェクト x を宣言 student型のオブジェクト aoki を宣言 構造体内のメンバーへのアクセス typedef struct { char name[256]; int height; double weight; student aoki; 構造体オブジェクト aoki は,以下のメンバを持つ aoki.name[256] aoki.height aoki.weight } student 構造体の定義 構造体のメンバはドット(.)演算子でアクセス可能 プログラミング入門2 6 構造体を使ったプログラム(構造体のメンバ) ソースファイル名:list1203.c (p.274, 若干変更) 構造体メンバへの値の代入と表示 #include <stdio.h> #include <string.h> /* 文字列操作関数用 strcpy使用のため*/ typedef struct{ char name[20]; int height; float weight; } student; /* 名前 */ /* 身長 */ /* 体重 */ int main(void) { student sanaka; /* 構造体メンバへの値の代入 */ strcpy(sanaka.name, "Sanaka"); sanaka.height = 175; sanaka.weight = 60.5; /* 文字列sanakaをsanaka.nameにコピー */ /* 身長 */ /* 体重 */ /* 構造体メンバの表示 */ printf("氏 名 = %s\n", sanaka.name); printf("身 長 = %d\n", sanaka.height); printf("体 重 = %f\n", sanaka.weight); return (0); } プログラミング入門2 7 解説 typedef struct{ char name[20]; int height; float weight; } student; /* 名前 */ /* 身長 */ /* 体重 */ int main(void) { student sanaka; /* 構造体メンバへの値の代入 */ strcpy(sanaka.name, "Sanaka"); sanaka.height = 175; sanaka.weight = 60.5; /* 文字列sanakaをsanaka.nameにコピー */ /* 身長 */ /* 体重 */ strcpy(sanaka.name, "Sanaka"); 文字配列へのポインタ 文字配列(sanaka.name)に“Sanaka”を代入 プログラミング入門2 8 構造体を使ったプログラム(メンバの初期化) ソースファイル名:list1204.c (p.275, 若干変更) 構造体メンバの初期化 /* 学生を表す構造体で表した佐中君を初期化 */ #include <stdio.h> typedef struct { char name[20]; int height; float weight; } student; /* 名前 */ /* 身長 */ /* 体重 */ int main(void) { student sanaka = {"Sanaka", 175, 60.5}; printf("氏 名 = %s\n", sanaka.name); printf("身 長 = %d\n", sanaka.height); printf("体 重 = %f\n", sanaka.weight); 構造体メンバの初期化 return (0); } プログラミング入門2 9 構造体同士の値の代入 (p.280) 同じ種類の構造体データであれば,互いに値を代入すること が可能 student aoki, maeda; aoki = maeda; maedaのメンバ(name, height, weight) をそれぞれaokiの対応するメンバに代入 配列では不可能! プログラミング入門2 10 復習: 配列のコピー 注意点 (p.93) va[5], vb[5] と2つの配列は要素数も同じだし,もっと簡単に 次のように代入できないの? vb = va ; for (i = 0; i < 5; i++) vb[i] = va[i]; 面倒でも,1つ1つ代入していく 重要 代入演算子によって,配列を代入することはできない プログラミング入門2 11 関数での構造体データの使用(値変更なし) ソースファイル名:struct1.c 関数への構造体データの受け渡し(値は変更しない) #include <stdio.h> typedef struct { char name[20]; int height; float weight; } student; /* 名前 */ /* 身長 */ /* 体重 */ void print_data( student std ) { printf("氏 名 = %s\n", std.name); printf("身 長 = %d\n", std.height); printf("体 重 = %f\n", std.weight); } int main(void) { student sanaka = {"Sanaka", 175, 60.5}; 構造体データを受け取り, 値を表示する関数 値を変更しない→ポインタでなくてOK print_data( sanaka ); return (0); } プログラミング入門2 12 関数での構造体データの使用(値変更あり) ソースファイル名:struct2.c 関数への構造体データの受け渡し(値の変更あり) #include <stdio.h> typedef struct { char name[20]; int height; /* 身長 */ float weight; /* 体重 */ } student; /* 名前 */ void change_data( student *std ) { (*std).height = 180; (*std).weight = 80.0; } 構造体データを受け取り, 値を変更する関数 値を変更する→ポインタ(アドレス)で受け取り! int main(void) { student sanaka = {"Sanaka", 175, 60.5}; change_data( &sanaka ); printf("氏 名 = %s\n", sanaka.name); printf("身 長 = %d\n", sanaka.height); printf("体 重 = %f\n", sanaka.weight); return (0); } プログラミング入門2 13 解説 構造体のポインタ渡し change_data( &sanaka ); *stdはsanaka のエイリアス 106番地 void change_data( student *std ) { (*std).height = 180; (*std).weight = 80.0; } 106番地 sanaka (*std).height → *std.height *std std student型のオブジェクトのアドレス を入れるための箱 (student型オブジェクトへのポインタ) ()は省略不可 *よりも.の方が優先順位が高いため, *(std.height)と解釈されてしまう! プログラミング入門2 14 関数での構造体データの使用(値変更あり) ソースファイル名:struct3.c(p.277,変更あり) 関数への構造体データの受け渡し(値の変更あり,アロー演算子使用) #include <stdio.h> typedef struct { char name[20]; int height; /* 身長 */ float weight; /* 体重 */ } student; /* 名前 */ void change_data( student *std ) { std->height = 180; std->weight = 80.0; } 構造体データを受け取り, 値を変更する関数 値を変更する→ポインタ(アドレス)で受け取り! int main(void) { student sanaka = {"Sanaka", 175, 60.5}; change_data( &sanaka ); printf("氏 名 = %s\n", sanaka.name); printf("身 長 = %d\n", sanaka.height); printf("体 重 = %f\n", sanaka.weight); return (0); } プログラミング入門2 15 アロー(->)演算子 change_data( &sanaka ); void change_data( student *std ) { (*std).height = 180; (*std).weight = 80.0; } std->height = 180; = void change_data( student *std ) { std->height = 180; std->weight = 80.0; } 構造体へのポインタ名 -> メンバ 重要 ポインタptrが指す構造体のメンバmemである(*ptr).memは, ->演算子を用いてptr->memと簡潔に記述せよ プログラミング入門2 16 複数のデータの扱い (構造体の配列, p.282) 構造体データを複数扱う際には,構造体の配列を 用いる(データカードを人数分用意する) 構造体の配列の宣言 typedef struct { char name[20]; int height; float weight; } student; std[0].name std[0] std[0].height std[0].weight std[1].name std[1] std[1].height std[1].weight std[2].name student std[5]; std[2] std[2].height std[2].weight ・・・・・・・・・・・・・ プログラミング入門2 17 構造体の配列 ソースファイル名:list1208.c (p.283を変更) 構造体の配列 #include <stdio.h> #define NUMBER 5 /* 学生の人数 */ typedef struct { char name[20]; /* 名前 */ int height; /* 身長 */ float weight; /* 体重 */ } student; int main(void) { int i; student std[]= { { "Sato", 178, 61.0 }, { "Sanaka", 175, 60.5 }, { "Takao", 173, 80.0 }, { "Mike", 165, 72.0 }, { "Masaki", 179, 77.5 }, }; puts("-----------------------------"); for (i = 0; i < NUMBER; i++) printf("%-8s %6d%6.1f\n", std[i].name, std[i].height, std[i].weight); puts("-----------------------------"); return (0); } プログラミング入門2 18 構造体の配列を関数へ渡す方法 ソースファイル名: struct4.c #include <stdio.h> #define NUMBER 5 /* 学生の人数 */ typedef struct { char name[20]; /* 名前 */ int height; /* 身長 */ float weight; /* 体重 */ } student; void print_data( student data[ ] ) = void print_data( student data[] ) { int i; puts("-----------------------------"); for (i = 0; i < NUMBER; i++) printf("%-8s %6d%6.1f\n",data[i].name, data[i].height, data[i].weight); puts("-----------------------------"); } student *data どちらも配列の先頭アドレスを受け取る 受け取ると,関数内で data[i]として 配列要素を扱える in main(void) { student std[] = { { "Sato", 178, 61.0 }, { "Sanaka", 175, 60.5 }, { "Takao", 173, 80.0 }, { "Mike", 165, 72.0 }, { "Masaki", 179, 77.5 }, }; print_data( std ); 配列データを関数に渡す時には, その配列の先頭要素のアドレスを渡す std(配列名)=&std[0] return (0); } プログラミング入門2 19 演習課題 (第11回) 問1)構造体 (kadai11-1.c) キーボードから3点の2次元座標値(x, y)を読み込み, 3点から作られる3角形の面積Sを出力するプログラムを作成せよ。 p2 1 S 2 2 2 a b ab 2 但し,構造体は以下のものを用いること a p1 S p3 b typedef struct { double x; double y; } point; プログラミング入門2 20 演習課題 (第11回) 問2)構造体の配列と関数(kadai11-2.c) student構造体の配列を用い,5名分の学生データを体重の軽い順 に並べ替え(ソート),並べ替える前と並べ替えた後の結果を表示 するプログラムを作成せよ。 並べ替え(ソート)のアルゴリズムについては,前回のレポートを参 考にせよ。 typedef struct { char name[20]; /* 名前 */ int height; /* 身長 */ float weight; /* 体重 */ } student; void weight_sort( student *data, int num); もしくは, student data[ ] プログラミング入門2 配列の要素数 21
© Copyright 2024 ExpyDoc