C語(yǔ)言程序設(shè)計(jì)(第二版)課件第9章結(jié)構(gòu)體和共用體_第1頁(yè)
C語(yǔ)言程序設(shè)計(jì)(第二版)課件第9章結(jié)構(gòu)體和共用體_第2頁(yè)
C語(yǔ)言程序設(shè)計(jì)(第二版)課件第9章結(jié)構(gòu)體和共用體_第3頁(yè)
C語(yǔ)言程序設(shè)計(jì)(第二版)課件第9章結(jié)構(gòu)體和共用體_第4頁(yè)
C語(yǔ)言程序設(shè)計(jì)(第二版)課件第9章結(jié)構(gòu)體和共用體_第5頁(yè)
已閱讀5頁(yè),還剩40頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第9章結(jié)構(gòu)體和共用體

結(jié)構(gòu)體和共用體(也稱聯(lián)合)是程序設(shè)計(jì)中常用的數(shù)據(jù)類型,常用于描述實(shí)際問題中具有多個(gè)不同數(shù)據(jù)成員的一類實(shí)體。9.1概述

9.2結(jié)構(gòu)體與結(jié)構(gòu)體類型變量9.3結(jié)構(gòu)體數(shù)組9.4指向結(jié)構(gòu)體類型數(shù)據(jù)的指針9.5動(dòng)態(tài)存儲(chǔ)分配與鏈表9.6共用體9.7枚舉類型9.8用Typedef定義類型9.9應(yīng)用實(shí)例——學(xué)生成績(jī)管理系統(tǒng)9.1概述家庭住址

(字符串)身份證號(hào)

(長(zhǎng)整型)性別

(字符型)年齡

(整型)姓名

(字符串)學(xué)號(hào)

(長(zhǎng)整型)

在實(shí)際應(yīng)用中,人們經(jīng)常需要將不同類型的數(shù)據(jù)作為一個(gè)整體來處理。

比如:要描述一個(gè)學(xué)生的基本情況,就需要記錄他的學(xué)號(hào)、姓名、年齡、性別、身份證號(hào)、家庭住址等信息。9.2結(jié)構(gòu)體與結(jié)構(gòu)體類型變量

在C語(yǔ)言中,結(jié)構(gòu)體是不同數(shù)據(jù)類型的集合。

在使用結(jié)構(gòu)體這種數(shù)據(jù)類型之前,必須要先對(duì)其進(jìn)行定義,對(duì)結(jié)構(gòu)體的定義包括結(jié)構(gòu)體類型和結(jié)構(gòu)體變量的定義兩部分。9.2.1結(jié)構(gòu)體類型的定義聲明一個(gè)結(jié)構(gòu)體類型的一般形式為:struct結(jié)構(gòu)體名{成員列表};structstudent{longnum;charname[20];intage;charsex;longcertificate;charaddress[40];};E-mail(字符串)電話號(hào)碼(長(zhǎng)整型)郵編(長(zhǎng)整型)家庭住址(字符串)部門(字符串)姓名(字符串)【例9.1】如果通訊地址表由下面的項(xiàng)目構(gòu)成:structaddr{charname[20]; /*姓名*/chardepartment[30]; /*部門*/charaddress[30]; /*家庭住址*/longbox; /*郵編*/longphone; /*電話號(hào)碼*/charemail[30]; /*E-mail*/};9.2.2結(jié)構(gòu)體類型變量的定義

應(yīng)當(dāng)定義結(jié)構(gòu)體類型的變量,并在其中存放具體的數(shù)據(jù)。定義方法有以下三種:

(1)先定義結(jié)構(gòu)體類型再定義結(jié)構(gòu)體變量。structstudent{intnum;charname[20];floatscore;};structstudentboy1,boy2;(2)在定義結(jié)構(gòu)體類型的同時(shí)定義結(jié)構(gòu)體變量。一般形式為:struct結(jié)構(gòu)名{

結(jié)構(gòu)體成員表列}變量名表列;structstudent{intnum;charname[20];floatscore;}boy1,boy2;(3)直接定義結(jié)構(gòu)體類型變量。一般形式為:struct{

結(jié)構(gòu)體成員表列}變量名表列;struct{intnum;charname[20];floatscorce;}boy1,boy2;9.2.2結(jié)構(gòu)體類型變量的定義有關(guān)結(jié)構(gòu)體類型需要說明的是:1)結(jié)構(gòu)體類型與變量的概念。只能對(duì)變量進(jìn)行操作(賦值、存取或運(yùn)算),而不能對(duì)一個(gè)結(jié)構(gòu)體類型進(jìn)行操作。編譯時(shí),只對(duì)變量分配內(nèi)存空間,對(duì)結(jié)構(gòu)體類型不分配內(nèi)存空間。2)對(duì)結(jié)構(gòu)體中的成員可以單獨(dú)使用,它的作用與地位相當(dāng)于普通變量。3)結(jié)構(gòu)體的成員也可以是一個(gè)結(jié)構(gòu)體變量,從而構(gòu)成嵌套結(jié)構(gòu)。structdate/*說明一個(gè)結(jié)構(gòu)體類型*/{intmonth;intday;intyear;};structstudent{intnum;charname[20];charsex;intage;structdatebirthday;/*birthday是structdate類型*/charaddress[20];}student1,student2;numnamesexagebirthdayaddressmonthdayyear4)結(jié)構(gòu)體中的成員名可以與程序中的變量名相同,但二者代表不同的對(duì)象。9.2.3結(jié)構(gòu)體變量的引用結(jié)構(gòu)體變量也可以像其他類型的變量一樣賦值、存取或運(yùn)算,所不同的是結(jié)構(gòu)體變量必須以成員作為基本單位來參與。結(jié)構(gòu)體成員的表示方法為:結(jié)構(gòu)體變量名.成員名例如:student1.num表示第一個(gè)人的學(xué)號(hào);student2.sex表示第二個(gè)人的性別。關(guān)于引用結(jié)構(gòu)體成員有幾點(diǎn)說明:(1)如果結(jié)構(gòu)體成員本身又屬于一個(gè)結(jié)構(gòu)體類型,則需要若干個(gè)成員運(yùn)算符,一級(jí)一級(jí)來找到最低的成員,且只能對(duì)最低級(jí)的成員進(jìn)行賦值、存取或運(yùn)算student1.monthstudent1.birthday.daystudent1.birthday.year(2)結(jié)構(gòu)體變量中各成員的使用方法與普通的簡(jiǎn)單類型變量完全相同。student1.sex=student2.sex;student1.num++;(3)不能將結(jié)構(gòu)體變量作為一個(gè)整體進(jìn)行輸入和輸出。假設(shè)已將student1和student2定義為結(jié)構(gòu)體類型structstudent的變量,并且各成員已賦值,則不能這樣引用:printf("%d,%s,%c,%d,%f,%s\n",student1);只能對(duì)結(jié)構(gòu)體變量中的成員分別進(jìn)行輸入、輸出或賦值。例如:student1.num=1001;僅在以下兩種情況下,可以把結(jié)構(gòu)體變量作為一個(gè)整體來訪問(引用)。1)可以對(duì)結(jié)構(gòu)體變量進(jìn)行整體賦值,例如:student1=student2;/*將student2中的所有內(nèi)容賦值給student1*/2)取結(jié)構(gòu)體變量的地址,例如:printf("%x",&student1);/*輸出student1的地址*/對(duì)結(jié)構(gòu)體變量的整體操作只限于賦值操作和參數(shù)傳遞,而且要求結(jié)構(gòu)體變量的類型必須完全一致?!纠?.2】結(jié)構(gòu)體變量的賦值并輸出其值。#include"stdio.h"voidmain(){structstu{intnum;char*name;charsex;floatscore;}boy1,boy2;boy1.num=102;boy1.num="zhangping";printf("inputsexandscore:");scanf("%c%f",&boy1.sex,&boy1.score);boy2=boy1;printf("number=%d\nname=%s\n",boy2.num,);printf("sex=%c\nscore=%.2f\n",boy2.sex,boy2.score);}程序的運(yùn)行結(jié)果:inputsexandscore:M96number=102name=zhangpingsex=Mscore=96.009.2.4結(jié)構(gòu)體變量的初始化與普通變量一樣,對(duì)結(jié)構(gòu)體變量可以在變量定義時(shí)指定初始值,也就是給結(jié)構(gòu)體變量的各個(gè)成員項(xiàng)賦初值?!纠?.3】外部結(jié)構(gòu)變量初始化#include"stdio.h"structstu{intnum;char*name;charsex;floatscore;}boy2,boy1={102,"zhangping",'M',96.00};voidmain(){boy2=boy1;printf("number=%d\nname=%s\n",boy2.num,);printf("sex=%c\nscore=%f\n",boy2.sex,boy2.score);}程序的運(yùn)行結(jié)果:inputsexandscore:M96number=102name=zhangpingsex=Mscore=96.00【例9.4】靜態(tài)結(jié)構(gòu)變量初始化#include"stdio.h"voidmain(){staticstructstu{intnum;char*name;charsex;floatscore;}boy2,boy1={102,"zhangping",'M',96.00};boy2=boy1;printf("number=%d\nname=%s\n",boy2.num,);printf("sex=%c\nscore=%f\n",boy2.sex,boy2.score);}不能在結(jié)構(gòu)體內(nèi)賦初值。例如,以下的初始化工作就是錯(cuò)誤的:structstudent{longintnum=102;charname[20]="zhangping";charsex='M';floatscore=96.00;}boy1;9.3結(jié)構(gòu)體數(shù)組結(jié)構(gòu)體變量也可以構(gòu)造成數(shù)組,稱為結(jié)構(gòu)體數(shù)組。每個(gè)結(jié)構(gòu)體數(shù)組元素都是一個(gè)結(jié)構(gòu)體變量,都含有結(jié)構(gòu)體的各個(gè)成員項(xiàng)。每個(gè)數(shù)組的元素在內(nèi)存中的地址是按照數(shù)組下標(biāo)的順序連續(xù)的。結(jié)構(gòu)體數(shù)組的定義方法,例如:structstudent{intnum;charname[20];floatscore;}student1[45];結(jié)構(gòu)體數(shù)組的初始化:structstudent{intnum;charname[20];floatscore;}a[2]={{1001,"Zhang",85},{1002,"Wang",86}};【例9.3】計(jì)算學(xué)生的平均成績(jī)和不及格人數(shù)。structstudent{intnum;charname[20];floatscore;}student1[5]={{1001,"Liping",55},{1002,"Zhangping",80},{1003,"Wangfang",75},{1004,"Chenglin",82},{1005,"Wuyong",94}};main(){inti,c=0;floataverage,s=0;for(i=0;i<5;i++){s+=student1[i].score; if(student1[i].score<60)c+=1; }average=s/5; printf("average=%f\ncount=%d\n",average,c);}【例9.4】建立同學(xué)通訊錄。#include"stdio.h"#defineNUM3structmen{charname[20];charphone[10];};main(){structmenman[NUM];inti;for(i=0;i<NUM;i++){printf("inputname:");gets(man[i].name);printf("inputphone:");gets(man[i].phone);}printf("name\t\tphone\n\n");for(i=0;i<NUM;i++)printf("%s\t\t%s\n",man[i].name,man[i].phone);}【例9.5】對(duì)候選人得票的統(tǒng)計(jì)程序,設(shè)有3個(gè)候選人,選民每次輸入一個(gè)候選人的姓名,要求最后輸出各人的得票結(jié)果。分析:設(shè)一個(gè)數(shù)組,有3個(gè)元素,每個(gè)元素中的信息應(yīng)該包括候選人的姓名(字符型)和得票數(shù)(整型),用結(jié)構(gòu)體數(shù)組來實(shí)現(xiàn)。#include"stdio.h"#include"string.h"structperson /*聲明結(jié)構(gòu)體類型structperson*/{charname[20]; /*候選人姓名*/intcount; /*得票數(shù)*/}leader[3]={"Li",0,"Zhang",0,"Fun",0}; /*定義結(jié)構(gòu)體數(shù)組*/voidmain(){inti,j;charleader_name[20]; /*定義字符數(shù)組*/for(i=1;i<=10;i++){scanf("%s",leader_name); /*輸入候選人的姓名*/for(j=0;j<3;j++)if(strcmp(leader_name,leader[j].name)==0)leader[j].count++;}printf("\nResult:\n");for(i=0;i<3;i++)printf("%5s:%d\n",leader[i].name,leader[i].count);}9.4指向結(jié)構(gòu)體類型數(shù)據(jù)的指針結(jié)構(gòu)體變量或數(shù)組也是內(nèi)存中的對(duì)象,可以通過指針進(jìn)行訪問。指向結(jié)構(gòu)體變量的指針稱為結(jié)構(gòu)體指針,實(shí)質(zhì)上是指向結(jié)構(gòu)體變量的首地址,其邏輯上加1,等于加一個(gè)結(jié)構(gòu)體類型所占的字節(jié)數(shù),即加一個(gè)結(jié)構(gòu)體的長(zhǎng)度。結(jié)構(gòu)體指針必須先說明,然后指向同類型的對(duì)象再通過指針引用所指對(duì)象的各個(gè)成員項(xiàng)。9.4.1指向結(jié)構(gòu)體變量的指針指向結(jié)構(gòu)體變量的指針變量的定義的一般形式為:struct結(jié)構(gòu)體名*結(jié)構(gòu)體指針變量名例如:strcutstud_score{intnum;charname[20];floatscore;};structstud_score*spoint;結(jié)構(gòu)體變量訪問的一般形式為:(*結(jié)構(gòu)體指針變量).成員名或?yàn)椋航Y(jié)構(gòu)體指針變量->成員名例如:(*spoint).num或?yàn)椋簊point->num【例9.8】指向結(jié)構(gòu)體變量的指針的應(yīng)用。structstudent{intnum;charname[20];floatscore;}student1={1001,"Zhang",75.5},*spoint;main(){spoint=&student1;printf("Number=%d,Name=%s,",student1.num,);printf("Score=%f\n",student1.score);printf("Number=%d,Name=%s,",(*spoint).num,(*spoint).name);printf("Score=%f\n",(*spoint).score);printf("Number=%d,Name=%s,",spoint->num,spoint->name);printf("Score=%f\n",spoint->score);}運(yùn)行結(jié)果如下:Number=1001,Name=Zhang,Score=75.500000Number=1001,Name=Zhang,Score=75.500000Number=1001,Name=Zhang,Score=75.500000結(jié)構(gòu)體變量.成員名(*結(jié)構(gòu)體指針變量).成員名結(jié)構(gòu)體指針變量->成員名這三種表示結(jié)構(gòu)成員的形式是完全等效的。9.4.2指向結(jié)構(gòu)體數(shù)組的指針指針變量也可以指向一個(gè)結(jié)構(gòu)體數(shù)組,這時(shí)結(jié)構(gòu)體指針變量的值是整個(gè)結(jié)構(gòu)體數(shù)組的首地址?!纠?.9】指向結(jié)構(gòu)體數(shù)組的指針變量的應(yīng)用實(shí)例。structstudent{intnum;charname[20];floatscore;}student1[5]={{1001,"Liping",55},{1002,"Zhangping",80},{1003,"Wangfang",76.5},{1004,"Chenglin",62},{1005,"Wuyong",94}};說明:(1)如果pa=student1,表示指針pa指向結(jié)構(gòu)體數(shù)組student1的第1個(gè)元素。student1+i和pa+i均表示數(shù)組第i個(gè)元素的地址,數(shù)組元素個(gè)成員的引用形式為:(student1+i)->name,(student1+i)->num和(pa+i)->name,(pa+i)->num等。student1+i和pa+i與student1[i]意義相同。(2)如果指針變量pa指向數(shù)組的某一個(gè)元素,則pa++指向下一個(gè)元素。(3)一個(gè)結(jié)構(gòu)指針變量雖然可以用來訪問結(jié)構(gòu)體變量或結(jié)構(gòu)體數(shù)組元素的成員,但是,不能使它指向一個(gè)成員。也就是說不允許取一個(gè)成員的地址來賦予它。右邊的賦值是錯(cuò)誤的:pa=&student1[0].num;正確的:pa=student1;/*賦予數(shù)組首地址*/或是pa=&student1[2];/*賦予2號(hào)元素的地址*/。main(){structstudent*pa;printf("NO\tName\t\tScore\t\n");for(pa=student1;pa<student1+5;pa++)printf("%d\t%s\t%f\t\n",pa->num,pa->name,pa->score);getch();}9.4.3結(jié)構(gòu)體指針變量作為函數(shù)的參數(shù)將一個(gè)結(jié)構(gòu)體變量的值傳遞給另一個(gè)函數(shù),有3種方法:(1)用結(jié)構(gòu)體變量的成員作參數(shù)。用法和普通變量作實(shí)參是一樣的,屬于“值傳遞”方式。應(yīng)當(dāng)注意實(shí)參與形參的類型保持一致。(2)結(jié)構(gòu)體變量作實(shí)參。在ANSIC標(biāo)準(zhǔn)中允許用結(jié)構(gòu)體變量作參數(shù)進(jìn)行整體的傳送,但這種傳送方式要經(jīng)全部成員逐個(gè)傳送,特別是成員為數(shù)組時(shí)將會(huì)使傳送的時(shí)間和空間開銷很大,嚴(yán)重地降低了程序的效率。因此,一般較少采用這種方法。(3)用指向結(jié)構(gòu)體變量(或數(shù)組)的指針作為實(shí)參,將結(jié)構(gòu)體變量(或數(shù)組)的地址傳給形參。用指針變量作函數(shù)參數(shù)進(jìn)行傳送,這時(shí)由實(shí)參傳向形參的只是地址,減少了時(shí)間和空間的開銷?!纠?.7】輸入10個(gè)用戶的信息,調(diào)用函數(shù)change將原電話號(hào)碼中259開頭的電話號(hào)碼改為255開頭。#include"stdio.h"#definemax10structuser{intnum;charname[20];chartelephone[8];};voidchange(structuseru){inti;for(i=0;i<10;i++)if((u[i].telephone[0]=='2')&&(u[i].telephone[1]=='5')&&(u[i].telephone[2]=='9'))u[i].telephone[2]=='5';}

main(){structuseruser1[10];inti;for(i=0;i<10;i++){printf("inputnum:");scanf("%d",&user1[i].num);printf("inputname:");scanf("%s",&user1[i].name);printf("inputtelephone:");scanf("%s",&user1[i].telephone);}change(user1);for(i=0;i<10;i++)printf("num:%d,name:%s,telephone:%s\n",user[i].num,user[i].name,user[i].telephone);}【例9.11】計(jì)算一組學(xué)生的平均成績(jī)和不及格人數(shù)。用結(jié)構(gòu)指針變量作函數(shù)參數(shù)編程。structstu{intnum;char*name;floatscore;}student[5]={{101,"Liping",45},{102,"Zhangping",62.5},{103,"Hefang",92.5},{104,"Chengling",87},{105,"Wangming",58}};main(){structstu*pa;voidave(structstu*pa);pa=student;ave(pa);}voidave(structstu*pa){intc=0,i;floatave,s=0;for(i=0;i<5;i++,pa++){s+=pa->score;if(pa->score<60)c+=1;}printf("s=%f\n",s);ave=s/5;printf("average=%f\ncount=%d\n",ave,c);}9.4.4結(jié)構(gòu)體與函數(shù)的類型結(jié)構(gòu)體除了可以作為函數(shù)的參數(shù)外,函數(shù)的返回值也可以是結(jié)構(gòu)體變量或是指向結(jié)構(gòu)體變量的指針。當(dāng)函數(shù)的返回值是一個(gè)結(jié)構(gòu)體變量時(shí),稱該函數(shù)為一個(gè)結(jié)構(gòu)體類型函數(shù),其一般形式為:struct結(jié)構(gòu)體名函數(shù)名(形參表){函數(shù)體}【例9.12】結(jié)構(gòu)體中包含了一個(gè)學(xué)生的學(xué)號(hào)、姓名、成績(jī)等成員項(xiàng)。結(jié)構(gòu)體數(shù)組中包含一個(gè)班45人的基本信息,通過函數(shù)輸入結(jié)構(gòu)體數(shù)組的每個(gè)元素各個(gè)成員項(xiàng)的值。計(jì)算出成績(jī)的平均值,輸出成績(jī)小于平均值的學(xué)號(hào)、姓名、分?jǐn)?shù)。#include"stdio.h"#defineNUM45structstu{intnum;charname[20];floatscore;}main(){structstuinp();inti;floatave=0.0;structstuws[NUM];for(i=0;i<NUM;i++){ws[i]=inp();ave+=ws[i].score;}ave/=NUM;for(i=0;i<NUM;i++)if(ws[i].score<ave)printf("num:%dname:%sscore:%f\n",ws[i].num,ws[i].name,ws[i].score);}structstuinp(){charstr[20];structstustemp;printf("\ninputnum:");scanf("%d",&stemp.num);printf("\ninputname:");gets();printf("\ninputscore");scanf("%f",&stemp.score);return(stemp);}函數(shù)的類型說明方式為:struct結(jié)構(gòu)體名*函數(shù)名(形參表)

【例9.13】結(jié)構(gòu)體指針型函數(shù)舉例。結(jié)構(gòu)體中包含一個(gè)學(xué)生的學(xué)號(hào)、姓名、成績(jī)。結(jié)構(gòu)體數(shù)組中包含一個(gè)班45人的基本信息,輸入一個(gè)學(xué)號(hào)再通過函數(shù)在結(jié)構(gòu)體數(shù)組中查找,找到后函數(shù)返回?cái)?shù)組元素的地址,沒有找到返回NULL(0)。#include"stdio.h"#defineNULL0structstu{intnum;charname[20];floatscore;}main(){structstu*findp(intnumber,structstu*sp);structstustudent[45]={{1001,"Liping",55},{1002,"Zhangping",80},{1003,"Wangfang",75},{1004,"Chenglin",82},……{1045,"Wuyong",94}};intfnum;/*存放待查找學(xué)號(hào)*/inti;structstu*sap;printf("Enterthenumber:");scanf("%d",&fnum);sap=findp(fnum,student);if(sap->num!=NULL){printf("number:%d\n",sap->num);printf("name:%s\n",sap->name);printf("score:%f\n",sap->score);}elseprintf("Notfound\n");}

structstu*findp(intnumber,structstu*sp){inti;structstu*stemp=NULL;for(i=0;i<45;i++,sp++)if(sp->num==number){stemp=sp;break;/*找到后終止循環(huán)*/}return(stemp);}9.5.1鏈表的概念在鏈表數(shù)據(jù)中,任意一個(gè)數(shù)據(jù)項(xiàng)都包含如下內(nèi)容:數(shù)據(jù)域指針域

每個(gè)數(shù)據(jù)項(xiàng)稱為一個(gè)結(jié)點(diǎn),每個(gè)結(jié)點(diǎn)不僅存放了數(shù)據(jù),而且指明了下一項(xiàng)數(shù)據(jù)到哪里去取。數(shù)據(jù)域存放該數(shù)據(jù)項(xiàng)的內(nèi)容,指針域存放下一數(shù)據(jù)項(xiàng)地址。9.5動(dòng)態(tài)存儲(chǔ)分配與鏈表

鏈表是一種常見的數(shù)據(jù)結(jié)構(gòu),它動(dòng)態(tài)地進(jìn)行存儲(chǔ)分配,并且可以方便而又簡(jiǎn)單地進(jìn)行數(shù)據(jù)輸入、刪除等操作。2000Data12500Data22300Data3NULLN1N2N3200025002300head結(jié)構(gòu)體中必須有一個(gè)成員項(xiàng)是指向相同類型結(jié)構(gòu)體的指針,稱為引用自身的結(jié)構(gòu)體。如:structstu{intnum;char*name;floatscore; /*三項(xiàng)數(shù)據(jù)域*/structstu*next; /*指向相同類型結(jié)構(gòu)體的指針,指針域*/};9.5.2動(dòng)態(tài)存儲(chǔ)分配(1)分配內(nèi)存空間函數(shù)malloc。函數(shù)原型:(類型說明符*)malloc(size);功能:在內(nèi)存的動(dòng)態(tài)存儲(chǔ)區(qū)中分配一塊長(zhǎng)度為“size”字節(jié)的連續(xù)區(qū)域。函數(shù)的返回值為該區(qū)域的首地址。“類型說明符”表示把該區(qū)域用于何種數(shù)據(jù)類型。“(類型說明符*”表示把返回值強(qiáng)制轉(zhuǎn)換為該類型指針。size是一個(gè)無符號(hào)數(shù)。例如:pc=(char*)malloc(100);表示分配100個(gè)字節(jié)的內(nèi)存空間,并強(qiáng)制轉(zhuǎn)換為字符數(shù)組類型,函數(shù)的返回值為指向該字符數(shù)組的首指針,把該指針賦予指針變量pc。(2)分配內(nèi)存空間函數(shù)calloc。函數(shù)原型:(類型說明符*)calloc(n,size);功能:calloc也用于分配內(nèi)存空間,在內(nèi)存動(dòng)態(tài)存儲(chǔ)區(qū)中分配n塊長(zhǎng)度為size字節(jié)的連續(xù)區(qū)域。函數(shù)的返回值為該區(qū)域的首地址。“(類型說明符*)”用于強(qiáng)制類型轉(zhuǎn)換。calloc函數(shù)與malloc函數(shù)的區(qū)別僅在于一次可以分配n塊區(qū)域。例如:ps=(structstu*)calloc(2,sizeof(structstu));其中,sizeof(structstu)是求stu的結(jié)構(gòu)長(zhǎng)度。該語(yǔ)句的意思是:按stu的長(zhǎng)度分配2塊連續(xù)區(qū)域,強(qiáng)制轉(zhuǎn)換為stu類型,并把其首地址賦予指針變量ps。(3)釋放內(nèi)存空間函數(shù)free。函數(shù)原型:free(void*ptr);功能:釋放ptr所指向的一塊內(nèi)存空間,ptr是一個(gè)任意類型的指針變量,它指向被釋放區(qū)域的首地址。被釋放區(qū)域應(yīng)是由malloc或calloc函數(shù)所分配的區(qū)域。【例9.11】分配一塊區(qū)域,輸入一個(gè)學(xué)生數(shù)據(jù)。#include"stdlib.h"#include"stdio.h"main(){structstu{intnum;char*name;floatscore;}*ps;ps=(structstu*)malloc(sizeof(structstu));ps->num=102;ps->name="Zhangping";ps->score=62.5;printf("Number=%d\nName=%s\n",ps->num,ps->name);printf("Score=%f\n",ps->score);free(ps);}9.5.3建立和輸出鏈表所謂動(dòng)態(tài)建立鏈表是指程序執(zhí)行過程中從無到有地建立鏈表,將一個(gè)一個(gè)新生成的結(jié)點(diǎn)順次連接入已建立的鏈表上,上一個(gè)結(jié)點(diǎn)的指針域存放下一個(gè)結(jié)點(diǎn)的起始地址,并給各結(jié)點(diǎn)的數(shù)據(jù)域賦值。所謂輸出鏈表是將鏈表上各結(jié)點(diǎn)的數(shù)據(jù)域中的值依次輸出,直到鏈表的結(jié)束NULL?!纠?.12】以3個(gè)結(jié)構(gòu)體變量為結(jié)點(diǎn)建立一個(gè)簡(jiǎn)單的鏈表并輸出。#include"stdio.h"structnode{intdata;structnode*next;};voidmain(){structnodea,b,c,*head,*p;head=&a;/*頭結(jié)點(diǎn)指向a的結(jié)點(diǎn)*/a.data=5;a.next=&b;/*a結(jié)點(diǎn)指向b結(jié)點(diǎn)*/b.data=10;b.next=&c;/*b結(jié)點(diǎn)指向c結(jié)點(diǎn)*/c.data=15;c.next=NULL;/*c結(jié)點(diǎn)指向尾結(jié)點(diǎn)NULL*/p=head;/*使p指向a結(jié)點(diǎn)*/while(p!=NULL){printf("%d-->",p->data);/*輸出指針p所指向結(jié)點(diǎn)的數(shù)據(jù)*/p=p->next;/*使p指向下一個(gè)結(jié)點(diǎn)*/}printf("NULL\n");}程序的輸出結(jié)果:5-->10-->15-->NULL9.5.3鏈表的基本操作鏈表的基本操作包括,建立并初始化鏈表,遍歷訪問鏈表(包括查找結(jié)點(diǎn),輸出結(jié)點(diǎn)等),刪除鏈表中的結(jié)點(diǎn),在鏈表中插入結(jié)點(diǎn)。鏈表的各種基本操作的步驟如下:1.建立鏈表①建立頭結(jié)點(diǎn)(或定義頭指針變量);②讀取數(shù)據(jù);③生成新結(jié)點(diǎn);④將數(shù)據(jù)存入節(jié)點(diǎn)的數(shù)據(jù)域中;⑤將新結(jié)點(diǎn)連接到鏈表中(將新結(jié)點(diǎn)地址賦給上一個(gè)結(jié)點(diǎn)的指針域連接到鏈表);⑥重復(fù)步驟②~⑤,直到尾結(jié)點(diǎn)NULL為止。2.遍歷訪問鏈表輸出鏈表即順序訪問鏈表中各結(jié)點(diǎn)的數(shù)據(jù)域,方法是:從頭結(jié)點(diǎn)開始,不斷地讀取數(shù)據(jù)和下移指針變量,直到尾結(jié)點(diǎn)為止?!纠?.13】建立并輸出一個(gè)學(xué)生的成績(jī)表(假設(shè)學(xué)生成績(jī)表中只含姓名和成績(jī))。#include<stdio.h>#include<malloc.h>typedefstructstudent{charname[20];intscore;structstudent*next;}ST,*STU;STUcreatelink(intn){inti;STUp,q,head;if(n<=0)return(NULL);head=(STU)malloc(sizeof(ST));printf("inputdatas:\n");scanf("%s%d",head->name,&head->score);p=head;for(i=1;i<n;i++){q=(STU)malloc(sizeof(ST));scanf("%s%d",q->name,&q->score);p->next=q;p=q;}p->next=NULL;return(head);}

voidlist(STUhead){STUp=head;while(p!=NULL){printf("%s\t%d\n",p->name,p->score);p=p->next;}}voidmain(){STUh;intn;printf("inputnumberofnode:");scanf("%d",&n);h=createlink(n);list(n);}程序運(yùn)行結(jié)果:inputnumberofnode:4↙inputdatas:A60↙B70↙C80↙D90↙A60B70C80D903.在鏈表的某結(jié)點(diǎn)前插入一個(gè)結(jié)點(diǎn)①開辟一個(gè)新結(jié)點(diǎn)并將數(shù)據(jù)存入該結(jié)點(diǎn)的數(shù)據(jù)域;②找到插入點(diǎn)結(jié)點(diǎn);③將新結(jié)點(diǎn)插入到鏈表中,將新結(jié)點(diǎn)的地址賦值給插入點(diǎn)上一個(gè)結(jié)點(diǎn)的指針域,并將插入點(diǎn)的地址存入新結(jié)點(diǎn)的指針域?!纠?.17】編寫一個(gè)函數(shù),在例9.16中建立的鏈表的前面插入一個(gè)結(jié)點(diǎn)。#include<stdio.h>#include<malloc.h>typedefstructstudent{charname[20];intscore;structstudent*next;}ST,*STU;STUcreatelink(intn){inti;STUp,q,head;if(n<=0)return(NULL);head=(STU)malloc(sizeof(ST));printf("inputdatas:\n");scanf("%s%d",head->name,&head->score);p=head;for(i=1;i<n;i++){q=(STU)malloc(sizeof(ST));scanf("%s%d",q->name,&q->score);p->next=q;p=q;}p->next=NULL;return(head);}

voidlist(STUhead){STUp=head;while(p!=NULL){printf("%s\t%d\n",p->name,p->score);p=p->next;}}STUincreasenodel(STUhead){STUs;s=(STU)malloc(sizeof(ST));printf("inputnewnodedatas:");scanf("%s%d",s->name,&s->score);s->next=head;head=s;return(head);}voidmain(){STUh;intn;printf("inputnumberofnode:");scanf("%d",&n);h=createlink(n);list(h);h=increasenodel(h);list(h);getch();}程序運(yùn)行結(jié)果:inputnumberofnode:3↙inputdatas:A60↙B70↙C80↙A60B70C80inputnewnodedatas:E100↙E100A60B70C80【例9.18】編寫一個(gè)函數(shù),在例9.16中建立的鏈表的第i個(gè)結(jié)點(diǎn)之后插入一個(gè)結(jié)點(diǎn)。#include<stdio.h>#include<malloc.h>typedefstructstudent{charname[20];intscore;structstudent*next;}ST,*STU;STUcreatelink(intn){inti;STUp,q,head;if(n<=0)return(NULL);head=(STU)malloc(sizeof(ST));printf("inputdatas:\n");scanf("%s%d",head->name,&head->score);p=head;for(i=1;i<n;i++){q=(STU)malloc(sizeof(ST));scanf("%s%d",q->name,&q->score);p->next=q;p=q;}p->next=NULL;return(head);}STUincreasenode2(STUhead,inti){STUs,p,q;intj=0;if(i<0)returnNULL;s=(STU)malloc(sizeof(ST));printf("inputnewnodedatas:");scanf("%s%d",s->name,&s->score);if(i==0){s->next=head;head=s;return(head);}q=head;while(j<i&&q!=NULL){j++;p=q;q=q->next;}if(j<i)returnNULL;p->next=s;s->next=q;return(head);}voidlist(STUhead){STUp=head;while(p!=NULL){printf("%s\t%d\n",p->name,p->score);p=p->next;}}voidmain(){STUh;intn,i;printf("inputnumberofnode:");scanf("%d",&n);h=createlink(n);list(h);printf("inputnewnodenumber:");scanf("%d",&i);h=increasenode2(h,i);list(h);getch();}程序運(yùn)行結(jié)果:inputnumberofnode:3↙inputdatas:A60↙B70↙C80↙A60B70C80inputnewnodenumber:2↙inputnewnodedatas:E100↙A60B70E100C804.刪除鏈表中的一個(gè)結(jié)點(diǎn)①找到要?jiǎng)h除結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn);②將要?jiǎng)h除結(jié)點(diǎn)的后驅(qū)結(jié)點(diǎn)的地址賦給要?jiǎng)h除結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)的指針域;③將要?jiǎng)h除節(jié)點(diǎn)的空間釋放?!纠?.19】編寫一個(gè)函數(shù),在例9.16中建立的鏈表中刪除鏈表的首結(jié)點(diǎn)函數(shù)。#include<stdio.h>#include<malloc.h>typedefstructstudent{charname[20];intscore;structstudent*next;}ST,*STU;STUcreatelink(intn){inti;STUp,q,head;if(n<=0)return(NULL);head=(STU)malloc(sizeof(ST));printf("inputdatas:\n");scanf("%s%d",head->name,&head->score);p=head;for(i=1;i<n;i++){q=(STU)malloc(sizeof(ST));scanf("%s%d",q->name,&q->score);p->next=q;p=q;}p->next=NULL;return(head);}voidlist(STUhead){STUp=head;while(p!=NULL){printf("%s\t%d\n",p->name,p->score);p=p->next;}}STUdeletenodel(STUhead){STUs;if(head!=NULL)printf("afterdeletedthefirstnode:\n");s=head;head=s->next;free(s);}voidmain(){STUh;intn;printf("inputnumberofnode:");scanf("%d",&n);h=createlink(n);list(h);h=deletenodel(h);list(h);}程序運(yùn)行結(jié)果:inputnumberofnode:4↙inputdatas:A60↙B70↙C80↙D90↙A60B70C80D90inputnewnodenumber:2↙afterdeletedthefirstnode:B70E100C80【例9.20】編寫一個(gè)函數(shù),在例9.16中建立的鏈表中刪除鏈表的第i個(gè)結(jié)點(diǎn)的函數(shù)。#include<stdio.h>#include<malloc.h>typedefstructstudent{charname[20];intscore;structstudent*next;}ST,*STU;STUcreatelink(intn){inti;STUp,q,head;if(n<=0)return(NULL);head=(STU)malloc(sizeof(ST));printf("inputdatas:\n");scanf("%s%d",head->name,&head->score);p=head;for(i=1;i<n;i++){q=(STU)malloc(sizeof(ST));scanf("%s%d",q->name,&q->score);p->next=q;p=q;}p->next=NULL;return(head);}voidlist(STUhead){STUp=head;while(p!=NULL){printf("%s\t%d\n",p->name,p->score);p=p->next;}}

STUdeletenode2(STUhead,inti){STUp,s;intj;if(i<1)returnNULL;if(i==1){if(head!=NULL){s=head;head=s->next;free(s);}return(head);}s=head->next;p=head;j=2;while(j<i&&s!=NULL){j++;p=s;s=s->next;}if(j<i)returnNULL;p->next=s->next;free(s);return(head);}voidmain(){STUh;inti,n;printf("inputnumberofnode:");scanf("%d",&n);h=createlink(n);list(h);printf("whichnodeyouwanttodelete:");scanf("%d",&i);h=deletenode2(h,i);list(h);}程序運(yùn)行結(jié)果:inputnumberofnode:4↙inputdatas:A60↙B70↙C80↙D90↙A60B70C80D90whichnodeyouwanttodelete:A60E100C809.6.1共用體的概念和定義兩種類型數(shù)據(jù)在內(nèi)存中所占的字節(jié)數(shù)不同,但要在同一地址開始存放。這種使幾個(gè)不同的類型數(shù)據(jù)共用同一段內(nèi)存的結(jié)構(gòu),稱為“共用體”類型的結(jié)構(gòu),即使用共享技術(shù),幾個(gè)變量互相共享。

例如:在學(xué)校的教師和學(xué)生中填寫以下表格:姓名、年齡、職業(yè)、單位等數(shù)據(jù)項(xiàng)的表格?!奥殬I(yè)”一項(xiàng)可分為“教師”和“學(xué)生”兩類,對(duì)“單位”一項(xiàng)學(xué)生應(yīng)填入班級(jí)編號(hào),教師應(yīng)填入某系某教研室,班級(jí)可用整型量表示,教研室只能用字符類型。要求把這兩種類型不同的數(shù)據(jù)都填入“單位”這個(gè)變量中,就必須把“單位”定義為包含整型和字符型數(shù)組這兩種類型的變量,也就是要把一個(gè)整型量、一個(gè)字符數(shù)組存放在同一個(gè)地址開始的內(nèi)存單元(“單位”這個(gè)變量)中。共用體與結(jié)構(gòu)體的不同:在結(jié)構(gòu)體中各成員有各自的內(nèi)存空間,一個(gè)結(jié)構(gòu)變量的總長(zhǎng)度是各成員長(zhǎng)度之和。而在共用體中,各成員共享一段內(nèi)存空間,一個(gè)共用體變量的長(zhǎng)度等于各成員中最長(zhǎng)的長(zhǎng)度。共用體類型的定義和共用體變量的說明之間的關(guān)系是一個(gè)共用體類型必須經(jīng)過定義之后,才能把變量說明為該共用體類型。定義共用體類型的一般形式為:union共用體名

{共用體成員表列};例如:unionperdata{intclass;charoffice[10];};定義了一個(gè)名為perdata的共用體類型,它含有兩個(gè)成員,一個(gè)為整型,成員名為class;另一個(gè)為字符數(shù)組,數(shù)組名為office。共用體變量的定義也有三種形式,說明如下:(1)先定義共用體類型,再定義共用體變量。unionperdata{intclass;charoffice[10];};unionperdataa,b;/*說明a,b為perdata類型*/(2)在定義共用體類型的同時(shí)定義共用體變量。unionperdata{intclass;charoffice[10];}a,b;(3)直接定義共用體類型的變量。union{intclass;charoffice[10];}a,b; 【例9.17】uniondata{inta;floatb;doublec;charch;}f1;structstu{inta;floatb;doublec;charch;}f2;main(){printf("%d,%d",sizeof(structstu),sizeof(uniondata));}程序運(yùn)行結(jié)果如下:15,89.6.2共用體變量的引用對(duì)共用體成員的引用一般引用形式為:共用體變量名.成員名例如,若定義了一個(gè)共用體類型:uniondata{inti;floatf;charch;}a;則可以使用以下方式引用共用體成員并賦值:a.i=5;a.f=3.25;a.ch='a';同樣,還可以定義共用體變量的指針:uniondata*p=&a;而用共用體指針變量的引用形式為:(*p).i或p->i在使用共用體類型的數(shù)據(jù)時(shí)要注意以下幾點(diǎn):(1)同一個(gè)內(nèi)存段可以用來存放幾種不同類型的成員,但在每一瞬間只能存放其中一種,而不是同時(shí)存放幾種。也就是說,每一瞬間只有一個(gè)成員起作用,其他的成員不起作用,即不是同時(shí)都起作用。(2)共用體變量中起作用的成員是最后一次存放的成員,在存入一個(gè)新的成員后,原有的成員就失去了作用。(3)共用體變量的地址和它的各成員的地址都是同一地址。(4)不能對(duì)共用體變量名賦值,也不能企圖引用變量名來得到一個(gè)值,還不能在定義共用體變量時(shí)對(duì)它初始化。(5)不能把共用體變量作為函數(shù)參數(shù),也不能使函數(shù)帶回共用體變量,但可以使用指向共用體變量的指針。(6)共用體類型可以出現(xiàn)在結(jié)構(gòu)體類型定義中,也可以定義共用體數(shù)組。反之,結(jié)構(gòu)體也可以出現(xiàn)在共用體類型定義中,數(shù)組也可以作為共用體成員?!纠?.18】設(shè)有一個(gè)教師與學(xué)生通用的表格,教師數(shù)據(jù)有姓名、年齡、職業(yè)、教研室四項(xiàng)。學(xué)生有姓名、年齡、職業(yè)、班級(jí)四項(xiàng)。編程輸入人員數(shù)據(jù),再以表格輸出。main(){struct{charname[10];intage;charjob;union{intclass;charoffice[10];}depa;}body[2];intn,i;for(i=0;i<2;i++){printf("inputname,age,jobanddepartment\n");scanf("%s%d%c",body[i].name,&body[i].age,&body[i].job);if(body[i].job=='s')scanf("%d",&body[i].depa.class);elsescanf("%s",body[i].depa.office);}

printf("name\tagejobclass/office\n");for(i=0;i<2;i++){if(body[i].job=='s')printf("%s\t%3d%3c%d\n",body[i].name,body[i].age,body[i].job,body[i].depa.class);elseprintf("%s\t%3d%3c%s\n",body[i].name,body[i].age,body[i].job,body

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論