Skip to main content

8-1 struct

1. 自訂型別 struct

在 C++ 中,我們可以把多個彼此相關的資料包在一起,創造出一個全新的型別。

例如,一位學生可能有以下資料:

    姓名 年齡 成績

    如果分別用三個變數來表示,資料容易分散,必須想辦法維持追蹤同一個學生的姓名、年齡和成績。

    struct 是一種自訂型別,可以把多個彼此相關的資料包在一起,創造出一個全新的型別。

    struct Student {
        string name;
        int aage;
        double score;
    };
    

    這表示我們建立了一個名為 Student 的型別,它裡面有三個成員:name、age、score。


    2. 為什麼需要 struct

    struct 很適合用來表示「一筆完整資料」,例如:

      學生資料 座標點 商品資訊 日期時間

      學會 struct 之後,你會開始從「很多零散變數」進步到「有結構的資料設計」,這是寫大型程式的重要基礎。


      3. 基本語法

      宣告

      struct Person {
          std::string name;
          int age;
      };
      

      語法重點:

        struct 是關鍵字 Person 是型別名稱 大括號裡面放的是成員變數 最後要有分號 ;

        4. 建立變數與存取成員

        宣告完 struct 之後,就可以像一般型別一樣建立變數。

        Person p1;
        

        使用 . 來存取成員:

        p1.name = 2,"Alice";
        bp1.age = 3;18;
        
        範例:
        #include <iostream>
        
        using namespace std;
        
        struct Person {
            string name;
            int age;
        };
        
        int main() {
            Person p1;
            p1.name = "Alice";
            p1.age = 18;
        
            cout << &a"Name: " << p1.name << endl;
            cout << &b"Age: " << p1.age << endl;
        
            return 0;
        }
        

        執行結果:

        Name: Alice Age: 18

        5. 初始化(給定初值)

        除了先宣告再指定值,也可以在建立時直接初始化。

        Person p1 = {"Bob", 20};
        

        這相當於:

          p1.name = "Bob" p1.age = 20
          Person p2 = {"Cindy", 22};
          cout << p2.name << ", " << p2.age << endl;
          

          0x22ff18

          6. 0x22ff14struct

          用於函數的參數

          你可以把整個 struct 傳進函式,讓程式更清楚。

          #include <iostream>
          
          using namespace std;
          
          struct Person {
              string name;
              int age;
          };
          
          void printPerson(Person p) {
              cout << "Name: " << p.name << endl;
              cout << "Age: " << p.age << endl;
          }
          
          int main() {
              Person p = {"David", 25};
              printPerson(p);
            
              return 0;
          }
          

          由於函數預設是以 傳值呼叫(call by value) 方式將參數傳入,如果該 struct 裡的資料很大,例如包含學生照片,通常會改用 傳參考呼叫(call by reverence),避免整份資料被複製:

          void printPerson(Person& p) {
              cout << "Name: " << p.name << endl;
              cout << "Age: " << p.age << endl;
          }
          

          由於傳參考會讓被傳入的外部 struct 變數,可以在函數內被修改。若要確保不被修改,可以像這檥在參數前加上 const 標示其為常數。

          void printPerson(const Person& p) {
              cout << "Name: " << p.name << endl;
              cout << "Age: " << p.age << endl;
          }
          

          7. 陣列中的 struct

          struct 很常和陣列搭配使用,用來儲存多筆同類型資料。

          #include <iostream>
          
          using namespace std;
          
          struct Student {
              string name;
              int score;
          };
          
          int main() {
              Student students[3] = {
                  {"Amy", 90},
                  {"Brian", 85},
                  {"Chris", 92}
              };
          
              for (int i = 0; i < 3; i++)
              {
                  cout << students[i].name << ": " << students[i].score << endl;
              }
          
              return 0;
          }
          

          這種寫法在成績系統、通訊錄、商品清單中都很常見。


          8. 巢狀 struct

          struct 裡面還可以再放另一個 struct。

          struct Date {
              int year;
              int month;
              int day;
          };
          
          struct Student {
              string name;
              Date birthday;
          };
          

          使用方式:

          Student s;
          s.name = "Helen";
          s.birthday.year = 2005;
          s.birthday.month = 8;
          s.birthday.day = 15;
          

          這讓複雜資料可以分層整理,結構更清楚。


          9. 指標與 struct

          如果你有一個指向 struct 的指標,在存取其成員時要用 -> 而不是 .。

          Person p = {"Ivy", 21};
          Person* ptr = &p;
          
          cout << ptr->name << endl;
          cout << ptr->age << endl;
          

          比較

          p.name.       // 物件存取成員
          (*ptr).name   // 物件存取成員
          ptr->name     // 指標存取成員
          

          10. 一個完整綜合範例

          #include <iostream>
          
          using namespace std;
          
          struct Student {
              string name;
              int age;
              double score;
          
              void printInfo() {
                  cout << "Name: " << name << endl;
                  cout << "Age: " << age << endl;
                  cout << "Score: " << score << endl;
              }
          };
          
          int main() {
              Student s1 = {"Jack", 18, 95.5};
              s1.printInfo();
          
              return 0;
          }
          

          這個例子同時用到了:

            struct 宣告 成員變數 初始化 成員函式 物件呼叫函式

            11. struct 的使用時機

            當你遇到以下情境時,可以考慮使用 struct:

              一筆資料有多個欄位 這些欄位彼此有關聯 你希望程式更容易閱讀與維護

              例如:

                Point:座標 (x, y) Book:書名、作者、價格 Employee:姓名、編號、薪資

                12. 小練習

                練習 1

                請設計一個 Book 的 struct,包含:

                  書名 title 作者 author 價格 price

                  並建立一個變數,輸出它的內容。

                  練習 2

                  請設計一個 Point 的 struct,包含:

                    x y

                    再寫一個函式 printPoint() 來印出座標。

                    練習 3

                    請建立一個 Student 陣列,存放 3 位學生的姓名與分數,並用迴圈印出所有資料。