202-ProgExⅡ / 構造体
構造体とは
異なる型のデータをひとまとめにして管理するためのデータ型
なぜ構造体を使う?
管理がしやすくなる
イメージしやすい
C言語のプリミティブな型だけでは表現しきれない型を定義できる
例えば…
ユーザ
書籍
授業
名刺
郵便
...
などなどなんでも良いけど,「1つ」と数えられるものはいくつかの情報の組み合わせを内包している
先ほどの例でどんなデータがあるかちょっと考えてみる
ユーザ
ユーザID
ユーザ名
メールアドレス
パスワード
登録日
・・・
書籍
タイトル
著者(複数)
出版社
出版年月日
ページ数
ISBN
価格
・・・
授業
授業名
年度
担当教員(複数)
単位数
実施学科
実施学年
・・・
名刺
氏名
役職
メールアドレス
電話番号
住所
・・・
郵便
宛先の郵便番号
宛先の住所
宛先の名前
送元の郵便番号
送元の住所
送元の名前
・・・
しかも,この構造体というものの配列とか,構造体を内蔵した構造体とかもありえる.
配列にすると
ユーザの配列
書籍の配列
授業の配列
名刺の配列
郵便の配列
・・・
構造体の中に構造体のパターンもありえる
授業
授業名
年度
担当教員(複数)
単位数
実施学科
実施学年
・・・
担当教員
氏名
学部
メールアドレス
オフィスアワー
・・・
この時,この要素となる情報のことをメンバと呼ぶ
/icons/hr.icon
構造体の定義と初期化は,「たい焼きの型」と「たい焼き」の関係のようなものです.
構造体を定義するということは,どんな形のたい焼きにするのかという形の型を作っているだけです
構造体を定義しても,たい焼きそのものを作っているわけではありません
実際のデータを流し込んで初めてたい焼きになります
/icons/hr.icon
構造体の基本構文
code:sample.c
struct 構造体名 {
データ型 メンバ名;
データ型 メンバ名;
...
};
宣言と初期化
code:sample.c
struct Person {
int age; // 年齢(整数)
};
struct Person person1;
strcpy(person1.name, "Alice"); // 名前を設定
person1.age = 25; // 年齢を設定
定義と同時初期化
code:sample.c
struct Person {
int age; // 年齢(整数)
};
struct Person person2 = {"Bob", 30};
ここで,scruct Person person1の部分は今までのint aみたいな存在な訳ですが,structが増えている分何度も書くことになれば少し面倒ですので,typedefを使って構造体の名前を新しい型として名前をつけることが可能です.この新しい名前のことをエイリアスと呼んだりします.
code:before.c
// 普通の書き方
struct Person {
int age; // 年齢(整数)
};
struct Person person1;
code:after-1.c
// パターン1
struct Person {
int age; // 年齢(整数)
};
typedef struct Person Person;
Person person1;
構造体の定義とtypedefによるエイリアスの定義を別にして書くパターンです.
afterでは構造体を使う際にstructを毎回書く必要がなくなりました.
code:after-2.c
// パターン2
typedef struct Person {
int age; // 年齢(整数)
} Person;
Person person1;
構造体の定義とエイリアスの定義を同時に各パターンです.
code:after-3.c
// パターン3
typedef struct {
int age; // 年齢(整数)
} Person;
Person person1;
無名構造体を使ってさらに省略して各パターンです.とても便利です.
この方法が最も短く書くことが可能ですが,この方法だと,構造体には名前がついていないので,必ずエイリアスを使う必要があることに注意が必要です.
shinyaoguri.icon今後は基本的にtypedefを使う前提で話を進めます
配列との組み合わせ
code:sample.c
struct Person {
int age;
};
int main() {
struct Person people3 = { {"Alice", 25},
{"Bob", 30},
{"Charlie", 35}
};
for (int i = 0; i < 3; i++) {
printf("Name: %s, Age: %d\n", peoplei.name, peoplei.age); }
return 0;
}
構造体ポインタの利用
code:sample.c
typedef struct {
int age;
} Person;
void printPerson(Person *p) {
printf("Name: %s, Age: %d\n", p->name, p->age);
}
int main() {
Person person = {"Alice", 25};
printPerson(&person);
return 0;
}
構造体の入れ子
code:sample.c
struct Address {
};
struct Person {
int age;
struct Address address; // 入れ子構造体
};
int main() {
struct Person person = {"Alice", 25, {"Tokyo", "Japan"}};
printf("Name: %s, Age: %d\n", person.name, person.age);
printf("City: %s, State: %s\n", person.address.city, person.address.state);
return 0;
}