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

Slides:



Advertisements
Similar presentations
第一單元 建立java 程式.
Advertisements

电子成绩单项目实现.
第九章 系 统 安 全 性 9.1 结构体 9.2 结构体型数组  9.3 结构体型指针 9.4 内存的动态分配 9.5 共用体
結構(struct).
第十一章 結構.
C程序设计 第9章 自定义数据类型 主讲教师: 鲁 萍 西安建筑科技大学 理学院.
程式設計 博碩文化出版發行.
C 程式設計— 結構 台大資訊工程學系 資訊系統訓練班.
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
2 C++ 程式概論 2.1 C++ 程式結構 程式註解 // 插入標題檔 #include 2-3
列舉(enum).
【變數與記憶體位址】 變數(Variable)提供一個有名稱的記憶體儲存空間。一個變數包含資料型態、變數本身的值及它的位址值。
第八章 利用SELECT查詢資料.
String C語言-字串.
结构体和共用体 2 梁春燕 华电信息管理教研室.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
101北一女中 資訊選手培訓營 妳不可不了解的指標 Nan.
STRUCTURE 授課:ANT 日期:2010/5/12.
STRUCTURE 授課:ANT 日期:2011/4/25.
C++语言程序设计 C++语言程序设计 第四章 数组及自定义数据类型 C++语言程序设计.
第九章 结构体和共用体 结构体的定义 结构体的使用 共用体的定义 共用体的使用 主讲:李祥 时间:2015年10月.
C語言簡介 日期 : 2018/12/2.
類別(class) 類別class與物件object.
SQL Stored Procedure SQL 預存程序.
C语言程序设计 李祥.
C 程式設計— 結構 台大資訊工程學系 資訊系統訓練班.
(Circular Linked Lists)
第五章 指针 5.1 指针的概念和定义 5.2 指针运算 5.3 指针和数组 5.4 字符串指针 5.5 指针数组 5.6 指向指针的指针
第3章 指標與字串 (Pointers and Strings)
Java 程式設計 講師:FrankLin.
JAVA 程式設計與資料結構 第四章 陣列、字串與數學物件.
Chap3 Linked List 鏈結串列.
第13章 结构体的应用 13.1 了解由用户构造的数据类型 13.2 结构体类型说明及结构体变量 13.3 结构体数组
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
|12 結構與列舉型態.
程式設計實習課(四) ----C 函數運用----
第一單元 建立java 程式.
陣列(Array).
第三章 資料型態與輸出控制 本章學習目標 認識Matlab的基本資料型態 練習資料型態的轉換 學習如何控制Matlab的輸出格式
第十章 用户自定义数据类型 目录 学生信息管理系统的开发 结构体数据类型的概述 结构体变量的使用 结构体数组
OOP6 結構Struct 黃兆武.
第十章 结构体与链表 西安工程大学.
輸入&輸出 函數 P20~P21.
第十章 指標.
挑戰C++程式語言 ──第8章 進一步談字元與字串
認識常數與變數 學習C++所提供的各種基本資料型態 瞭解溢位的發生 學習認識資料型態之間的轉換
Class & Object 靜宜大學資工系 蔡奇偉副教授 ©2011.
C qsort.
第二章 类型、对象、运算符和表达式.
挑戰C++程式語言 ──第7章 輸入與輸出.
第14章 結構與其他資料形式.
陣列與結構.
指標、串列 (Linked List).
北一女中 資訊選手培訓營 妳不可不了解的指標 Nan.
1757: Secret Chamber at Mount Rushmore
資料表示方法 資料儲存單位.
第四章 陣列、指標與參考 4-1 物件陣列 4-2 使用物件指標 4-3 this指標 4-4 new 與 delete
Programming & Language Telling the computer what to do
ABAP Basic Concept (2) 運算子 控制式與迴圈 Subroutines Event Block
Array(陣列) Anny
SQLite資料庫 靜宜大學資管系 楊子青.
Chapter 4 Multi-Threads (多執行緒).
C語言程式設計 老師:謝孟諺 助教:楊斯竣.
台大資訊工程學系 資訊系統訓練班 第119期 吳晉賢
安排座位.
C 程式設計— 結構 台大資訊工程學系 資訊系統訓練班.
方法(Method) 函數.
ABAP Basic Concept (2) 運算子 控制式與迴圈 Subroutines Event Block
InputStreamReader Console Scanner
Presentation transcript:

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

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

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

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

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

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

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

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

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

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

如果要把某個結構變數的內容,存入另一個結構變數,可以將成員一一拷貝。 例如,定義結構 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; 拷貝整個結構

【語法練習 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;

10-1-2 結構的輸出

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

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

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

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

【語法練習 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);

【語法練習 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);

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

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

第 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

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

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

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

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

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

我們可以宣告 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}};

更複雜一點的巢狀結構陣列,例如   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]

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

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

結構指標所指向的結構資料成員,有兩種不同的表示法:   (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 為指標,請務必小心。

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

結構陣列 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)

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

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

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

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

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

11 main() 12 { 13 void print_emp(struct EMPLOYEE); 14 struct EMPLOYEE x; 15 16 x.id = 18; 17 strcpy(x.name,"Crick"); 18 x.salary = 100000L; 19 20 print_emp( x ); 21 }

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

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

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

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

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

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

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。

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

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