<span class="bsf-rt-reading-time"><span class="bsf-rt-display-label" prefix="閱讀時間:"></span> <span class="bsf-rt-display-time" reading_time="6"></span> <span class="bsf-rt-display-postfix" postfix="mins"></span></span><!-- .bsf-rt-reading-time -->【C語言】結構 (Struct) 是什麼?7段程式碼帶你搞懂

【C語言】結構 (Struct) 是什麼?7段程式碼帶你搞懂

暨上篇介紹完 陣列 (Array) 之後,不知道大家有沒有更熟悉陣列的概念了呢!

相信大家一定曾經遇到過這樣的問題,就是當要宣告一個變數的時候,突然發現那個變數需要有好多的屬性,但是每一種屬性的資料型別 (Data Type) 可能都不一樣,有int、char…,那這個時候我們該怎麼辦?

別擔心,接下來, Hani 就是要帶大家來瞭解一下C語言當中非常實用的自訂型別方法 — 結構 (Struct)

準備好了嗎? 那就讓我們開始吧!

結構 (Struct) 的概念?

還記得嗎?我們上次說到

陣列是一個用來儲存『相同資料型態』元素的集合。

而結構的主要用途是

將各種不同資料型態的變數集合起來,變成一個新的資料型態

什麼意思?還是有點霧煞煞的對吧,來看看下面這段程式碼!

struct employee {
     char name[10];
     int age;
     float salary;
     char phone_number[10];
};

說明:上面這段程式碼中,我們利用C語言中的關鍵字 struct 來宣告了一個名為 employee 的結構,當中包含了4個不同的屬性,分別是

  • name (字元陣列)
  • age (整數變數)
  • salary (單精度浮點數變數)
  • phone_number (字元陣列)

這樣我們就成功定義出了一個新的資料型態 — 『employee』

如何宣告結構變數?

Name_Of_Structure Name_Of_Variable;

Name_Of_Structure : 這邊就是我們剛剛利用 struct 定義出來的自訂型態。

Name_Of_Variable : 想取的名稱。

下面這段程式碼就是實際的宣告方式!

struct employee Dennis, Paige;

又或是還有另外一種宣告方式,將變數直接宣告在 struct 之後

struct employee {
     char name[10];
     int age;
     float salary;
     char phone_number[10];
} Dennis, Paige;

結構變數要初始化嗎?該怎麼做?

記得,一定要養成初始化的好習慣!

那初始化該怎麼做呢?方法有三種:

方法1:宣告結構變數時,直接將值assign進去

struct employee Dennis = {
     "Dennis",
     24,
     78000,
     "0923473923"
};

***一定要記得用逗號將各個屬性隔開哦!***

方法2:直接用屬性的名稱來指定,這樣就可以不用按照結構宣告時的順序

struct employee Dennis = {
     .phone_number = "0923473923",
     .name = "Dennis",
     .age = 24,
     .salary = 78000
};

方法3:在自定義結構的時候,同時宣告結構變數並初始化

struct employee {
     char name[10];
     int age;
     float salary;
     char phone_number[10];
} Dennis = {"Dennis", 24, 78000, "0923473923"};

*** 記得!結尾一定要加上分號! ***

如何存取 (access) 和指定 (assign) 結構當中的值?

利用 .(點)來存取和指定結構內的值。

什麼意思呢?下面讓我們來指定值到 Dennis 這個結構變數!

strcpy(Dennis.name,"Dennis");
Dennis.age = 24;
Dennis.salary = 78000;
strcpy(Dennis.phone_number,"0923473923");

p.s. 不要真的打電話過來喔~我是不會接的!

陣列可以用來儲存結構嗎?

當然可以!

相信大家還沒有忘記陣列的定義吧~忘記的話記得來這裡複習一下!

對於陣列來說,只要儲存的是同一個資料型別的變數,那就沒有問題,而結構正是我們自定義的一個新的資料型別,所以利用這個結構宣告的陣列中儲存的就是這個結構型別的變數。

不知道大家看到這裡是不是已經知道怎麼宣告結構陣列了呢?

struct employee part_time[20], full_time[20];

上面這段程式碼,我們宣告了兩個結構陣列,分別是 part_time 和 full_time 的 employee,陣列長度都是 20。

結構可以作為函數 (function) 的參數傳遞嗎?

當然也可以!

利用結構宣告的變數,也是一個變數,所以也是可以直接拿來當作函式的參數傳遞出去的。

舉例來說:

#include <stdio.h>

struct employee {
     char name[10];
     int age;
     float salary;
     char phone_number[10];
};

void transfer_employee(employee trans_employee) {
     trans_employee.salary = 82000;
     printf("%f\n",transfer_employee.salary)
}

int main() {
     struct employee Dennis = {
          "Dennis",
          24,
          78000,
          "0923473923"
     };
     transfer_employee(Dennis);
     printf("%f\n",Dennis.salary);
     return 0;
}

上面這段程式碼中,我們將 Dennis 當作 transfer_employee 這個 function 的參數傳過去,然後修改了其中的 salary 屬性,接下來考考大家,執行結果會是怎麼樣呢!

答案揭曉:

82000
78000

因為在傳送 Dennis 這個參數的時候,OS 會額外複製一個 Dennis 傳送過去,因此我們在 transfer_employee 中修改到的是全新的 Dennis,而在 main function 中的才是原來的 Dennis,所以有兩個不一樣的 Dennis,這樣懂了嗎!

p.s 這樣的傳送方式稱為 call by value

結構當中可以再放進結構嗎?

也是可以的!

有些時候某些屬性本身也是一個結構,而這樣的情況就必須在結構中再嵌入結構。

來看看這段程式碼!

struct date {
     int month;
     int day;
     int year;
};

struct human {
     char name[10];
     int age;
     struct date birthDate;
};

由於日期本身還會額外包含年份、月份,所以上面的 birthDate 變數就會是用 date 這個結構來宣告。

補充 – typedef 用法

看到這裡,不知道大家有沒有發現,我們上面定義完結構之後要宣告結構變數時,前面都還是要加上 struct 關鍵字來宣告,非常麻煩,那麼有沒有什麼方法呢?

利用 typedef 來定義別名

來看看這個例子!

typedef struct employee Emp;
struct employee {
     char name[10];
     int age;
     float salary;
     char phone_number[10];
};

經過 typedef 的宣告之後,我們就幫 struct employee 創造了一個新的別名 – Emp

所以接下來我們要宣告的時候就可以不用再寫 strcut employee 啦!

Emp Dennis = {
     "Dennis",
     24,
     78000,
     "0923473923"
};

總結

以上就是7段關於結構 (Struct) 的程式碼:

  • 結構 (Struct) 的概念?
  • 如何宣告結構變數?
  • 結構變數要初始化嗎?該怎麼做?
  • 如何存取 (access) 和指定 (assign) 結構當中的值?
  • 陣列可以用來儲存結構嗎?
  • 結構可以作為函數 (function) 的參數傳遞嗎?
  • 結構當中可以再放進結構嗎?
  • 補充 – typedef 用法

希望看完之後,大家就可以開始活用 Struct 來寫程式了!

對文章有任何問題的話,都非常歡迎下面留言讓我知道哦!

By Hani

This Post Has 34 Comments

  1. Mila

    用很有趣的方式介紹,整理的蠻好的,然後電話那邊有點逗哈哈哈

    1. Han I

      哈哈哈,希望對妳有幫助!

  2. Huan Hsuan, Chen

    感謝分享~雖然對初學者的我還很難
    但我會繼續努力

    1. Han I

      慢慢來,付出的努力一定不會白費!

  3. Chenglin

    解釋得很容易理解,非常感謝這麼用心的介紹,傳址傳值剛開始很容易弄錯

    1. Han I

      之後會寫一篇文章專門介紹call by reference跟call by value,謝謝你的回饋!

  4. Wei

    這對初學者的我來說還有點難理解
    但是版主整理的非常平易近人!
    先收藏起來,等我更熟悉時再回來看一次!!
    謝謝版主細心分享。

    1. Han I

      不客氣!
      歡迎隨時回來看看!

  5. chingminlin

    文章看下來覺得很輕鬆好懂,對初學者的我來說,開始有一點點可以理解,謝謝分享!

    1. Han I

      有空可以再多回來看看喔!

  6. 美好世界

    版主介紹的很詳細很容易理解
    對於初學者的我來說有很大的幫助
    謝謝版主分享

    1. Han I

      不客氣,可以幫我分享給需要的人哦!

  7. Tim Hsiao

    好久沒碰程式語言了,看完版主教學,馬上就想起來80%了,謝謝版大

    1. Han I

      水!這樣就對了啦!!!

  8. Kita

    謝謝站長分享的教學文,好容易理解哦
    簡短的重點提醒,對我這種有閱讀障礙的人來說,真是太棒了!

    1. Han I

      簡短的重點才記得起來啊~記憶體是非常重要的,一定要省著點用!

  9. Pei-ni

    整理得很清楚!另外也推薦版主可以看看目錄的這項外掛https://www.johntool.com/wordpress-table-of-contents/
    就會自動幫你整理好在最前面了!

    1. Han I

      是阿璋的文章耶!哈哈哈,沒問題,我馬上去看看!

  10. Colin

    感謝版主詳細的整理分享,直接記重點~

    1. Han I

      讚!忘記隨時可以回來看看喔!

  11. 小葉

    對於初學程式語言的人來說,介紹的真的是非常平易近人,馬上手刀加到我的最愛,期待版主更多的教學文章

    1. Han I

      謝謝啦~我會繼續努力讓大家可以輕鬆入門這些概念!

  12. 蔡明軒

    講解的好仔細!雖然我對這方面沒研究,但剛好身邊朋友有在研究,會幫版主分享!感謝版主分享~

  13. satomi

    感謝分享~對初學者的我來說太難,還是交給專業的人來吧

    1. Han I

      ok的!如果身邊有需要的人也可以分享給他們看看哦!

  14. carol

    步驟講的很仔細呢
    自己也是學程式的苦手
    之前學到有點想放棄XD
    謝謝版主的解說~

    1. Han I

      每個領域都有每個領域的難關,加油!

  15. sammy

    好專業的文章XD 本來對這方面完全是零,看完好像覺得有0.1!哈哈謝謝分享

  16. Doyle Lam

    常常覺得程式碼是很複雜的事情,不過看完您的文章又感覺並非那麼複雜,大概關鍵在於沒有人指點吧~

    1. Han I

      這也是其中一環,但是概念真的不複雜,只是看起來讓人害怕而已,所以我致力於把概念講解的簡單,希望能讓大家都更容易理解程式!

Leave a Reply