1 ! 学生の成績を管理したい. 2 ! ! ID,名前,試験の成績 ! 学生の成績を管理したい. ! ID,名前,試験の成績 どうやって管理する? ! ! 配列を用いるのも1つ. 構造体を用いて新しい型を作成する. ! IDと名前と試験の成績をもつStudent型を作成する. ! ただ,成績でソートするときに面倒 情報を1つにまとめたい. ! 構造体は複数の情報を1つの型として扱える. ▪ 1つ入れ換えると全配列を入れ換える必要がでる. id[0] id[1] id[2] id[3] Student型 id name score id[4] na[0] na[1] na[2] na[3] na[4] sc[0] sc[1] sc[2] sc[3] sc[4] 3 id: 4 name: Suzuki score : 74 Student型の配列 st[0] st[1] st[2] st[3] st[4] 4 構造体を作るには,structを使う. ! 定義したStudentを使う. ! ! using namespace std; の直後に定義するのが一般的. Student x; struct Student{ x.id = 4; int id; string name; x.score = 74; int score; }; struct (型の名前){必要なデータ型} ; ! 構造体の変数宣言:「構造体の名前」+「変数名」 構造体の各要素にアクセス:「.(ドット)」を使う. ! { }の後ろのセミコロンを忘れないこと ! あとは,普通のデータ型と同じように扱える. ! ! ! 自作する型の名前は先頭を大文字にする方がベター ▪ セミコロンの前にxと書くと,Student型のxを同時に宣言できる仕様なので,何も宣言 しない場合もセミコロンが必要.(教科書参照) 5 会社のスタッフの管理. ! id: 4 name: Suzuki score : 74 x.name = Suzuki ; //staff.cpp Staff z; John : 38 int age; cin >> z.name >> z.age; cout << z.name << John : 38 }; Staff x; cout << x.name << : << x.age << endl; Staff y = x; cout << y.name << : << y.age << endl; << z.age << endl; 構造体の配列も宣言できる. list[0] = x; list[1] = y; x.name = John ; x.age = 38; : Staff list[3]; 名前と年齢をもつ Staff構造体を作成 int main(void){ キーボードからの入力. z.nameで変数zの名前に 入力された値を代入. //続き % staff string name; 会社のスタッフの管理. ! //左までの実行例 struct Staff{ 6 list[2] = z; Staff xでStaff型の変数xを宣言. x.nameで名前にアクセス. for(int i=0; i<3; i++){ cout << list[i].name << : << list[i].age << endl; listの中の1つ1つはStaff型. list[0].ageは配列の先頭のStaff型 の年齢にアクセスしている. } Staff型の変数同士の代入も可能 return 0; 7 } 8 ! 配列のように初期化できる. ! 構造体の各要素の型に注意して初期化すること. Staff型のxを name = John ,age =38 で初期化 //staff.cpp //Staff構造体の宣言 Student x; int main(void){ x.id = 4; x.name = Suzuki ; Staff x = { John , 38}; Student x ={4, Suzuki , 74}; xをコピーしたyのnameを Bob に変更. Staff y = x; y.name = Bob ; x.score = 74; ! 会社のスタッフの管理. ! Staff list[3] = {x, y, { David , 27}}; 構造体の配列の初期化は2次元配列の初期化に似ている. for(int i=0; i<3; i++){ cout << list[i].name << Student list[2] = {{ 4, Suzuki , 74}, { 6, Tanaka , 63}}; : Staff型の1次元配列を宣言 し,xとyと27歳のDavidで 初期化. << list[i].age << endl; } return 0; } 9 ! 構造体の要素には任意の型を用いることができる. ! ! 違う構造体の中身は変数の名前が同じでも大丈夫. struct Point{ int x, y; //x座標,y座標 }; Point型をもつTriangle型の利用. //triangle.cpp △ABC //Point構造体の定義 struct Triangle{ string name //点の名前 10 //Triangle構造体の定義1 string name; //三角形の名前 Point a, b, c; //3点を用意. cout << t.name << ={ << t.a.name << A:(3, 5) B:(1, 1) struct Triangle{ C:(4, 2) C:(4, 2) Triangle t = { ABC , { A ,3, 5}, { B , 1, 1}, { C , 4, 2}}; }; //Triangle定義1 △ABC B:(1, 1) int main(void){ A:(3, 5) :( << t.b.x << , << t.b.y << ), << t.c.name << :( << t.c.x << , << t.c.y << ) return 0; Point abc[3]; //3点を用意. } }; //Triangle定義2 11 << t.a.x << , << t.a.y << ), << t.b.name << << string name; //三角形の名前 :( } << endl; //実行例 % triangle ABC = { A:(3,5), B:(1,1), C(4,2)} Triangle型の 名前,Point型a, b, c の順に初期化. まずTriangle型の各要 素にアクセスし, Point型がもっている 各要素にアクセスする. 12 Point型をもつTriangle型の利用. ! ! //triangle2.cpp △ABC //Point構造体の定義 //Triangle構造体の定義2 B:(1, 1) int main(void){ ! 関数の戻り値や引数としても利用できる. A:(3, 5) ! 値渡しの場合,関数内で構造体の中身を変更してもmainでは反 ={ ; for(int i=0; i<3; i++){ cout << t.abc[i].name << : ( << t.abc[i].x << , << t.abc[i].y << ) ; if(i!=2){ cout << , ;} } cout << } << endl; return 0; } //実行例 % triangle2 ABC = { A:(3,5), B:(1,1), C(4,2)} //inoutPoint.cpp //Point構造体の宣言 //Point input(void)関数 //void printPoint(Point)関数 int main(void){ Point a = input( ); printPoint(a); for(int i=0; i<N; i++){ まずTriangle型の Point型配列にアクセス してから,Point型の各 要素にアクセスする. } } printPoint関数内で, p.name = abc ; としてもmain内では変更されていない. 13 14 ! リファレンス引数 ! (ざっくり)関数で変更した値を引き継ぎたいときに用いる. ! 構造体のリファレンス引数 ! 関数で変更した値を引き継ぎたいときに用いる.(左) B11 ! 構造体のデータサイズが大きい場合にも用いる.(右) ▪ 値を変更しない場合はconst宣言をしておく. C:(2,4) void update(Point &p){ list[i] = input( ); void printPoint(const Point &p){ p.x += 2; printPoint(list[i]); cout << p.name p.y += 3; } << :( p.x << , << p.y << ) << endl; return; return 0; } return; return p; A:(3,5) C24 << :( p.x << , << p.y << ) << endl; cin >> p.name >> p.x >> p.y; A35 const int N=2; cout << p.name Point p = { NULL , 0, 0}; % inputPoint B:(1,1) void printPoint(Point p){ Point input(void){ Triangle型の 名前,Point型配列 の順に初期化. //実行例 cout << endl; Point list[N]; 映されない. C:(4, 2) Triangle t = { ABC , {{ A ,3, 5}, { B , 1, 1}, { C , 4, 2}}}; cout << t.name << 構造体は1つのデータ型として扱える. } 15 return; } 16 //refPoint.cpp //Point構造体の宣言 //update関数 //point関数 int main(void){ Point a = { X , 1, 2}; //実行例 ! % refPoint ! (ざっくり)構造体のリファレンスと同じような用途で使用できる. X:(3, 5) ! ポインタ先の構造体の各要素にアクセスする方法. A:(5, 7) ▪ 「.」を用いる場合 (*p). x B:(7, 9) ▪ 「->」アロー演算子を用いる場合 p->x update(a); print(a); const int N = 2; Point b[N] = {{ A , 3, 4}, { B , 5, 6}}; 構造体のポインタ引数 リファレンス引数には, 変数をそのまま渡す. void update(Point *p){ update(b[i]); } return 0; if(p!=0){ (*p).x += 2; for(int i=0; i<N; i++){ print(b[i]); void update(Point *p){ if(p!=0){ p->x += 2; (*p).y += 3; リファレンス引数には, 変数をそのまま渡す. p->y += 3; } } return; return; } } } 17 //refPoint.cpp //Point構造体の宣言 //update関数 //point関数 int main(void){ Point a = { X , 1, 2}; ! //実行例 const int N = 2; Point b[N] = {{ A , 3, 4}, { B , 5, 6}}; 配列と配列の要素数を1つの構造体にする. % refPoint ! 配列内の要素数の出力:配列に保存されている要素数が重要. X:(3, 5) ! 構造体にしてしまって,配列とその要素数を1まとめにする. A:(5, 7) B:(7, 9) const int N =10; update(&a); print(&a); 18 struct MyArray{ int num; ポインタ引数には, アドレスを渡す. double array[N]; arrayに実際に入っている要 素数を保存するための変数. }; for(int i=0; i<N; i++){ update(&b[i]); print(&b[i]); } return 0; } ポインタ引数には, アドレスを渡す. 19 20 ! MyArray構造体のもつarray配列の要素の表示. //myArray.cpp ! numを利用する. //printR ! 左がリファレンス引数版,右がポインタ引数版 void printR(const MyArray &a){ cout << a->array[i] << cout << endl; printR(x); MyArray型のxの numを5, array[N]を 1.2, 2.3, 3.4, 4.5, 5.6, 残りは0 で初期化. cout << endl; ; printP(&x); } } 1.2 2.3 3.4 4.5 5.6 MyArray x = {5, {1.2, 2.3, 3.4, 4.5, 5.6}}; for(int i=0; i<a->num; i++){ } % myArray 1.2 2.3 3.4 4.5 5.6 int main(void){ if(a!=0){ ; (リファレンス版) //printP関数(ポインタ版) void printP(const MyArray *a){ for(int i=0; i<a.num; i++){ cout << a.array[i] << //実行例 //MyArray構造体の宣言 return 0; } } cout << endl; } ポインタ引数には,アドレスを渡す. 21 ! Point型変数pへのキーボードからの入力 22 ! ! cinやcoutを使うときに毎回以下を書くのは面倒. istream& operator >>(istream &in, Point& p){ ▪ cin >> p.name >> p.x >> p.y; return in >> p.name >> p.x >> p.y; ▪ cout << p,name :( << a.x < << , << a.y << ) ; ! cinやcoutをPoint型にも対応させる. } 解決法 ostream& operator <<(ostream &out, Point& p){ ! input関数,output関数を作成する. return out << p.name :( << p.x < << , << p.y << ) ! cinやcoutをPoint型にも対応させる. } ! これで,Point型変数pに対応したcin, coutが利用できる. ! cin >> p; ! cout << p; 23 24
© Copyright 2024