Semorphe

結構

把幾個值綁成一個東西。 · ⏱ 約 30 分鐘

你會學到三件事

  1. struct 把幾個變數包成一個
  2. C 宣告時一定要寫 struct 這個字
  3. . 和 -> 的差別,以及為什麼有兩個

開始之前

一個點有 x 和 y。用兩個變數的話,它們只是碰巧放在一起—— 函式要傳兩個、陣列要開兩個、改一個忘了另一個。

struct 讓它們變成一個東西。

🟢 先把編輯器打開,跟著下面一起做:跟著做

一、定義一個型別

把幾個值綁成一個型別:

1struct Point {2    int x;3    int y;4};
宣告int(整數)變數y宣告int(整數)變數x定義結構Point134

⚠️ 最後那個分號不能少。 這是 C 少數幾個「大括號後面要分號」的地方, 而漏掉它的錯誤訊息通常指向下一行——很難查。

這一段不會產生任何變數。它在說「以後有一種東西叫 Point,長這樣」。

二、🔴 用的時候要寫 struct

積木盤上這一顆寫著「定義結構 …」; 而底下設定欄位的那幾行是「把 … 設成 …」(第 5 課用過)。

C 裡用它的時候,前面那個 struct 不能省:

1struct Point p;
宣告struct Point變數p1

⚠️ C 一定要寫那個 struct,而 C++ 可以省略成 Point p;。

這是 C 和 C++ 一個很表面、而每天都會遇到的差別。

(老程式碼常見 typedef struct { ... } Point; 就是為了省掉它。)

三、. 取成員

拿裡面的值用一個點:

1p.x = 3;2p.y = 4;3printf("%d %d\n", p.x, p.y);
變數p結構的欄位x3變數p結構的欄位y4變數p結構的欄位x變數p結構的欄位y格式化輸出 (printf)%d %d\n,,把設成把設成使用命名空間std引入函式庫cstdio(C++ 標準輸入輸出)123

和 C++ 完全一樣。

四、-> 是「透過指標取成員」

手上是指標的時候,用箭頭:

1struct Point *q = &p;2printf("%d\n", q->x);
變數p取得的位址 (&)變數q指標的欄位x(->)格式化輸出 (printf)%d\n,建立struct Point指標變數q初始值(*)使用命名空間std引入函式庫cstdio(C++ 標準輸入輸出)12

q 是一個指標,所以不能直接 q.x——要先去那個地址。

(*q).x        // 先去 q 指的地方,再取 x
q->x          // 一模一樣,只是好寫好讀

⚠️ -> 就是 (*). 的縮寫,沒有別的意思。

判準很簡單:

左邊是什麼 用哪個
一個結構 .
一個指向結構的指標 ->

⚠️ 用錯的話編譯器會攔你,所以這個錯不可怕——它只是煩。

五、為什麼結構常常用指標傳

傳指標就不會複製一整份:

1void move(struct Point *p) {2    p->x = p->x + 1;3}
變數p指標的欄位x(->)變數p指標的欄位x(->)1+把設成定義函式 回傳型別void(無回傳)move(參數int*p)12

兩個理由:

  1. 要改到本體(第 3 課那件事)
  2. 不用複製一整個結構——結構大的時候,傳值等於整份拷貝

所以 C 的慣例是:結構參數幾乎都傳指標。

完成的樣子

這一課的參考做法——程式碼每一行的號碼,就印在對應的那塊積木上。

1#include <cstdio>2using namespace std;3struct Point {4    int x;5    int y;6};7 8int main() {9    struct Point p;10    p.x = 3;11    p.y = 4;12    printf("%d %d\n", p.x, p.y);13    struct Point *q = &p;14    printf("%d\n", q->x);15    return 0;16}
宣告int(整數)變數y宣告int(整數)變數x變數p結構的欄位x3變數p結構的欄位y4變數p結構的欄位x變數p結構的欄位y變數p取得的位址 (&)變數q指標的欄位x(->)0回傳格式化輸出 (printf)%d\n,建立struct Point指標變數q初始值(*)格式化輸出 (printf)%d %d\n,,把設成把設成宣告struct Point變數p定義函式 回傳型別int(整數)main定義結構Point使用命名空間std引入函式庫cstdio(C++ 標準輸入輸出)123849101112131415

換你了

加一個 struct Point 的陣列(三個點),用迴圈填值再印出來。

再進階:寫一個函式算兩點的距離——參數用指標傳。

到編輯器做這一題:練習:三個點的陣列,用迴圈填值再印出來

做一個

struct Student 裡有 math 和 eng。開一個三人的陣列,填上分數, 找出總分最高的那個人,印出他的編號和平均。

資料用這三筆:80 90、95 95、60 100。 🔴 沒有 struct 的話,這一題要開兩個平行陣列 math[3] 和 eng[3]—— 而那兩個陣列沒有任何東西保證它們的第 i 格講的是同一個人。

到編輯器做這一題:做一個:總分最高的那一個

這一課你做了什麼

如果卡住了

你看到 多半是因為
錯誤訊息指著結構定義的下一行 定義結尾的分號漏了
Point p; 說找不到型別 C 要寫 struct Point p;
q.x 編譯錯誤 q 是指標,要用 q->x
函式裡改了值外面沒變 參數傳的是複本。要傳指標
在編輯器打開這一課 →