13.2 定義結構體

定義的語法:關鍵字 struct、你取的型態名稱、大括號裡列出成員、結尾一個分號

struct student {      // 定義一個叫 student 的新型態
    string name;      // 成員變數:姓名
    int seat;         // 成員變數:座號
    string phone;     // 成員變數:電話
};                    // 結尾的分號千萬別忘!

這五行就「發明」了一個新型態 student。大括號裡宣告的變數叫這個結構體的成員變數(member variables);成員的型態不限——intstring、陣列、vector,甚至另一個結構體都可以。定義通常放在 main 外面(跟全域變數同一個位置),讓整份程式都看得到它。型態名稱自己取,規則跟變數命名相同;有人習慣首字母大寫(提醒自己「這是型態、不是變數」),小寫也完全可以——本單元兩種都會示範。

宣告變數、用「.」存取成員

定義好之後,student 就是一個型態名稱,宣告變數的寫法跟 int a; 一模一樣;存取成員用句點 .——a.name 就是「a 的 name」:

#include <iostream>
#include <string>
using namespace std;

struct student {
    string name;
    int seat;
    string phone;
};

int main() {
    student a;                    // 宣告一個 student 型態的變數
    a.name = "temmie";            // 用「.」存取成員:a 的 name
    a.seat = 60;
    a.phone = "0912345678";
    cout << a.name << ' ' << a.seat << ' ' << a.phone << '\n';
    return 0;
}

執行結果:

temmie 60 0912345678

a.name 就是一個普通的 stringa.seat 就是一個普通的 int——所有你會的操作(運算、比較、當參數傳)它們都照常支援。句點就是「的」,這個直覺你其實早就有了:p.first10.11)、v.size()10.2)都是同一個句點。

結構體陣列與整包賦值

student 既然是型態,開陣列天經地義:student a[35]; 就是 35 位同學,a[i]完整的一包a[i].name 是第 i 包裡的姓名。讀入要逐成員寫——整包 cin >> a[i] 是編譯錯誤,因為沒人教過 cin 一個 student 長什麼樣:

#include <iostream>
#include <string>
using namespace std;

struct student {
    string name;
    int seat;
    string phone;
};

student a[35];        // 結構體陣列:35 個 student,每一格都是完整的一包

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a[i].name >> a[i].seat >> a[i].phone;   // a[i] 是一個 student
    }

    student b = a[0];         // 整包賦值:三個成員一次全部複製
    b.seat = 99;              // 動的是複本,a[0] 不受影響
    cout << a[0].name << ' ' << a[0].seat << '\n';
    cout << b.name << ' ' << b.seat << '\n';
    return 0;
}

執行結果(輸入 2alice 5 0911111111bob 7 0922222222):

alice 5
alice 99

注意 student b = a[0]; 這行:結構體可以用 = 整包賦值。上冊的陣列不行(8.8 提過 t = s 是編譯錯誤)、vector 可以(10.6)——結構體站在 vector 這邊。而且就算成員裡包著一個陣列,賦值時陣列的內容也會整包照搬,這是結構體幫陣列「開的後門」。

動手試試看:自己定義一個「書」的結構體(書名 string、頁數 int、價格 int),宣告陣列、讀入 3 本書的資料再逐本印出——把定義、宣告、句點、陣列一次走過。