6.1. 構造体
構造体は、分散したデータを一つにまとめる事ができる型である。
例として、traP メンバーの名簿を考えよう。
今この講習に居るメンバーの traP ID、学籍番号、学年 の情報がほしいとする。
これらをプログラムで扱うとき、素朴には以下のように個別に変数を宣言すればよい。
string trap_id, student_id;
int grade;しかし、複数人分の情報を扱いたかったり、関数に渡したかったりするときにやや不便である。
例として、2人のメンバーの情報が完全に一致するか(同一か)を判定するプログラムを以下に記す。
#include <string>
#include <iostream>
using namespace std;
// 引数が長すぎる……
bool equals(
string trap_id1, string student_id1, int grade1,
string trap_id2, string student_id2, int grade2
) {
return trap_id1 == trap_id2
&& student_id1 == student_id2
&& grade1 && grade2;
}
int main() {
// 宣言が長すぎる……
string trap_id1, student_id1, trap_id2, student_id2;
int grade1, grade2;
cin >> trap_id1 >> student_id1 >> grade1
>> trap_id2 >> student_id2 >> grade2;
if (equals(
trap_id1, student_id1, grade1,
trap_id2, student_id2, grade2
)) {
cout << "same" << endl;
} else {
cout << "not same" << endl;
}
}これはあまりに長い。 配列を使えば宣言はそれぞれの変数でまとめることはできるが、できれば学生情報は一つの変数にまとめたい。
ここで、複数の変数をまとめてひとつの値として扱える構造体 (struct) を導入し、構造体の 型 を定義する。
TIP
他の言語などではクラスやオブジェクトなどと呼ばれる。
用語
- 構造体に属する変数はメンバ変数 (member variable) と呼ばれている。
- ある構造体の型を持った値は、その構造体のインスタンス (instance) と呼ばれる。
構造体を用いると、コードは以下のようになる。
#include <iostream>
#include <string>
using namespace std;
struct Member {
string trap_id, student_id;
int grade;
};
bool equals(Member member1, Member member2) {
return member1.trap_id == member2.trap_id &&
member1.student_id == member2.student_id &&
member1.grade == member2.grade;
}
int main() {
Member zer0star{"zer0-star", "22BXXXXX", 2};
Member hoshimiya{"hoshimiya", "99B99999", 99999};
if (equals(zer0star, hoshimiya)) {
cout << "same" << endl;
} else {
cout << "not same" << endl;
}
}少し見やすくなったように感じないだろうか?
struct Member {
string trap_id, student_id;
int grade;
};この部分で構造体 Member を定義している。構造体 Member は以下の3つのメンバ変数を持つ。
string型のtrap_idstring型のstudent_idint型のgrade
宣言は以下のように対応する。
Member zer0star{"zer0-star", "22BXXXXX", 2};
Member hoshimiya{"hoshimiya", "99B99999", 99999};これは省略されているが、先頭から順に trap_id = "zer0-star", student_id = "22BXXXXX", grade = 2 とするという宣言である。
次に、構造体を使用する方を見てみよう。equals 関数の実装は以下のとおり。
bool equals(Member member1, Member member2) {
return member1.trap_id == member2.trap_id &&
member1.student_id == member2.student_id &&
member1.grade == member2.grade;
}関数の引数として、 int 型などと同様に Member 型を受け取ることができる。 Member 型の変数1つを渡すのは、 trap_id student_id grade の3変数を渡したことと同じになる。
Member 型の各変数にアクセスするには、 member.trap_id のように、 . で変数名とメンバ変数を繋げれば良い。
このようにしたあとは、以下のように構造体を使って equals を使用することができる。
if (equals(zer0star, hoshimiya)) {
cout << "same" << endl;
} else {
cout << "not same" << endl;
}なんだか仰々しいものに見えるかもしれないが、本質的には複数の変数をまとめて、わかりやすくなるように取り扱っているだけである。