Presentation is loading. Please wait.

Presentation is loading. Please wait.

第十章 結構(structure)、聯集(union)

Similar presentations


Presentation on theme: "第十章 結構(structure)、聯集(union)"— Presentation transcript:

1 第十章 結構(structure)、聯集(union)

2 10-1 結構(struct)的基本語法 結構宣告與初值設定 結構的輸出 結構的輸入   10-2 結構陣列   10-3 巢狀結構   10-4 結構與指標   10-5 結構資料的函數呼叫   10-6 聯集 (union)   10-7 程式觀摩

3 10-1 結構(struct)的基本語法 結構是一堆相關資料項的集合,與陣列不同的是結構的成員可以是不相同的資料型態,而陣列元素必須是相同的資料型態。 例如一個公司的員工,通常會建立一些基本資料,例如姓名、職稱、年齡、電話、住址等,這些基本資料的性質並不同,因為姓名通常是文字資料,而年齡則是數值資料,不相同的資料型態就可以結構來定義。

4 10-1-1 結構宣告與初值設定 結構的定義格式如下: struct 標籤名稱 { 成員宣告1; 成員宣告2; 成員宣告3; . }
結構宣告與初值設定 結構的定義格式如下: struct 標籤名稱 { 成員宣告1; 成員宣告2; 成員宣告3; }  每個成員宣告都包括資料型態與成員名稱,用分號結束。

5 例如定義一個結構 STUDENT 表示學生資料,包括學號、姓名、年齡,如下:
struct STUDENT { long id ; char name[9] ; int age ; } 其中 STUDENT 是標籤名稱,id 是學號,為長整數型態,name 是姓名,為 9 個元素的字元陣列,age 是年齡,為整數型態,標籤名稱用大寫是為了和一般變數名稱有所區別,這是好的程式習慣。若用資料處理的說法,STUDENT 是一個紀錄,包括學號、姓名、年齡三個欄位。

6   定義了結構之後,我們就可以宣告結構變數:
  struct STUDENT x;   記憶體就配置了 x 變數,包括 3 個成員:   x.id 是 x 的學號 x.name 是 x 的姓名 x.age 是 x 的年齡   這個‧點運算就是取得結構的某項成員。

7 我們可以設定 x 的初值:   struct STUDENT x = {844001,"Sam",18};   用大括弧將結構成員值逐一依序填入。

8 結構變數的大小就是所有結構成員大小的總和。
所以 x.id 是長整數 佔 4 byte x.name 是字元陣列 佔 9 byte x.age 是整數 佔 2 byte x總共佔用4+9+2=15 個位元組的記憶体。

9 在定義結構時,也可以順便宣告變數:  struct STUDENT { long id; char name[9]; int age; } p1,p2; 他們的成員分別是   p1.id p1.name p1.age p2.id p2.name p2.age

10 甚至也可以連初值一起設定   struct STUDENT { long id; char name[9]; int age; } p1={ , "Peter",18}, p2={ , "mary",17}; 注意! 結構定義只是定義結構的"樣子",而宣告結構變數才會真正安排記憶体空間來存取結構的資料。

11 如果要把某個結構變數的內容,存入另一個結構變數,可以將成員一一拷貝。
例如,定義結構 POINT 表示二維座標點   struct POINT { int x ; int y ; } p1={ 100,100 };   struct POINT k;   我們可以把 p1 拷貝給 k:  k.x = p1.x; k.y = p1.y; 或是 k=p1; 拷貝整個結構

12 【語法練習 10-1-1】 (1) 定義一個結構 NUM 包括兩個成員:整數 i 與長整數 l
struct NUM { int i; long l; }; (2) 宣告變數 kk 為 NUM 結構型態 struct NUM kk; (3) 宣告變數 pp 為 NUM 結構型態,並設初值為 100 與 50000L struct NUM pp = { 100, 50000L }; (4) 將 pp 拷貝給 kk kk = pp;

13 結構的輸出

14 【範例 】 定義一個結構 STUDENT 包括學號、姓名、年齡三項成員,宣告結構變數並設定初值後,將成員內容輸出到螢幕上。

15 4 struct STUDENT { 5 long id; 6 char name[9]; 7 int age; 8 }; 9 struct STUDENT x= { , "Superman", 100 }; 10 11 main() 12 { printf("id : %ld\n",x.id); printf("name : %s\n",x.name); printf("age : %d\n",x.age); 16 }

16 10-1-3 結構的輸入 對一個結構而言,用點運算取得的成員,就好像是一個普通的變數,所以成員資料的輸入,就和一般的變數輸入相同。
結構的輸入 對一個結構而言,用點運算取得的成員,就好像是一個普通的變數,所以成員資料的輸入,就和一般的變數輸入相同。 例如,定義一個日期的結構   struct DATE { int day; int month; int year; };

17   宣告變數 birth 及 death:   struct DATE birth,death; 由鍵盤輸入 birth 的成員資料就可用下列寫法: scanf("%d",&birth.day); scanf("%d:,&birth.month); scanf("%d",&birth.year); 分別輸入日、月、年的資料

18 【語法練習 10-1-2】 (1) 定義一個結構 T 包括兩個成員:整數 i 與字元 c
struct T { int i; char c;}; (2) 宣告變數 kk 為 T 結構型態 struct T kk; (3) 輸入 kk 的 i 成員 scanf("%d", &kk.i); (4) 輸出 kk 的 i 成員 printf("%d", kk.i); (5) 輸入 kk 的 c 成員 kk.c = getchar(); scanf("%c", &kk.c); (6) 輸出 kk 的 c 成員 putchar( kk.c ); printf("%c", kk.c);

19 【語法練習 10-1-3】 (1) 定義一個結構 MAN 包括兩個成員:整數 age 與 12 個元素的字元陣列 name
struct MAN { int age; char name[12]; }; (2) 宣告變數 p 為 MAN 結構型態 struct MAN p; (3) 輸入 p 的 age 成員 scanf("%d",&p.age); (4) 輸出 p 的 age 成員 printf("%d", p.age); (5) 輸入 p 的 name 成員 scanf("%s", p.name ); (6) 輸出 p 的 name 成員 printf("%s", p.name);

20 10-2 結構陣列 結構陣列是結構最常應用的方式許多資料記錄的檔案,以及一般日常生活的文書表格,都是用結構陣列的方式來操作。一個陣列的每一個元素都是結構,就是結構陣列。 例如一個 5 項產品的統計表:

21 就可以看成是一個結構陣列,先定義每一個項目為一個結構:
struct PRODUCT { int no ; char name[10]; int quanity; float price; }; 再宣告整個表格為結構陣列,預留 5 個元素   struct PRODUCT table[5];

22 第 0 個元素的產品編號是 table[0].id 品名是 table[0].name 數量是 table[0].quanity 價格是 table[0].price 同理,第i個產品的編號是 table[i].id 品名是 table[i].name 數量是 table[i].quanity 價格是 table[i].price

23 如果我們要寫程式統計 50 位學生的國文、英文、數學三科成績,可以定義一個 SCORE 結構。
struct SCORE { char name[9]; int chinese; int english; int math; };

24 宣告結構陣列儲存 50 筆學生成績 struct SCORE s[50]; 如此,第i個學生的姓名是 s[i].name 國文成績是 s[i].chinese 英文成績是 s[i].english 數學成績是 s[i].math

25 對於事先建立的表格資料,我們通常以結構陣列設定初值的方式來建立。例如會員的名單資料
struct MEMBER { char name[p]; int id; char phone[8]; } people[4]={ {"wang",4012," "}, {"kou",3895," "}, {"chang",1234," "}, {"chen",9914," "} };   建立了4個會員資料,請注意每個資料用大括弧框起來,資料用逗號隔開,最後一筆不加逗號

26 10-3 巢狀結構 一個結構的成員是另一個結構,就是所謂的巢狀結構。這個結構成員必須先定義,才能用來定義新的結構。

27 例如先定義 DATE 結構表示日期,由年、月、日組成。
  struct DATE { int day; int month; int yeaar; };   再定義學生的結構,包括學號、姓名、生日三項成員。   struct STU { long id ; char name[9]; struct DATE birthday;

28 我們可以宣告 x 為 STU 結構的變數   struct STU x;   則學生 x 的學號是 x.id 姓名是 x.name 出生年是 x.birthday.year 出生月是 x.birthday.month 出生日是 x.birthday.day  關於初值的設定,也可直接用大括弧框起來,如   struct STU y={794001,"HongShan",{11,26,1980}};

29 更複雜一點的巢狀結構陣列,例如   struct STU people[50];  宣告50個學生的資料,而第i個結構資料是 people[i] 其結構成員 people[i].id 為第i個學生的學號 people[i].name 為第一個學生的姓名 people[i].birthday 為第一個學生的出生日期,是一個結構變數  所以, 其出生年是 people[i].birthday.year 出生月是 people[i].birthday.month 出生日是 people[i].birthday.day  至於第i個學生姓名的第一個字母就是 people[i].name[0]

30 10-4 結構與指標 如果一個指標指向一個結構變數,我們就稱它為結構指標。

31 例如宣告 x 為學生結構 STU 的變數,而 ptr 為一指向 STU 結構資料的指標:
struct STU { char name[9]; int score; }: struct STU x,*ptr; 如果將 ptr 指向 x 結構變數 ptr=&x; 那麼就可以用 ptr 指標來存取 x 的各項成員資料

32 結構指標所指向的結構資料成員,有兩種不同的表示法:
  (1) x.score 是學生的成績,因為 ptr 指向 x,所以 (*ptr).score 也是代表 x 的成績 (2) ptr->score 也是代表 x 的成績  注意! 因為‧點運算比 * 間接運算優先,所以 (*ptr).score 的小括弧不可省略。 (*ptr).score 與 *ptr.score 意義是不相同的。(*ptr).score 表示 ptr 是一"指標"指向一結構,該結構有 score 成員;*ptr.score 表示 ptr 是一個"結構",此結構有一成員 score 為指標,請務必小心。

33 struct MESSAGE { char *str ; int length ; }; struct MESSAGE x={"Compile",7} ; 則 x.length 的內容是7,而 x.str 是字串"Compile",*x.str 是字元'c'

34 結構陣列 struct MESSAGE command[]={{"Edit",4},
{"Compile",7}, {"Link",4}, {"Run",3} };   則第i個命令字串是 command[i].str 其第一個字母是 *(command[i].str) 其長度是 command[i].length 若有結構指標 ptr 指向 x:   struct MESSAGE *ptr=&x;   則所指字串長度為 ptr->length 或 (*ptr).length 字串內容為 ptr->str 或 (*ptr).str 字串的第一個字母是 *(ptr->str) 或 *((*ptr).str)

35 【遞迴式定義】 有一種結構指標的定義非常特殊,稱為遞迴式定義(recursive definition),多用於動態的資料結構。 例如:
struct NODE { int num; struct NODE *next; }; struct NODE x,*p; 定義一個 NODE 結構,包括兩個成員,一個是整數資料 num,另一個是指向 NODE 結構的指標 next,這種 NODE 結構稱為"節點"。

36 如果將 p 指向 x: p=&x; 則 x.num 是 x 的整數資料成員 x.next 是指向下一個節點的指標 而 p->num 相當於 x.num p->next 相當於 x.next 而 p->next->num 就是 x 下一個節點的整數資料成員。

37 10-5 結構資料的函數呼叫 當我們想要把結構型態的資料傳入函數時,通常可以有下列幾種做法: 1. 傳遞整個結構變數的內容
10-5 結構資料的函數呼叫 當我們想要把結構型態的資料傳入函數時,通常可以有下列幾種做法: 1. 傳遞整個結構變數的內容 2. 傳遞整個結構變數的位址 3. 逐一傳遞結構的各項成員 4. 逐一傳遞結構各項成員的位址

38 其中的第3種與第4種方法,必須將結構變數的所有成員,逐一代入函數的引數,實在很麻煩,所以通常不予採用。
第1種做法直接將整個結構變數的值,拷貝一份給函數內的型式引數,如此結構變數的值就不會被函數所更動,缺點是拷貝整個結構佔用較多的記憶體(堆疊)空間。 第2種做法是較常使用的,只須傳遞結構變數的指標,減少引數佔用的空間,但是函數內須用間接運算來存取結構的成員。

39 【範例 10-5-1】傳遞整個結構變數的內容 5 struct EMPLOYEE { 6 int id; 7 char name[9];
long salary; 9 };

40 11 main() 12 { void print_emp(struct EMPLOYEE); struct EMPLOYEE x; 15 x.id = 18; strcpy(x.name,"Crick"); x.salary = L; 19 print_emp( x ); 21 }

41 22 void print_emp (struct EMPLOYEE m)
23 { printf("id : %d\n",m.id); printf("name : %s\n",m.name); printf("salary : %ld\n",m.salary); 27 }

42 【範例 10-5-2】 傳遞結構變數的指標給函數 3 #include <string.h> 4
5 struct EMPLOYEE { int id; char name[9]; long salary; 9 };

43 11 main() 12 { void print_emp (struct EMPLOYEE *); struct EMPLOYEE x; 15 x.id = 18; strcpy(x.name,"Crick"); x.salary = L; 19 print_emp( &x ); 21 }

44 22 void print_emp (struct EMPLOYEE *m)
23 { printf("id : %d\n",m->id); printf("name : %s\n",m->name); printf("salary : %ld\n",m->salary); 27 }

45 10-6 聯集 (union) 結構和聯集最大的差異是,結構的成員每個都佔有自己的記憶體,而聯集的成員全部共用一塊記憶體位置。
我們可以說,聯集型態的資料是在不同時間,取得不同名稱的成員資料,這些成員佔用相同的記憶體位置。所需記憶體的大小,就是所有成員中佔用記憶體空間最大的。 例如,同一筆資料有時當成一個整數來用,有時當成兩個字元來用,就可以用 union 來宣告。 使用 union 的目的是為了節省記憶體的使用,更重要的目的是相同的資料有不同的用法。最常應用在系統呼叫的引數,或是與硬體相關的暫存器等。

46 union 的定義格式如下: union 標籤名稱 { 成員宣告1; 成員宣告2; 成員宣告3; } 每個成員宣告都包括資料型態與成員名稱,用分號結束。

47 union common { char ch; int i; long l; float f; }; 這4個成員 ch,i,l,f 分別是 char,int,long,float 的型態,但是佔用相同的記憶體位置。其中 char 佔1個 byte,int 須用2個 bytes,long 佔4個 bytes,float 則須用4個 bytes,取最大值可知共用的記憶體為4個 bytes。

48 【範例 10-6-1】union 型態的基本用法 6 union UDATA { 7 int i; 8 char c; 9 } data;
data.c = 'A'; printf("%d\n",data.i); data.i = 66; printf("%c\n",data.c); data.i = 258; printf("%02X",data.c); 【範例 】union 型態的基本用法

49 union TWOBYTE { unsigned int x ; struct BYTE { unsigned char hi ; unsigned cahr lo ; } h ; } code ; 定義整數 x 與結構 h 共用記憶體,而 h 又包括 hi 與 lo 兩個成員。宣告 code 是這種 union 型態的變數,那麼 code.x 是把 code 當成整數 code.h.hi 是取 code 的 high byte code.h.lo 是取 code 的 low byte

50


Download ppt "第十章 結構(structure)、聯集(union)"

Similar presentations


Ads by Google