




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、第八章結構體和共用體 前面幾章,我們已經介紹了幾種基本數據類型(如整型int,浮點型float/double,字符型char等),這些都是簡單數據類型,簡單數據類型的變量之間看不出必然的聯系(在內存中可以不一起存放;彼此的引用也沒有必然的聯系)。 另外,介紹了一種構造數據類型數組。它是具有同種數據類型的多個數據的集合,把多個數據捆綁在一起,彼此之間建立了一種聯系。 現實生活中有很多情況要求把多個不同數據類型的數據集中以整合的姿態出現,因此,用數組就不能有效表達。如:學生檔案:學號、姓名、年齡、性別、課程代碼、課程名、成績、學分。一個學生的信息由:s_no,name,age, sex, cour
2、secode,coursename, score , n_score 等集中包含的,由若干不同數據類型的數據構成。在C語言中引入一個結構體類型來實現之。 如:struct studentlong s_no;char name20;int age;char sex;long coursecode;char coursename30;float score;float n_score; 8.1 結構體一、結構體類型和變量如同枚舉類型和枚舉類型的變量,也有結構體類型和結構體類型變量。枚舉類型和結構體類型都是用戶自定義類型,一旦定義了某個結構體類型后(如前面:struct student),就與系統定
3、義的int , float等一樣,可以用來定義變量。1、定義結構體類型變量的三種形式: 、先定義結構體類型,再定義變量struct studentlong s_no;char name20;int age;char sex;long coursecode;char coursename30;float score;float n_score;struct student stu1,stu2 ;或 student stu1,stu2 ;student :具體的結構體類型標記struct student :可以用來作為新的類型名來定義一個變量如:struct dateint year;int mo
4、nth;int day;int day_in_year;char month_name4;struct date d1, d2 ;定義類型的同時定義變量如:struct dateint year;int month;int day;int day_in_year;char month_name4; d1, d2 ;成員或域,需要定義其類型。由所有成員的類型整合出該用戶定義結構體類型。sizeof(struct date)或sizeof(date)的值均為4*sizeof(int)+4*sizeof(char)注意:類型定義中的成員是沒有空間的,只有定義了該結構體類型的某個變量d1,該變量的對應
5、成員才會分配空間,結構體變量的空間是所有成員空間的總和。 直接定義結構體類型和變量在第二種方式中定義結構體類型的變量時,可以省略結構體類型標記如:structint year;int month;int day;int day_in_year;char month_name4; d1, d2 ;2、說明:、結構體類型與結構體變量:變量定義要分配空間,而類型定義不會;故可以引用變量,而不能引用類型。date結構體類型標記符可以省略、結構體變量在內存中的存放:所有成員在內存中依次連續存放,一個緊挨一個,整個結構體變量需占內存總數等于所有成員分別占用內存空間的總和。d1:2B 2B 2B 2B 1B
6、 1B 1B 1B year month day day_in_year char char char char 、結構體類型標記只有在存在變量定義列表的情況下才可以被省略,而且在以后的程序代碼中,不再定義類似的結構體類型變量。如:struct int year;int month;int day;int day_in_year;char month_name4; ; / 用下面的方法也可以解決無標記的結構體類型不能在以后定義變量的困惑如:typedef struct int year;int month;int day;int day_in_year;char month_name4; ON
7、ESTRUCT ,*struct_ptr;ONESTRUCT str1, str2 ,a20 ;struct_ptr p ;、成員與變量成員本身實質上是變量,有地址空間。但引用時與一般變量不一樣,引用成員要受結構體變量的限制。成員不能獨立存在,引用時在成員變量之前加上結構體變量名和成員引用運算符“.”。故即使成員名與一般變量同名,也不是一個對象。 成員和變量可以同名; 結構體標記和成員可以同名;和變量可以同名; 不同結構體變量的成員可以同名。因為它們是不同的命名空間。typedef關鍵字typedef是給已經定義過的類型名定義一個新的別名typedef int INTEGER;typedef
8、unsigned char BYTE;typedef unsigned short WORD;typedef unsigned long DWORD;typedef常用來給一個名字長的類型指定一個短類型名typedef _currentposition CP;typedef char81 STRING;Typedef char STRING81;STRING name;/char name82;Typedef int *pInt;pInt pa=&a;/int *pa=&a;、結構體類型可以嵌套定義struct payfloat basic;float yearly;/工齡float posi
9、tion;/職務float bonus;/獎勵;/工資部分struct addfloat overtime;/加班float familyplan;/獨子float transportation; ;/加發部分struct subfloat housing;float water_electricity;float cleaning; ;/扣發部分struct payrollchar name20;char depart20;struct pay salary;struct add addition;struct sub subtraction;struct payroll real;、結構體
10、類型可以嵌套定義 struct sub float housing; float water_electricity; float cleaning; subtraction; /扣發部分;struct payroll real;struct payrollchar name20;char depart20;struct pay float basic; float yearly;/工齡 float position;/職務 float bonus;/獎勵 salary; /工資部分struct add float overtime;/加班 float familyplan;/獨子 float
11、 transportation; addition; /加發部分二、結構體變量的初始化外部類和靜態類的結構體變量定義時可以帶初值列表,即初始化;而自動類結構體變量帶初值列表實際上是賦值操作。如:struct date d1 =1981,5,13,133,”May” ;struct studentlong s_no ;char name20 ;int age ;char sex ;long coursecode ;char coursename30 ;float score;float n_score; stu1 =961811530,”Wang Ming”,18,M,4111011,”大學體育
12、”,98.0,2.0;struct payroll emp1=“Li Ming”,”IE”,229,66,205,420,25,2,16.2,36,90.5,70;三、結構體變量的引用1、ANSI C規定:不能對結構體變量進行整體輸入輸出如:struct student stu1 =.;/ scanf(“%ld,%s,%d,%c,%ld.”,&stu1)/ printf(“%ld,%s,%d,%c,%ld.”,stu1);/ C+:允許兩個同結構體類型的變量互相整體賦值如:struct student stu1 , stu2 =.; stu1 = stu2 ; / 例: struct A in
13、t i , j; double d ; a ,a1=1,2,3.3;struct B int i , j ; double d ; b ;則:a=a1;/ a =b;/ a .i=b.i ; a.j=b.j; a.d =b.d ;/ 成員的引用:結構體變量名 . 成員名“ . ”運算符的優先級確保結構體成員引用可以不用圓括號a1 .i =100(a1 .i )=100int m =a1.j ;2、成員的數據類型為嵌套的結構類型:不能對此成員進行整體賦值和引用,只能對該成員(某個結構體類型)的具體數據類型成員來引用,如:real . addition . overtime=100;/real .
14、 addition =100,2,66;/ 3、成員運算:同變量一樣,如:int n =a.j+a.j ;a1.i +=a.i; a. j+ (a.j)+4、結構體變量和成員的地址:scanf(“%d”,&a .i);printf(“%xn”,&a); 8.2 結構體數組結構體與數組結合可以使我們構造任意復雜的客觀對象抽象模型。例:人員登記表的建立與查詢:#include void main() struct people char name20; int age; pe8 ; int i,j;for(i=1;i形參的傳遞。【例】對一個Person結構數組進行“冒泡法”排序,工資高的排在后面#
15、include #define N 4struct Person char name20; unsigned long id; float salary; /注意類型定義的作用域struct Person alloneN = “jone”, 12345, 339.0, “david”, 13916, 311.0, “jasen”, 42876, 623.0, “jone”, 12345, 400.0void main(void) struct Person temp; int i, j, k; for (i=1; i=N-1; i+) / 排序 for (j=1; jallonej.salar
16、y) / 比較工資成員 temp = allonej; / 交換結構變量 allonej = allonej+1; allonej+1 = temp; /end for i for (k=0; k成員名#include #include struct Person char name20; unsigned long id; float salary;void main(void) struct Person pr1, *prPtr; 其中,符號“-”為指向結構成員運算符。 因此,下列3 種書寫格式等價:故, studentp-name 等價于 注意:當用點操作符時,
17、它的左邊應是一個結構變量;當用箭頭操作符時,它的左邊應是一個結構指針(已經指向一個合法的結構體對象)。 指針是有類型的,引用一個整型指針得到一個整數,引用一個結構指針得到一個結構體#include struct Person char name20; unsigned long id; float salary;struct Person allone4 = “jone”, 12345, 339.0, “david”, 13916, 311.0, “jasen”, 42876, 623.0, “jone”, 12345, 400.0【例】用指針方法對一個Person結構數組進行“冒泡法”排序,
18、工資高的排 在后面。 結構變量名. 成員名 (* 結構指針變量名). 成員名 結構指針變量名-成員名 prPtr = &pr1; strcpy(prPtr-name, “David”); prPtr-id = 1234567; prPtr-salary = 333.33; printf(“”);void main(void) struct Person * pA4 = &allone0, &allone1, &allone2, &allone3 ; struct Person * temp; int i, j; for (i=1; i=3; i+) / 排序 for (j=1; jsalary
19、 pAj-salary) / 比較工資成員 temp = pAj-1; / 交換結構指針 pAj-1 = pAj; pAj = temp; / 打印輸出 在程序中建立了一個結構指針數組pA,并依次初始化為結構數組元素的地址值。對結構成員的訪問,即由點操作符改成了箭頭操作符。 發生交換時,并不是兩個結構變量值的交換,而是兩個結構指針交換,所以交換的臨時變量是一個結構指針。最后輸出的是通過結構指針訪問的結構變量值。 由于不必用結構值賦值的方法進行交換,故其運行效率高。8.4 結構與函數1、與其它數據類型一樣,結構可以用作函數的參數(可采用傳值/傳址方式)【例】由前述結構Student,編程對其結構
20、變量進行賦值和打印輸出。void input(struct Student * student_p) / 因要回傳,故用結構指針 printf(Input a students No, Name & Score:”); scanf(“%d”, &(student_p-No); scanf(“%s”, student_p-Name); scanf(“%f”, &(student_p-Score);void print(struct Student student) / 打印,可單向傳值 printf(“The students No:%dn”, student .No); printf(“The
21、 students Name:%sn”, student.Name); printf(“The students Score:%fn”, student.Score); 調用時: void main(void) struct Student student; input(&student); print(student); 將一個完整的結構變量作為參數傳遞,雖合法,但麻煩,效率低。2、結構可以作為函數的返回值。【例】由前述結構Student,編程對其結構變量進行賦值。struct Student input(void) struct Student student; printf(Input
22、a students No, Name & Score:”); scanf(“%d”, &(student . No); scanf(“%s”, student . Name); scanf(“%f”, &(student . Score); return (student); / 返回一個student類型的變量 調用時: void main(void) struct Student student; student = input( ); 【例】輸入10個學生的學號、姓名和4門課的成績,分別用函數實現: 輸入學生的有關信息; 求出每個學生的平均分數; 求出每門課的平均分數; 按平均分進行學
23、生名次排列; 找出最高總分所對應的學生 ;#include #include #define STUDENTMEMBER 10#define CLECTUREMEMBER 4/ 結構定義struct Student int No; char Name8; float ScoreCLECTUREMEMBER;/ 函數原型說明void Input(Student *,int );void PAverageScore(Student *,int );void CAverageScore(Student *,int);void SortScore(Student *,int);struct Stude
24、nt HighestScore(Student *,int);/函數HighestScore返回最高分學生的有/關信息void main(void) struct Student studentsSTUDENTMEMBER; / 定義變量 struct Student higheststudent; int i;/ 調用有關函數 Input(students, STUDENTMEMBER); PAverageScore(students, STUDENTMEMBER); CAverageScore(students, STUDENTMEMBER); SortScore(students, ST
25、UDENTMEMBER); / 輸出排序后的學生信息 printf( No. Name Score1 Score2 Score3 Score4n); for (i=0; iSTUDENTMEMBER; i+) printf(%6d %8s %f %f %f %fn, studentsi.No, studentsi.Name, studentsi.Score0, studentsi.Score1, studentsi.Score2, studentsi.Score3); higheststudent = HighestScore(students, STUDENTMEMBER); printf(
26、The student with highest score is: %s(No.%6d)n, higheststudent.Name, higheststudent.No); / 輸出最高分學生的信息void Input(struct Student * pstudent, int n) int i, j; float score; for (i=0; iNo); printf(Input the name of student No.%2d:, i+1); scanf(%s, (pstudent+i)-Name); /fflush(stdin);gets(pstudent+i)-Name)
27、; printf(Input %d clecture scores of student No.%2d:n, CLECTUREMEMBER, i+1); for (j=0; jScorej = score; void PAverageScore(struct Student * pstudent,int n) int i, j; float averagescore; printf(Average score for studentn); printf( No. Name Average Scoren); for (i=0; in; i+) averagescore = 0; for (j=0
28、; jScorej; averagescore /= CLECTUREMEMBER; printf(%6d %8s %fn, (pstudent+i)-No, (pstudent+i)-Name, averagescore); /常規來說,不在函數內輸出信息 void CAverageScore(struct Student * pstudent,int n) int i, j; float averagescore; printf(Average score for clecturen); printf( No. Average Scoren); for (j=0; jCLECTUREMEM
29、BER; j+) averagescore = 0; for (i=0; iScorej; averagescore /= n; printf(%6d %fn, j+1, averagescore); void SortScore(struct Student * pstudent,int n) int i,j, k, m, max; float scoremax, score; int tempNo; / tempNo, tempName, tempScore:臨時變量, char tempName8; / 用于兩個結構變量的數據交換 float tempScoreCLECTUREMEMBE
30、R; for (i=0; in-1; i+) max = i; for (scoremax=0, m=0; mScorem; for (j=i+1; jn; j+) for (score=0, m=0; mScorem; if (scorescoremax) /發現新的j學生總分更高 max = j; scoremax = score; struct Student temp;思考:是否有必要把總分作為Student類型的成員之一,再設計一個專門統計學生總分的函數一次性計算出所有學生總分信息并保存。/ 結構數組的第 i 號元素與第 max 號元素相交換 if(max!=i) tempNo =
31、(pstudent+i)-No; strcpy(tempName, (pstudent+i)-Name); for (m=0; mScorem; (pstudent+i)-No = (pstudent+max)-No; strcpy(pstudent+i)-Name, (pstudent+max)-Name); for (m=0; mScorem = (pstudent+max)-Scorem; (pstudent+max)-No = tempNo; strcpy(pstudent+max)-Name, tempName); for (m=0; mScorem = tempScorem; te
32、mp =*(pstudent+i);*(pstudent+i) = *(pstudent+max);*(pstudent+max) =temp;struct Student HighestScore(struct Student * pstudent ,int n) float maxscore=0, score; int maxno, i, j; /先求出第一個學生的總分,假定為最大總分 for (j=0; jScorej; maxno = 0; for (i=1; in; i+)/遍歷其他所有學生 score = 0; for (j=0; jScorej; if (maxscorescor
33、e) maxscore = score; maxno = i; return (*(pstudent+maxno);/返回結構體值的函數8.5 引用自身的結構 結構可以嵌套,即結構中可以包含結構體類型的成員。【例】 struct Education char major20; / 主修課程 char degree20; / 學位 ; struct Student int StudentNo; char Name8; struct Education education; / 結構中嵌套一個Education結構 float Score; ; struct Student ss; / 創建一個結
34、構變量 在引用嵌套結構的成員時,要使用多個點操作符。 例:cation.major注: 結構類成員不能是當前定義結構體類型的結構變量。(但可用當前定義結構體類型的結構指針作為成員) 例:struct Node char name20; Node * pNext; / 允許Node結構指針作為其成員 Node m; / error 不應含有自身結構變量 ; 結構成員不能是自身的結構變量,但可用結構指針作為成員鏈表。 引用自身的結構:結構中的某個成員是指向該結構類型對象的指針。鏈表是最簡單的動態數據結構。每個結點僅只含有一個指向自身的指針,則構成單向鏈表。設計頭指針指向鏈表的第一個結點
35、,最后一個結點的指針域不指向任何結點(為空指針)。 【例】 struct node float number; / 結構成員1:數據域 node * next; / 結構成員2:指針域,指向另一個node變量 創建若干 node 類型的變量,使用 next 指針相連,即構成了鏈表。 數組:連續分配的一塊內存空間。 鏈表:若干不連續的內存塊(堆內存)用指針相連(以單向鏈表為例)。 數據成員 指針頭指針a0a1an 鏈表的作用: 數組的特點是,引用其中數據的規格十分嚴格;增減操作具有破壞性 ;存儲區相鄰。存儲空間在程序執行時已經確定。 對于某些問題,數據的數量事先無法確定,只能在程序的運行過程中,
36、按需要臨時向系統申請存儲空間“動態分配”內存問題(動態數據結構)。 與數組不同,鏈表可以隨機存取(因其中每個節點都附有指向下一節點的鏈指針),鏈表可以使用十分復雜的數據結構,鏈表可以十分方便地進行檢索操作。 鏈表的作用: 可以在內存中建立未知大小的數組; 存儲磁盤文件。可以方便、迅速地插入或刪除節點內容而無須重新安排文件。鏈表廣泛地應用于程序設計中。 鏈表的操作有創建、插入、刪除、查詢等。 對于鏈表的各種操作,一般應具備以下條件: 已知鏈表的頭結點(鏈頭指針) 已知鏈表結點間的勾鏈關系(哪個結點是下一個結點),且不能斷開,無論增減結點皆如此。建鏈的基本步驟: 申請結點存貯空間 數據送入結點(有
37、時指針域需置空) 結點入鏈鏈表操作需使用動態內存分配與釋放存貯空間的函數。#include #include void* malloc(unsigned int size); 功能:向系統申請分配由參數size指定長度的存貯區,并返回指向新 分配存貯區的指針(void * 類型)。當系統無內存分配時,則返回NULL。 void free(void * ptr) ;功能:釋放由指針ptr所指的存貯塊,以供今后再次分配。【例】創建鏈表#include #include struct Student int StudentNo; char Name8; int Score;struct Studen
38、tNode struct Student student; struct StudentNode * Next;struct StudentNode * CreateNode(void);void ShowLink(struct StudentNode *);void main(void) struct StudentNode * head; head = CreateNode(); ShowLink(head);struct StudentNode * CreateNode(void) struct StudentNode *head, *p, *newp; char answer; new
39、p = (struct StudentNode *) malloc(sizeof(struct StudentNode); head = p = newp; do if (newp=NULL) printf(Error! Cant mallocate memory.); exit(1); printf(Input students no, name, score:n); scanf(%d, &(newp-student. StudentNo); scanf(%s, newp-student.Name); scanf(%d, &(newp-student.Score); newp-Next =
40、NULL; getchar(); printf(Input again?(y/n); scanf(%c, &answer); if (answer=n| answer=N) break; else newp = (struct StudentNode *) malloc(sizeof(struct StudentNode); p-Next = newp; p = newp; while (1); return (head);void ShowLink(struct StudentNode * head) struct StudentNode * p; p = head; printf(nOut
41、put datan); while (p!=NULL) printf(No:%dn, p-student. StudentNo); printf(Name:%sn, p-student.Name); printf(Score:%dnn, p-student.Score); p = p-Next; 運行結果為: Input students no, name, score:1A1Input again?(y/n)y2B2Input again?(y/n)nOut dataNo:1Name: AScore:1No:2Name: BScore:2頭指針a1a2an a1頭指針a1a2an a1 插入
42、結點 在結點a1,a2之間插入結點a1。則應: a1-next= a1-next; / 原a1-next= a2 a1-next = a1; void InsertNode(struct StudentNode * last, struct StudentNode *entity) / 插入新節點entity于last節點之后 if (last=NULL) last = entity; entity = NULL; else entity-Next = last-Next; last-Next = entity; a1a1an a2 a1an a2 刪除結點 刪除結點a1,a2之間的結點a1。
43、則應: a1-next= a1-next; 釋放結點a1所占用的內存空間。 void DeleteNode(struct StudentNode * point) struct StudentNode * p; p = point-Next; point-Next = point-Next-Next; free(p); 綜合舉例例8.14 編程處理某班N個學生4門課的成績,它們是數學、物理、英語和計算機,按編號從小到大的順序依次輸入學生的姓名、性別和四門課的成績。計算每個學生的平均分,并以清晰的打印格式從高分到低分的順序打印平均分高于全班總平均成績的男生的成績單。分析:從題目的要求來看,該問題
44、可以分成三個功能塊:輸入數據、排序,求總平均成績和輸出,我們把它規劃成四個函數。再來看主要的數據類型或數據結構的選擇,由于學生的姓名、性別、各門功課的成績及平均成績具有一定的關聯性,作為集合數據,將其規劃為一個結構體:struct student char name20; /姓名 char sex; /性別,m代表男,f代表女 float score4; /學生的各科成績 float aver; /平均成績; 這樣學生的數據就可以存放在一個結構數組中。有了上面的分析結果,我們就可以規劃出三個函數的原型:(1)輸入數據:void input(struct student *p,int n);第一個參數用來接收存儲學生數據的結構數組的首地址,第二個參數接收學生的個數,(2)排序:void sort(struct student *p,int n);第一個參數用來接收存儲學生數據的結構數組的首地址,第二個參數接收學生的個數,(3)輸出:void outp
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 交旅融合新趨勢與市場前景深度分析
- 《加與減》(教學設計)-2024-2025學年二年級上冊數學滬教版
- 初中化學跨學科教學的創新路徑與實踐探索
- 人教版9數上 22 章末復習 教案+導學案
- 全國浙教版初中信息技術八年級下冊第三單元第15課《智能物聯系統的調試與完善》教學設計
- 接地體和接地導線的選擇吳振國時間年月課件
- Module8(教學設計)-2023-2024學年外研版(三起)英語五年級下冊
- 人教版九年級化學上冊3.3元素 教學設計
- 勞務員試題庫完整
- 小學美術湘美版二年級下冊第4課 動物聚會教學設計及反思
- 公路養護安全意識培訓
- 控制性詳細規劃城市用地分類和代號
- 鐵路專用線設計規范(試行)(TB 10638-2019)
- 主題一+鞋子擦洗自己做+第二課時(課件)-甘肅教育出版社勞動三年級+下冊
- ISO 45003-2021職業健康安全管理-工作中的心理健康安全-社會心理風險管理指南(中文版)
- 三年級語文 寫通知(全國一等獎)
- 2020電網技術改造工程概算定額第五冊調試工程
- 起重機機械金屬結構
- 自然教育課程的追尋與實踐
- 諾如病毒診斷和治療
- 《無人機攝影測量》考試復習題庫(含答案)
評論
0/150
提交評論