• 検索結果がありません。

基礎プログラミング2015

N/A
N/A
Protected

Academic year: 2021

シェア "基礎プログラミング2015"

Copied!
22
0
0

読み込み中.... (全文を見る)

全文

(1)

応用プログラミング

第10回

構造体

(2)
(3)

構造体

*国民の個人情報を管理したい

例: マイナンバー(id), 名前(na), 年齢(ag) *管理する方法は?

 配列を用いる方法

 ただし, 年齢などでソートするとき面倒

na[0] na[1] na[2] na[3] na[4]

ag[0] ag[1] ag[2] ag[3] ag[4]

id[0] id[1] id[2] id[3] id[4]

ここをソートしたら…

ここも合わせてソート ここも合わせてソート

(4)

構造体

*国民の個人情報を管理したい

例: マイナンバー(id), 名前(name), 年齢(age)

*構造体を用いて新しい型を作成する

 マイナンバー・名前・年齢の情報をもつ新しいNation型を作成  構造体は複数の情報を一つの型として扱える

Na[0] Na[1] Na[2] Na[3] Na[4] Nation型 id name age Nation型の配列Na id: 12345 name: Sasaki age: 30

(5)

構造体の定義(P.100)

struct

Nation{

int id;

string name;

int age;

}

;

*構造体を作る方法  structによって定義する  using namespace std; の直後(関数の前)に定義するのが一般的 struct 型の名前{必要なデータ型の宣言}  自作する型の名前は先頭を大文字にするのが良い(通常の 変数型と区別するため)  { }の後ろのセミコロン「;」を忘れないこと! (「;」の前に変数を書くと, 同時に宣言もできる仕様なので何 も宣言しない場合でも「;」が必要.空文のような扱い.)

struct

Nation{

int id;

string name;

int age;

} x, y

;

// Nation型の変数x, y

(6)

構造体の基本(P.101)

*定義した構造体を使用する方法

Nation

x;

x.id = 12345;

x.name = “Sasaki”;

x.age = 30;

id: 12345 name: Sasaki age: 30  構造体の変数宣言:「構造体の名前」+「変数名」  構造体の各要素にアクセス:「変数名」+「.(ドット)」+「要素名」 *あとは基本的に普通のデータ型と同様に扱える

(7)

構造体の基本(P.101)

Staff{ string name; int age; }; int main(){ Staff x; x.name = “John”; x.age = 33;

cout << x.name << ‘ ’ << x.age << endl; Staff y = x;

cout << y.name << ‘ ’ << y.age << endl; return 0;

}

// 実行結果 John 33

(8)

構造体の基本(P.101)

// Staff構造体の定義は先ほどと同じ int main(){ Staff list[3]; list[0].name = “Tom”; list[0].age = 29; list[1].name = “Bob”; list[1].age = 31;

cin >> list[2].name >> list[2].age; for(int i = 0; i < 3; i++){

cout << list[i].name << ‘ ’ << list[i].age << endl; } return 0; } // 実行結果 Alice 25 Tom 29 Bob 31 Alice 25

(9)

構造体変数の初期化(P.102)

Staff x; x.name = “Sasaki”; x.age = 30; *配列のようにして初期化する  構造体の各要素(メンバ)の型に注意して初期化値を決める Staff x = {“Sasaki”, 30}; Staffの要素は string型, int型の順 *構造体の配列の初期化は2次元配列のときに似ている Staff member[2] = {{“Sasaki”, 30}, {“Tom”, 29}};

(10)

構造体変数の初期化(P.102)

// Staff構造体の定義は同じ int main(){

Staff x = {“Bob”, 31};

Staff y = x; // xが持つ値を初期化値に指定 Staff list[3] = {x, y, {“Sasaki”, 30}};

for(int i = 0; i < 3; i++){

cout << list[i].name << ‘ ’ << list[i].age << endl; } return 0; } // 実行結果 Bob 31 Bob 31 Sasaki 30 Staff型の1次元配列を 宣言・初期化

(11)

構造体・配列を要素にもつ構造体(P.103)

*構造体は任意の型の要素を持てる(例:配列, 別の構造体, etc.)  異なる構造体の中では同じ変数名を使ってよい(関数と同じ) struct Point{ string name; // 点の名前 int x, y; // x, y座標 }; // 定義0 struct Triangle1{ string name; // 三角形の名前 Point a, b, c; // 三角形の頂点 }; // 定義1 struct Triangle2{ string name; // 三角形の名前 Point abc[3]; // 三角形の頂点 }; // 定義2 y x B:(4,2) ΔABC C:(1,1) A:(2,3)

(12)

構造体・配列を要素にもつ構造体(P.103)

// 定義0 // 定義1 int main(){ Triangle1 t = {“T1”, {“A”, 2, 3}, {“B”, 4, 2}, {“C”, 1, 1}}; cout << t.name << “:{”

<< t.a.name << “(” << t.a.x << “, ” << t.a.y << “)” << “, ” << t.b.name << “(” << t.b.x << “, ” << t.b.y << “)” << “, ” << t.c.name << “(” << t.c.x << “, ” << t.c.y << “)}” << endl; return 0;

}

t.name : Triangle1型変数 t の name(名前)にアクセス

t.a.name : t がもつPoint型変数 a の name(名前)にアクセス t.a.x : t がもつPoint型変数 a の x(x座標)にアクセス

t.a.y : t がもつPoint型変数 a の y(y座標)にアクセス

// 実行結果

(13)

構造体・配列を要素にもつ構造体(P.103)

// 定義0 // 定義2 int main(){ Triangle2 t = {“T1”, {{“A”, 2, 3}, {“B”, 4, 2}, {“C”, 1, 1}}}; cout << t.name << “:{”; 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; } // 実行結果 T1:{A(2, 3), B(4, 2), C(1, 1)}

t.abc[i].name : t がもつPoint型配列abc のi番目の name(名前) t.abc[i].x : t がもつPoint型配列abc のi番目の x(x座標)

(14)

構造体の関数での利用(P.104)

*構造体は一つの変数型として扱える  関数の仮引数や戻り値としても指定できる  他の変数同様, 関数内で値を変更してもmain関数方には影響なし //構造体Pointの定義 Struct Point{ string name; int x, y; }; //Point型の仮引数をもつoutput関数

void output(Point k){

cout << k.name << “, ” << k.x << “, ” << k.y << endl; k.name = “done”; } //返却値がPoint型の関数input Point input ( ){ Point p = {“noname”, 0, 0}; cin >> p.name << “, ” << p.x << “, ” << p.y << endl; return p; } 関数内で変更しても main関数(呼び出し元)の 変数には影響しない 構造体を用いることにより, return文で一度に複数の 情報を送ることができる

(15)

構造体の関数での利用(P.104)

Struct Point{ string name; int x, y; }; Point input ( ){ Point p = {“noname”, 0, 0}; cin >> p.name << “, ” << p.x << “, ” << p.y << endl; return p; }

void output(Point k){

cout << k.name << “, ” << k.x << “, ” << k.y << endl; k.name = “done”; } //左からの続き int main(){ Point a = input(); output(a);

cout << a.name << endl; const int N = 2; Point b[N]; for(int i = 0; i < N; i++){ b[i] = input(); output(b[i]); } return 0; } //実行例 A 1 2 A, 1, 2 A B 3 0 B, 3, 0 //以下略

(16)

構造体のリファレンス引数(P.105)

*構造体をリファレンス引数で関数に渡すことが可能

*構造体のリファレンス引数に対しては, 2通りの使われ方がある: (左) 関数内での値の更新を呼び出し元の関数にも反映させるとき (右) サイズが大きい構造体を引数として取るとき

void update(Point& p){

p.x += 2; p.y += 3; }

void print(const Point& p){

cout << p.name << “, ” << p.x << “, ” << p.y << endl; } 右の場合は, 値の変更を目的としてい ないので, 習慣的にconst宣言を行う (値の変更をさせないようにする)

(17)

構造体のリファレンス引数(P.105)

struct Point{ string name; int x, y;

};

void update(Point& p){ p.x += 2;

p.y += 3; }

void print(const Point& p){

cout << p.name << “, ” << p.x << “, ” << p.y << endl; } int main(){ Point a = {“X”, 1, 2}; update(a); print(a); const int N = 2; Point b[N] = {{“A”, 3, 4}, {“B”, 5, 6}}; for(int i = 0; i < N; i++){ update(b[i]); } return 0; } // 実行結果 X, 3, 5 A, 3, 4 B, 5, 6

(18)

構造体のポインタ引数(P.106)

*構造体をポインタ引数で関数に渡すことが可能 *ポインタとして構造体の要素にアクセスする方法が2通りある: (左) 間接演算子「*」を用いる方法 (右) アロー演算子「->」を用いる方法 void update(Point *p){ if(p != 0){ (*p).x += 2; (*p).y += 3; } } void update(Point *p){ if(p != 0){ p -> x += 2; p -> y += 3; } } 同値 もしポインタpが何も指し示していなければ, プログラムが異常を起こすので, pがNULLポインタかどうかを確認(p != 0)

(19)

構造体のポインタ引数(P.106)

struct Point{ string name; int x, y; }; void update(Point *p){ if(p != 0){ p -> x += 2; // (*p).x += 2; p -> y += 3; // (*p).y += 3; } }

void print(const Point *p){ if(p != 0){ cout << p -> name << “, ” << p -> x << “, ” << p -> y << endl; } } int main(){ Point a = {“X”, 1, 2}; update(&a);

print(&a);

const int N = 2;

Point b[N] = {{“A”, 3, 4}, {“B”, 5, 6}}; for(int i = 0; i < N; i++){

print(&b[i]); } return 0; } // 実行結果 X, 3, 5 A, 3, 4 B, 5, 6

(20)

配列の情報をまとめる構造体(P.107)

const int N = 10; //大域変数 struct MyArray{ int size; double d[N]; }; *配列と配列の要素数を一つの構造体にする  配列内の要素を出力 → 配列のどこまで値が入っているかが重要  構造体にして, 配列とその要素数をひとまとめにする (例) MyArray k = {3, {1.1, 2.2, 3.3}}; k.sizeに要素数3が格納されているので, 関数にはkを渡すだけで良い.

(21)

配列の情報をまとめる構造体(P.107)

const int N = 10; //大域変数 Struct MyArray{ int size; double d[N]; };

void print(const MyArray& a){ for(int i = 0; i < a.size; i++)

cout << a.d[i] << “ ”; cout << endl;

}

void add(MyArray& a, double d){ if(a.size < N){ a.d[a.size] = d; a.size++; } } int main(){ MyArray x = {5, {1.2, 2.3, 3.4, 4.5, 5.6}}; print(x); for(double i = 1.0; i < 10.0; i++) add(x, i); print(x); return 0; } // 実行結果 1.2 2.3 3.4 4.5 5.6 1.2 2.3 3.4 4.5 5.6 1.0 2.0 3.0 4.0 5.0

(22)

練習問題

問題. 人名と好きな果物(高々3つ)を格納する配列の組を保存す るためのPfruit構造体を宣言し, ある果物を入力すると, その果物 が好きな人物の名前を列挙するプログラムを作成せよ.ただし, 入 力した果物が好きな人がいない場合は, 「Not exist」と出力せよ. // 実行例1

Input a fruit: orange Alice, Tom

// 3人の名前と好きな果物リスト Alice : banana, apple, orange

Bob : apple, strawberry Tom : apple, orange

// 実行例2

Input a fruit: apple Alice, Bob, Tom

// 実行例3

Input a fruit: pineapple Not exist.

参照

関連したドキュメント

このように資本主義経済における競争の作用を二つに分けたうえで, 『資本

方法 理論的妥当性および先行研究の結果に基づいて,日常生活動作を構成する7動作領域より

Series of numerical analysis to estimate structural frequency and modal damping were conducted for a two-dof model using the simulated external forces induced by impulse force and

Mochizuki, On the combinatorial anabelian geometry of nodally nonde- generate outer representations,

床版 主構造 横桁 支承 支モル 下躯体 下基礎 高欄 地覆 舗装 伸縮.

葛ら(2005):構造用鋼材の延性き裂発生の限界ひずみ,第 8

活性 クロマ チン構 造の存在... の複合体 がきわ

節の構造を取ると主張している。 ( 14b )は T-ing 構文、 ( 14e )は TP 構文である が、 T-en 構文の例はあがっていない。 ( 14a