速學結構與自訂資料型態
在C++程式設計中,我們往往需要同時處理多種型態不同的資料,以表示複雜的物件或事物。例如學生記錄中除了有學號(整數)、姓名(字串)外,還可能有成績(整數或浮點數)、性別(字元或列舉)與電話號碼(字串)等資料。這時,單純使用陣列或基本變數會使程式碼顯得零散、缺乏結構化;幸運的是,C++提供了可以自行定義的結構型態(struct)、列舉(enum)、聯合(union)與型態定義(typedef)等自訂資料型態工具。這些機制讓程式設計師可創造出更具彈性與可讀性的型態,使程式碼更容易理解、維護與擴展。
8-1 結構 (struct) 簡介
結構的概念:
結構(struct)是一種集合多種不同型態資料的複合資料型態。透過結構,程式設計師能將相關的資料彙整為一個整體,輕鬆地對整體物件進行操作,而不必分散管理每一個成員。換句話說,結構就是用來表示實際問題中複雜資料的一種手段,好比一本「資料表單」:每個成員表示不同的欄位欄位,而整個結構物件就是一筆完整的紀錄。
這種自訂型態特別適合表達較複雜的實體,如學生檔案(包含姓名、學號、成績)、公司員工資料(包含員工代號、名字、薪資、職稱)或一個3D點座標(包含x、y、z三個維度的值)。
8-1-1 宣告結構變數
結構定義語法:
定義結構並不會直接配置記憶體空間,而是告訴編譯器產生一種新的型態定義。要使用結構,必須宣告結構變數:
舉例:
若要同時定義結構並宣告變數,可將變數宣告放在結構定義的尾端,例如:
存取結構成員:
透過「點號」(dot operator)運算子來存取結構成員:
結構變數的指定運算也相當便利,可直接將一個結構變數指定給另一個相同型態的結構變數,而不必逐一指定成員:
結構陣列:
若要存放多筆相同型態的結構資料,可宣告結構陣列:
透過結構陣列,我們可輕鬆遍歷所有紀錄:
巢狀結構:
結構的成員不僅可以是基本型態或陣列,也可以是另一個結構,形成「巢狀結構」。透過巢狀結構,我們可描述更複雜的資料。例如:
每層結構多一層點號存取。例如:p.home.city可取得該人的所在城市名稱。
8-2 列舉 (enum)
列舉型態的概念:
列舉是一種能將一組相關常數定義為列舉成員的型態,透過具意義的名稱代替神祕的數值常數,使程式碼的可讀性與維護性提升。列舉成員預設從0開始遞增,但也可自行指定初始值。
列舉宣告語法:
範例:
透過列舉,我們能清楚地使用coffee、milk、tea、water這些名字,替代模糊不清的數字常數,大幅提升程式碼語意明確度。
8-3 聯合型態 (union)
聯合的概念:
聯合(union)和結構很像,都能集合多種不同型態的成員,但最大差異在於聯合的所有成員「共用同一塊記憶體區域」。也就是說,聯合變數會以成員中「所需空間最大者」來配置記憶體大小,其餘成員共用這塊空間。
這意味著在同一時間,只有一個成員能有意義的值,其餘成員若被存取則會出現不預期的結果。
聯合宣告語法:
範例:
由於i與c共用空間,因此若讀取d.c[0]、d.c[1]等,將會是該整數的位元組表示。
應用情境:
聯合常用於需在同一記憶體空間中存放不同型態資料的場景。例如程式中加解密或解析資料包,不同時間以不同格式詮釋該區域記憶體的內容。這樣可節省記憶體使用量,不過必須清楚了解聯合的限制。
8-4 型態定義 (typedef)
typedef的功能:
typedef指令可用來為現有資料型態(包括基本型態、結構、陣列等)重新定義一個更直覺或方便使用的名稱。透過typedef,我們可使程式碼更易讀、易管理,特別當原先型態名稱冗長或難記時。
結合struct與typedef:
若經常使用某個結構型態,可用typedef將struct省略:
常見錯誤與問題分析
-
結構定義後漏掉分號:
一定要在結構定義結束的
}後加上分號! -
結構型態重複定義相同名稱的結構:
在同一作用域(同一檔案內)定義同名結構會造成編譯錯誤,必須使用不同名稱或將其擺在不同namespace或檔案。 -
使用typedef後仍加上struct關鍵字:
修正後:
-
使用enum時不當使用:
在enum中成員名稱若有重複、或是將列舉值指定給不適合的變數型態,可能造成編譯錯誤或程式語意不清。確保每個列舉成員都具備清晰的語意。 -
聯合型態中成員共用記憶體造成混淆:
若你在union中已經透過某成員寫入資料後,又透過另一成員讀取,可能產生不可預期結果。請確保在同一時刻只針對其中一個成員有意義的存取。
課後評量與深入思考
-
指出以下程式碼的錯誤:
此處多餘的
struct關鍵字可移除。 -
若有一個enum Drink定義:
請問water的值為多少?
coffee=25, milk=20, tea=15, water未指定則延續最後一次指定值,tea為15,water自15加1=16。 -
解釋為何二元搜尋法(binary search)須先確保資料排序後才能使用?
雖然此為前章所述的演算法題材,但可引申思考:自訂型態(如struct)的成員若是鍵值,排序有助於後續以列舉或switch-case進行邏輯判斷或搜尋。
總結
在本章中,我們介紹了C++中4種自訂資料型態:結構(struct)、列舉(enum)、聯合(union)與型態定義(typedef)。透過這些工具,我們不僅可輕鬆表示複雜的實體或資料集,也能為原有資料型態重新命名,使程式碼更具可讀性與彈性。
- 結構能群組不同型態的資料成員,形成一個有意義的自訂型態。
- 列舉將常數命名化,使程式碼更清晰易讀。
- 聯合雖可共用記憶體空間,但使用時須格外謹慎,避免成員間衝突。
- typedef可為現有型態取更佳的名稱,提升程式碼易讀度。
掌握這些自訂資料型態,不僅是在C++程式設計中必備的基礎,更是在面對複雜問題時的重要工具,使我們能夠在日後更進階的程式設計任務中靈活運用、優雅解決問題。
請先 登入 以發表留言。