450 likes | 608 Views
第 8 章 結構與其它自訂資料型態. 8-1 結構 8-2 其它自訂資料型態 8-3 本章綜合練習. 8-1 結構. 結構為一種使用者自訂資料型態,能將一種或多種資料型態集合在一起,形成新的資料型態。 考慮描述一位學生成績資料,這時除了要記錄學號與姓名等字串資料外,還必須定義數值資料型態來記錄如英文、國文、數學等成績,此時陣列就不適合使用。. 結構宣告與存取方式. 宣告方式如下: struct 結構型態名稱 { 資料型態 結構成員 1 ; 資料型態 結構成員 2 ; …… };
E N D
第8章 結構與其它自訂資料型態 8-1 結構 8-2 其它自訂資料型態 8-3 本章綜合練習
8-1 結構 • 結構為一種使用者自訂資料型態,能將一種或多種資料型態集合在一起,形成新的資料型態。 • 考慮描述一位學生成績資料,這時除了要記錄學號與姓名等字串資料外,還必須定義數值資料型態來記錄如英文、國文、數學等成績,此時陣列就不適合使用。
結構宣告與存取方式 • 宣告方式如下: • struct 結構型態名稱 • { • 資料型態 結構成員1; • 資料型態 結構成員2; • …… • }; • 在結構定義中可以使用C的基本資料型態、陣列、指標,甚至是其它結構成員。
Student結構型態 • 宣告與定義方式如下: • struct Student • { • char S_Num[10]; • char Name[20]; • int Chi_score; • int Math_score; • int Eng_score; • }; • Student John,;
結構變數的宣告與存取示範:CH08_1 • 程式範例是使用結構型態來定義Student結構,並示範如何宣告、存取結構成員與介紹結構變數間的指定運算過程。
結構指標 • 1.使用->符號指向結構指標的資料成員: • 結構指標->結構成員名稱; • 2.使用取值運算子「*」,再使用小數點「.」取得結構變數的資料成員。 • (*結構指標).結構成員名稱;
結構指標資料存取方法的示範與練習:CH08_2 • 程式範例設定一結構為圓,並分別宣告一個結構變數及結構指標,而此結構指標指向該變數。 • 接著利用結構變數計算出圓面積後,再分別用兩種結構指標方式將資料顯示在螢幕上。
結構指標與運算子的存取示範與練習:CH08_3 • 使用結構指標來進行結構成員運算時,必須特別注意運算子的優先順序,例如->運算子的運算順序優先於++與--運算子,例如f2->a++是等於 (f2->a)++。以下的程式範例正好說明這個結果。
結構成員宣告為指標變數的存取示範:CH08_4 • 程式範例,是宣告圓的結構體,並設定結構成員area為指標變數,用以記錄圓面積。 • 這說明如果結構中的成員宣告為指標變數,則在結構變數中會利用(.)存取該指標變數;而在結構指標中會以(->)存取指標變數。
結構陣列 • 陣列在程式設計中使用相當頻繁,主要是用來儲存相同資料型態成員的集合,而結構的功用則可以集合不同資料型態成員,不過那可是只有一筆結構資料,如果同時要記錄多筆相同結構資料,還是得宣告一個結構陣列型態。 • 宣告方式如下: • struct 結構名稱 結構陣列名稱[陣列長度 ];
五個元素的student結構陣列 • 陣列中每個元素都各自擁有字串name與整數score成員: • struct student • { • char name[10]; • int score; • }; • struct student class1[5];
結構陣列的宣告與存取練習:CH08_5 • 程式範例是基本的結構陣列的宣告與存取方式。不過請各位留意,第23行是個重要的觀念。 • 因為陣列名稱即為此陣列第一個元素的記憶體位址,所以陣列中的各個元素也可以使用指標常數運算的觀念來存取。
結構陣列中陣列成員的宣告與存取練習:CH08_6 • 程式範例宣告5個學生的結構陣列,其中每個學生的結構中又有成績的陣列成員,最後結果將列印與存取學生結構陣列的陣列成員元素。
結構指標陣列 • 結構陣列是以結構變數的方式呈現,當然也可以宣告成結構指標陣列方式,使得陣列中的每個元素,所存放的都是指標。 • 因為是結構指標陣列,所以不能使用*運算子或指標運算來存取結構內的資料成員。例如把第24行改為: • printf("姓名:%s \t", *s2[i].name); /* 這個陳述句不合法 */ • 或 • printf("姓名:%s \t", (s2+i)->name); /* 這個陳述句不合法 */
巢狀結構 • 謂巢狀結構就是在一個結構中宣告建立另一個結構。 • 就如同一個書包(外層結構)裡面還裝有數個資料夾(裡層結構)。如下圖所示:
巢狀結構的宣告 • 將裡層結構與外層結構分開宣告,其中裡層結構A宣告於一處,外層結構B則以結構A為資料型態宣告變數。 • 內層結構被包於外層結構之下,其中內層結構包在外層結構B之內,定義內層結構的成員時,也一併宣告變數,可省略內層結構的名稱定義。
巢狀結構grade • 這個結構中,省略了內層結構student 的名稱定義,而直接使用grade結構即可: • struct grade • { • struct • { • char *name; • int height; • int weight; • } std[10]; • char *teacher; • };
巢狀結構成員的宣告與存取練習:CH08_8 • 程式範例將以省略內層結構的名稱定義,而直接使用grade結構來定義巢狀結構,並示範其中巢狀結構的成員的宣告與存取練習。
鏈結串列的應用 • 巢狀結構的應用相當普遍廣泛,最典型的例子就是在資料結構科學上有關鏈結串列(Linked List)的應用。 • 所謂鏈結串列,就像火車車箱一般,所有節點串成一列,而且指標所指方向一樣。 • 資料欄及鏈結欄組成,如下圖所示:
student結構 • 是一個巢狀結構,而內層結構也是使用student進行宣告,但是宣告成指標變數next,表示它可以用來存放一個student結構的記憶體位址。如下所示: • struct student • { • char name[20]; /* 資料欄位 */ • int score; /* 資料欄位 */ • struct student *next; /*鏈結欄位 */ • } s1, s2; /* 宣告s1 與 s2 兩個節點 */
鏈結串列的建立與存取練習:CH08_9 • 程式範例是練習建立與存取3個學生節點的鏈結串列。 • 並利用結構指標ptr來作為串列的讀取旗標。
函數與結構 • 結構是一種使用者自訂資料型態,因此也可以在函數與函數之間傳遞結構變數。 • 結構資料型態並不是C的基本資料型態,因此要在函數中傳遞結構型態,必須在全域範圍內事先作宣告,其它函數才可以使用此結構型態來定義變數。
傳值呼叫 • 傳值呼叫會將整個結構變數複製到函數裡,結構的所有成員項目會一直存在函數中供直接使用。 • 但是當結構物件容量很大時,不僅佔用許多記憶體,也會降低程式執行的效率。
結構傳值呼叫函數的示範與練習:CH08_10 • 程式範例輸入一份書籍訂購,包含有書名、單價及數量。並利用傳值呼叫方式將結構變數傳遞到函數來計算訂購總額。
傳址呼叫 • 傳址呼叫所傳入的參數為結構變數的記憶體位址,並以「&」運算子將位址傳給函數,在函數內則透過結構指標來存取結構資料。 • 這樣的方式可解決傳值呼叫所造成的佔用記憶體與效率減低問題,不過如果在函數中更改了傳來的參數值,那麼主函數內結構變數的值也會同步更改。
結構傳址呼叫函數的示範與練習:CH08_11 • 利用傳址呼叫方式將結構變數傳遞到函數來計算訂購總額。 • 呼叫時,直接將結構變數位址傳入函數即可並將書名改為"本書已付款了!!"字樣。
其它自訂資料型態 • 自訂資料型態,其實可以看成是替指定資料型態來自訂名稱,接著在程式中,即可以此自訂名稱來定義所指定的資料型態變數。 • 在C中,除了struct可自定資料型態外,還包含列舉(enum)、聯合(union)與型態定義(typedef)三種方式。
型態定義指令 • 型態定義指令(typedef) 可用來重新定義資料型態,將原有的型態或結構利用typede指令以有意義的新名稱來取代,讓程式可讀性更高。 • 宣告語法如下: • typedef 原型態 新定義型態;
型態定義指令的宣告示範與練習:CH08_12 • 程式範例是說明型態定義指令(typedef)重新定義int 型態、字元陣列與hotel結構,當重新定義結構後,就不必加上struct保留字了。
列舉型態指令 • 列舉型態指令(enum)也是一種由使用者自行定義的資料型態,內容是由一組常數集合成的列舉成員,並給予各常數值不同的命名。 • 列舉型態指令的優點,在於把變數值限定在列舉成員的常數集合裡,並利用名稱方式來作指定,使得程式可讀性大為提高。
列舉型態指令(enum) • 定義與宣告方式如下: • enum 列舉型態名稱 • { • 列舉成員1, • 列舉成員2, • … • }; • enum列舉型態名稱 列舉型態變數;
列舉型態指令的宣告示範與練習:CH08_13 • 程式範例將宣告與定義Drink列舉型態,並定義變數c_drink及顯示變數c_drink值,請仔細觀察列舉成員常數值間的變化。
聯合型態指令 • 聯合型態指令(union) 與結構型態指令(struct),無論是在定義方法或成員存取上都十分相像,但結構型態指令所定義的每個成員擁有各自記憶體空間,不過聯合卻是共用記憶體空間。 • 如下圖所示:
聯合型態指令的宣告與成員記憶體空間分析:CH08_14聯合型態指令的宣告與成員記憶體空間分析:CH08_14 • 程式範例將宣告Data聯合型態,並說明聯合型態的成員變數都使用共同記憶體位址,並且當其中成員b的數值載入後,成員a的數值也會被修改。
結構傳址呼叫與型態定義指令的應用:CH08_15 • s陣列名稱本身必須以傳址方式傳遞,所以必須在引數上宣告指標變數,而sort函數則使用氣泡排序法依據成績來進行排序。
堆疊結構 • 堆疊結構是一種「先進後出」(First In, Last Out)的資料結構,例如自助餐中餐盤由桌面往上一個一個疊放,且取用時由最上面先拿,就是一種堆疊概念。
佇列結構 • 佇列是一種「先進先出」(First In, First Out)的資料結構,就好比搭捷運時買票的隊伍,先到的人當然可以優先買票,買完後就從前端離去準備搭捷運。
佇列資料的存入、取出與走訪實作:CH08_17 • 設計一程式使用malloc()函數來配置堆疊中新元素的記憶體空間,本題中元素仍為學生姓名及成績的結構資料。
多項式串列表示法 • 多項式的鏈結串列表示法主要是儲存非零項目,並且每一項節點均符合以下資料結構:
多項式的串列 • 認識了多項式串列表示法後,關於多項式的加法也相當簡單,只要逐一比較A、B串列節點指數,把握指數相同者,係數相加,否則直接照抄入新串列的原則即可。
多項式串列表示法的加法運算:CH08_18 • 設計一程式,利用多項式的鏈結串列表示法來實作上述兩多項式串列加法運算的原理。這個程式包含了許多C的進階語法,也希望各位能反覆研究,融會貫通。