《C語(yǔ)言程序設(shè)計(jì)》課件第8章_第1頁(yè)
《C語(yǔ)言程序設(shè)計(jì)》課件第8章_第2頁(yè)
《C語(yǔ)言程序設(shè)計(jì)》課件第8章_第3頁(yè)
《C語(yǔ)言程序設(shè)計(jì)》課件第8章_第4頁(yè)
《C語(yǔ)言程序設(shè)計(jì)》課件第8章_第5頁(yè)
已閱讀5頁(yè),還剩73頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

本節(jié)要點(diǎn)8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.1結(jié)構(gòu)體類(lèi)型-----概念例如:登記學(xué)生的信息,可能需要用到char型的姓名,int型或char型的學(xué)號(hào),int型的年齡,char型的性別,float型的成績(jī)等。又例如:對(duì)于記錄一本書(shū),需要char型的書(shū)名,char型的作者名,float型的價(jià)格等。這種新的數(shù)據(jù)類(lèi)型可以包含多項(xiàng)數(shù)據(jù),從而達(dá)到表示一個(gè)整體的目的,這種包含多個(gè)數(shù)據(jù)項(xiàng),每個(gè)數(shù)據(jù)項(xiàng)的數(shù)據(jù)類(lèi)型可能不同的變量集合稱(chēng)作結(jié)構(gòu)體(structure)。8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.1結(jié)構(gòu)體類(lèi)型-----定義格式:struct結(jié)構(gòu)體名 {

成員說(shuō)明; };語(yǔ)法規(guī)則:①struct是關(guān)鍵字,表示開(kāi)始定義結(jié)構(gòu)體類(lèi)型;②

結(jié)構(gòu)體名要遵循標(biāo)識(shí)符定義的規(guī)則;③{}大括號(hào)不能省略,多個(gè)數(shù)據(jù)項(xiàng)的定義用此大括號(hào)括起來(lái);④

成員說(shuō)明的形式類(lèi)似變量、數(shù)組或者指針等的定義,但不能為成員進(jìn)行初始化;⑤{}大括號(hào)后的分號(hào)不能省略。8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.1結(jié)構(gòu)體類(lèi)型-----定義例如: structstudent { charname[20]; //姓名 intnum; //學(xué)號(hào) floatscore; //成績(jī) };

這里student是一個(gè)結(jié)構(gòu)體名字,structstudent是自定義的數(shù)據(jù)類(lèi)型名。結(jié)構(gòu)體類(lèi)型聲明可以放在函數(shù)外,此時(shí)為全局結(jié)構(gòu)體,類(lèi)似全局變量,在它之后聲明的所有函數(shù)都可以使用;也可以放在函數(shù)內(nèi),此時(shí)為局部結(jié)構(gòu)體,類(lèi)似局部變量,只能放在該函數(shù)內(nèi)使用。8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.1結(jié)構(gòu)體類(lèi)型-----定義還可以使用關(guān)鍵字typedef給結(jié)構(gòu)體的數(shù)據(jù)類(lèi)型自定義一個(gè)簡(jiǎn)潔的名字,一般格式如下: typedefstruct結(jié)構(gòu)體名 {

成員說(shuō)明; }數(shù)據(jù)類(lèi)型名稱(chēng);語(yǔ)法規(guī)則:①typedef是關(guān)鍵字,寫(xiě)在struct關(guān)鍵字之前;②

自定義的簡(jiǎn)潔類(lèi)型名字,必須寫(xiě)在右括號(hào)之后,通常使用大寫(xiě)字符,以明顯區(qū)分結(jié)構(gòu)體名和結(jié)構(gòu)體類(lèi)型名;例如: typedefstructstudent { charname[20]; //姓名 intnum;//學(xué)號(hào) floatscore; //成績(jī) }STU;8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.2結(jié)構(gòu)體變量結(jié)構(gòu)體類(lèi)型變量的定義有以下三種方法:(1)先定義結(jié)構(gòu)體類(lèi)型再定義結(jié)構(gòu)體變量一般形式如下: struct結(jié)構(gòu)體名

結(jié)構(gòu)體變量名;語(yǔ)法規(guī)則:①

結(jié)構(gòu)體變量名要遵循標(biāo)識(shí)符命名規(guī)則;②

可以同時(shí)定義多個(gè)變量,之間用逗號(hào)分隔;③

關(guān)鍵字struct要與結(jié)構(gòu)體名一起使用,共同構(gòu)成結(jié)構(gòu)體類(lèi)型名。例如:structstudentstu1,stu2;8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.2結(jié)構(gòu)體變量(2)在定義結(jié)構(gòu)體類(lèi)型的同時(shí)定義變量一般形式如下: struct結(jié)構(gòu)體名 {

成員說(shuō)明; }結(jié)構(gòu)體變量名;語(yǔ)法規(guī)則:①

結(jié)構(gòu)體變量在結(jié)構(gòu)體類(lèi)型定義的右大括號(hào)后進(jìn)行定義,變量名要遵循標(biāo)識(shí)符命名規(guī)則;②

可以同時(shí)定義多個(gè)變量,之間用逗號(hào)分隔;③

結(jié)構(gòu)體類(lèi)型定義最后的分號(hào),改在結(jié)構(gòu)體變量名之后。例如:structstudent{charname[20];intnum;floatscore;}stu1,stu2;8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.2結(jié)構(gòu)體變量(3)直接定義結(jié)構(gòu)體變量(不指定結(jié)構(gòu)體名)一般形式如下: struct {

成員說(shuō)明; }結(jié)構(gòu)體變量名;語(yǔ)法規(guī)則:①

此種方式在定義結(jié)構(gòu)體類(lèi)型時(shí)省略了結(jié)構(gòu)體的名字,沒(méi)有完整的結(jié)構(gòu)體類(lèi)型名,被稱(chēng)為無(wú)名稱(chēng)的結(jié)構(gòu)體類(lèi)型;②

使用無(wú)名稱(chēng)的結(jié)構(gòu)體類(lèi)型定義結(jié)構(gòu)體變量,結(jié)構(gòu)體變量只能跟在右大括號(hào)后,不能在其它位置再定義此結(jié)構(gòu)體類(lèi)型的變量;③

結(jié)構(gòu)體類(lèi)型沒(méi)有名字,無(wú)法用它來(lái)聲明函數(shù)的形參類(lèi)型或者函數(shù)的返回值類(lèi)型。例如:struct{charname[20];intnum;floatscore;}stu1,stu2;8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.3結(jié)構(gòu)體變量的初始化和引用(1)結(jié)構(gòu)體類(lèi)型的字節(jié)長(zhǎng)度

結(jié)構(gòu)體變量定義之后,內(nèi)存就開(kāi)辟一段內(nèi)存空間去存儲(chǔ)結(jié)構(gòu)體變量的值,通常情況下結(jié)構(gòu)體變量所占用內(nèi)存的字節(jié)數(shù)等于所屬結(jié)構(gòu)體類(lèi)型的所有成員字節(jié)數(shù)的總和,但也有例外。【例8.1】運(yùn)行程序,查看結(jié)構(gòu)體變量占用的內(nèi)存字節(jié)數(shù)。 #include<stdio.h> structstudent { charname[20]; intnum; floatscore; };

8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.3結(jié)構(gòu)體變量的初始化和引用structtest{chara;intb;charc;};intmain(){structstudents;structtestt;printf("structstudent類(lèi)型字節(jié)數(shù):%ld\n",sizeof(structstudent));printf("structstudent類(lèi)型變量字節(jié)數(shù)%ld\n",sizeof(s));8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.3結(jié)構(gòu)體變量的初始化和引用printf("structtest類(lèi)型字節(jié)數(shù):%ld\n",sizeof(structtest));printf("structtest類(lèi)型變量字節(jié)數(shù):%ld\n",sizeof(t));return0;}程序運(yùn)行結(jié)果如右圖所示

structstudent類(lèi)型的三個(gè)成員name、num和score的字節(jié)數(shù)加起來(lái)正好是28,與程序運(yùn)行結(jié)果一致。

但structtest類(lèi)型的三個(gè)成員a、b和c的字節(jié)數(shù)加起來(lái)是6,但程序運(yùn)行結(jié)果卻是12。這是因?yàn)橐韵聝蓚€(gè)原因:

結(jié)構(gòu)體變量的首地址的字節(jié)數(shù)要能夠被其最寬基本類(lèi)型成員的大小所整除;

結(jié)構(gòu)體的總大小為結(jié)構(gòu)體最寬基本類(lèi)型成員大小的整數(shù)倍,如有需要編譯器會(huì)在最末一個(gè)成員之后加上填充字節(jié)。8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.3結(jié)構(gòu)體變量的初始化和引用

例8.1中的structtest結(jié)構(gòu)體類(lèi)型,其最寬字節(jié)數(shù)的成員為整型的a,占4個(gè)字節(jié)。在存儲(chǔ)的時(shí)候,結(jié)構(gòu)體的首地址必須能夠被其中最寬數(shù)據(jù)類(lèi)型字節(jié)數(shù)整除,參照原因①,第一個(gè)成員是char類(lèi)型,占1個(gè)字節(jié),所以要在char后面填充3個(gè)字節(jié),然后再存儲(chǔ)下一個(gè)成員;最后一個(gè)成員也是char類(lèi)型,占1個(gè)字節(jié),參照原因②,結(jié)構(gòu)體的總大小為最寬數(shù)據(jù)類(lèi)型的整數(shù)倍,所以會(huì)在第二個(gè)char之后再填充3個(gè)字節(jié),加起來(lái)總和即為12個(gè)字節(jié)。但若將structtest結(jié)構(gòu)體類(lèi)型的成員聲明順序,做如下修改,其所占用的字節(jié)數(shù)就為8,內(nèi)存的利用率立即提升了33%。8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.3結(jié)構(gòu)體變量的初始化和引用

structtest { intb; chara;charc; };

因此,定義結(jié)構(gòu)體類(lèi)型,組織其數(shù)據(jù)成員的時(shí)候,可以將相同類(lèi)型的成員放在一起,這樣就減少了編譯器為了對(duì)齊而添加的填充字節(jié)數(shù),從而更加有效地利用內(nèi)存。(2)結(jié)構(gòu)體成員訪問(wèn)運(yùn)算符

每個(gè)結(jié)構(gòu)體變量,各自占用獨(dú)立的內(nèi)存空間,每個(gè)變量都有自己的成員數(shù)據(jù),可以使用結(jié)構(gòu)體成員訪問(wèn)運(yùn)算符“.”來(lái)訪問(wèn)屬于自己的成員,其一般格式如下:

結(jié)構(gòu)體變量.成員名;8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.3結(jié)構(gòu)體變量的初始化和引用例如: structstudent { charname[20]; intnum; floatscore; }s1,s2; strcpy(,"張三"); s1.num=10001; s1.score=95.5f;

如果成員名是一個(gè)變量名,那么引用的就是這個(gè)變量的內(nèi)容;如果成員名是一個(gè)數(shù)組名,那么引用的就是這個(gè)數(shù)組的首地址。8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.3結(jié)構(gòu)體變量的初始化和引用(3)結(jié)構(gòu)體變量的初始化1)定義的同時(shí)直接初始化語(yǔ)法規(guī)則:①

在定義變量的同時(shí),使用{}將初始值對(duì)應(yīng)的賦給每一個(gè)成員,每個(gè)初始值用逗號(hào)分隔;②

賦值時(shí)數(shù)據(jù)類(lèi)型要與成員的類(lèi)型匹配,同字符、字符數(shù)組的初始化一樣,如果是字符就用單引號(hào)括起來(lái),如果是字符串就用雙引號(hào)括起來(lái);③

初始值必須是常量,不可以是變量;④

初始值的數(shù)量可以少于成員的數(shù)量,未賦值的成員的初始值用0來(lái)代替。8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.3結(jié)構(gòu)體變量的初始化和引用例如: structstudent { charname[20]; intnum; floatscore; } structstudentstu1={"王五",152648512,80f};

相當(dāng)于成員name的值是"王五",成員num的值是152648512,成員score的值是80f。

8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.3結(jié)構(gòu)體變量的初始化和引用2)先定義結(jié)構(gòu)體變量,需要時(shí)再初始化。此時(shí),只能使用結(jié)構(gòu)體變量訪問(wèn)單獨(dú)訪問(wèn)成員進(jìn)行賦值。語(yǔ)法規(guī)則:①

需要使用哪個(gè)成員,就給哪個(gè)成員賦初值即可;②

未賦值的成員的初始值用0來(lái)代替,指針成員的值為NULL;③

初始值的類(lèi)型要跟成員的類(lèi)型保持一致。

例如: structtest { intb; chara; charc; }t; … t.b=25; t.a='A'; t.c='B';8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.3結(jié)構(gòu)體變量的初始化和引用(4)結(jié)構(gòu)體變量的引用

使用“.”運(yùn)算符對(duì)成員進(jìn)行引用在引用結(jié)構(gòu)體變量及其成員時(shí),應(yīng)注意以下幾點(diǎn):①C語(yǔ)言中不允許對(duì)結(jié)構(gòu)體變量整體進(jìn)行輸入和輸出的,對(duì)結(jié)構(gòu)體變量的操作都是對(duì)結(jié)構(gòu)體變量成員進(jìn)行操作的。是個(gè)體關(guān)系,不能整體操作。②

如果成員本身就是屬于一個(gè)結(jié)構(gòu)體類(lèi)型的話,那么此時(shí)就繼續(xù)用若干個(gè)“.”運(yùn)算符號(hào),一級(jí)一級(jí)地訪問(wèn),直到訪問(wèn)到最底一層的成員,如:class.student.age=20;。③

結(jié)構(gòu)體變量可以作為函數(shù)的參數(shù),也可以作為函數(shù)的返回值。當(dāng)函數(shù)的形參與實(shí)參為結(jié)構(gòu)體變量時(shí),這種傳遞參數(shù)的方式屬于值傳遞方式,即形參的變化不影響實(shí)參。如果用結(jié)構(gòu)體變量的指針做參數(shù),則可直接對(duì)實(shí)參的結(jié)構(gòu)體變量進(jìn)行修改。8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.3結(jié)構(gòu)體變量的初始化和引用【例8.2】輸入兩個(gè)學(xué)生的學(xué)號(hào)、姓名和成績(jī),輸出成績(jī)較高的學(xué)生的學(xué)號(hào)、姓名和成績(jī)。#include<stdio.h>intmain(){structstudent{intnum;charname[20];floatscore;}s1,s2;printf("請(qǐng)輸入第一位學(xué)生的學(xué)號(hào)、姓名和成績(jī):");scanf("%d%s%f",&s1.num,,&s1.score);printf("請(qǐng)輸入第一位學(xué)生的學(xué)號(hào)、姓名和成績(jī):");scant("%d%s%f",&s2.num,,&s2.score);8.1結(jié)構(gòu)體類(lèi)型和結(jié)構(gòu)體變量8.1.3結(jié)構(gòu)體變量的初始化和引用printf("最高成績(jī)是:\n");if(s1.score>s2.score)printf("%d%s%6.2f\n",s1.num,,s1.score);elseif(s1.score<s2.score)printf("%d%s%6.2f\n",s2.num,,s2.score);else{printf("%d%s%6.2f\n",s1.num,,s1.score);printf("%d%s%6.2f\n",s2.num,,s2.score);}return0;}

程序的運(yùn)行結(jié)果如右圖所示。

8.2結(jié)構(gòu)體數(shù)組及其應(yīng)用(1)結(jié)構(gòu)體數(shù)組的定義結(jié)構(gòu)體數(shù)組與其它數(shù)據(jù)類(lèi)型的數(shù)組的定義形式一樣,只是數(shù)據(jù)類(lèi)型不同,例如:

structstudent { intnum; charname[20]; charsex; intage; floatscore; charaddr[30]; }; structstudentstud[2];

上述定義了一個(gè)名為stud的,長(zhǎng)度為2的結(jié)構(gòu)體數(shù)組,數(shù)組有2個(gè)元素,每個(gè)元素都為structstudent類(lèi)型的數(shù)據(jù)。8.2結(jié)構(gòu)體數(shù)組及其應(yīng)用(2)結(jié)構(gòu)體數(shù)組初始化

將每個(gè)元素的成員值用花括號(hào)括起來(lái),再將數(shù)組的全部元素值用一對(duì)花括號(hào)括起來(lái)。每個(gè)元素的初始化規(guī)則與結(jié)構(gòu)體變量的初始化規(guī)則相同。例如: structstudent { intnum; charname[20]; charsex; intage; floatscore; charaddr[30]; }stud[2]={{80360,"zhangsan",'F',19,80,"35shandongRoad"}, {80361,"wanger",'F',19,90,"101shandongRoad"}};8.2結(jié)構(gòu)體數(shù)組及其應(yīng)用②

在一個(gè)花括號(hào)內(nèi)一次列出各個(gè)元素的成員值,此時(shí)需要注意{}內(nèi)值的數(shù)量。例如: structstudent { intnum;[20]; charsex; intage; floatscore; charaddr[30]; }stud[2]={80360,"zhangsan",'F',19,80,"35shandongRoad", 80361,"wanger",'F',19,90,"101shandongRoad"};8.2結(jié)構(gòu)體數(shù)組及其應(yīng)用【例8.3】有n個(gè)學(xué)生的信息(包括學(xué)號(hào)、姓名、成績(jī)),要求按照成績(jī)的高低順序輸出各學(xué)生的信息。 #include<stdio.h> structstudent { intnum; charname[20]; floatscore; }; intmain() { structstudentstu[5]={ {86110,"zhang",78}, {86112,"wang",96.5},

8.2結(jié)構(gòu)體數(shù)組及其應(yīng)用

{86114,"li",85}, {86116,"zhao",72.5}, {86118,"sun",99.5}}; structstudenttemp; constintn=5; inti,j,k; for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) if(stu[j].score>stu[k].score) k=j; if(k!=i) {

8.2結(jié)構(gòu)體數(shù)組及其應(yīng)用

temp=stu[k]; stu[k]=stu[i]; stu[i]=temp; } } for(i=0;i<n;i++) printf("%6d%8s%6.2f\n",stu[i].num,stu[i].name,stu[i].score); return0; }程序運(yùn)行結(jié)果如下圖8.3所示:8.3指向結(jié)構(gòu)體的指針(1)結(jié)構(gòu)體指針變量的定義

結(jié)構(gòu)體指針變量就是指向結(jié)構(gòu)體變量的指針變量??梢允褂媒Y(jié)構(gòu)體指針變量間接訪問(wèn)結(jié)構(gòu)體變量,結(jié)構(gòu)體指針變量的值就是所指向的結(jié)構(gòu)體變量的首地址。結(jié)構(gòu)體指針變量定義的一般形式為: struct結(jié)構(gòu)體名稱(chēng)*結(jié)構(gòu)體指針名稱(chēng);

例如:structstudent*pt;(2)結(jié)構(gòu)體指針變量的初始化

結(jié)構(gòu)體指針變量也必須先賦值后使用。賦值就是把結(jié)構(gòu)體變量的地址賦給該指針變量,例如:structstudentstu;structstudent*pstu=&stu。8.3指向結(jié)構(gòu)體的指針(3)結(jié)構(gòu)體指針變量調(diào)用成員

結(jié)構(gòu)體指針變量初始化后,就能更方便地訪問(wèn)結(jié)構(gòu)體變量的各個(gè)成員,調(diào)用時(shí)使“.”或者“->”運(yùn)算符,其訪問(wèn)成員項(xiàng)的一般形式為: (*結(jié)構(gòu)體指針變量).成員名

或:

結(jié)構(gòu)體指針變量->成員名

例如:(*pstu).num或pstu->num

因?yàn)槌蓡T運(yùn)算符“.”的優(yōu)先級(jí)高于間接尋址元素運(yùn)算符“*”,所以(*pstu)兩側(cè)的括號(hào)不可以少。【例8.4】通過(guò)指向結(jié)構(gòu)體變量的指針變量輸出結(jié)構(gòu)體變量中成員的信息。 #include<stdio.h> #include<string.h> intmain() {8.3指向結(jié)構(gòu)體的指針

structstudent { longnum; floatscore; charname[20]; charsex; }; structstudents; structstudent*p; p=&s; s.num=80631; strcpy(,"Lihua"); s.sex='M'; s.score=86.5;

8.3指向結(jié)構(gòu)體的指針

printf("學(xué)號(hào)\t姓名\t性別\t成績(jī)\n");

printf("%ld\t%s\t%c\t%5.1f\n",s.num,,s.sex,s.score); printf("%ld\t%s\t%c\t%5.1f\n", (*p).num,(*p).name,(*p).sex,(*p).score); printf("%ld\t%s\t%c\t%5.1f\n", p->num,p->name,p->sex,p->score); return0; }程序運(yùn)行結(jié)果如下圖所示:8.3指向結(jié)構(gòu)體的指針(4)結(jié)構(gòu)體變量做函數(shù)的參數(shù)

用結(jié)構(gòu)體變量的成員作參數(shù)。

例如,用類(lèi)似stu.num的結(jié)構(gòu)體變量的成員作函數(shù)實(shí)參,將實(shí)參值傳遞給形參。用法與用普通變量作實(shí)參是一樣的,屬于“值傳遞”方式。應(yīng)當(dāng)注意實(shí)參與形參的類(lèi)型保持一致。

用結(jié)構(gòu)體變量作實(shí)參

用結(jié)構(gòu)體變量作實(shí)參時(shí),采取的也是“值傳遞”的方式,將結(jié)構(gòu)體變量所占的內(nèi)存單元的內(nèi)容全部按順序傳遞給形參,形參也必須使用同類(lèi)型的結(jié)構(gòu)體變量。在函數(shù)調(diào)用期間形參也要占用內(nèi)存單元。由于采用值傳遞的方式,如果在執(zhí)行被調(diào)用函數(shù)期間改變了形參(也是結(jié)構(gòu)體變量)的值,該值不能返回主調(diào)函數(shù),這往往造成使用上的不便,因此很少用這種方法。8.3指向結(jié)構(gòu)體的指針

用指向結(jié)構(gòu)體變量(或數(shù)組元素)的指針作實(shí)參

將結(jié)構(gòu)體變量或結(jié)構(gòu)體數(shù)組元素的地址傳給實(shí)參,形參是結(jié)構(gòu)體指針,這種傳遞方式是地址傳遞,這種傳遞方式在實(shí)際應(yīng)用中使用頻率較高。

【例8.5】計(jì)算一年后程序員的工資。 #include<stdio.h> structcoder { intsalary;//薪水 intexperience;//經(jīng)驗(yàn) chartype[15];//崗位 }; voidoneYearLater(structcoder*p); intmain()8.3指向結(jié)構(gòu)體的指針

{ structcoderc={15000,3,"Java"}; printf("崗位:%s\n當(dāng)前薪資:%-5d\n當(dāng)前經(jīng)驗(yàn):%d年 \n",c.type,c.salary,c.experience); oneYearLater(&c); printf("------------------一年后---------------------\n"); printf("崗位:%s\n當(dāng)前薪資:%-5d\n當(dāng)前經(jīng)驗(yàn):%d年 \n",c.type,c.salary,c.experience); return0; } //一年后 voidoneYearLater(structcoder*p) {

8.3指向結(jié)構(gòu)體的指針 p->salary=p->salary*1.1; p->experience++; }程序運(yùn)行結(jié)果如右圖所示:

函數(shù)調(diào)用語(yǔ)句oneYearLater(&c);傳遞的是結(jié)構(gòu)體變量c的地址,傳遞給oneYearLater()函數(shù)的形參p,p是結(jié)構(gòu)體指針變量。因?yàn)槭堑刂穫鬟f,因此在oneYearLater()函數(shù)體內(nèi),修改了成員salary和experience的值后,實(shí)參c的值會(huì)同時(shí)被更改。此種傳遞方式,因?yàn)樾螀⑹墙Y(jié)構(gòu)體指針形式,只占用4個(gè)字節(jié)的內(nèi)存,相較于形參是結(jié)構(gòu)體變量的形式,有效地提升了內(nèi)存使用率。8.4簡(jiǎn)單鏈表操作8.4.1鏈表概述(1)動(dòng)態(tài)分配內(nèi)存空間①分配內(nèi)存空間函數(shù)malloc():函數(shù)原型:void*malloc(unsignedintsize);函數(shù)功能:在內(nèi)存的動(dòng)態(tài)存儲(chǔ)區(qū)中分配一塊長(zhǎng)度為size字節(jié)的連續(xù)區(qū)域;函數(shù)參數(shù):size表示要申請(qǐng)的內(nèi)存空間字節(jié)數(shù);函數(shù)返回值:void型指針。返回的是申請(qǐng)到的內(nèi)存空間的首地址。例如:char*pc=(char*)malloc(100);②分配內(nèi)存空間函數(shù)calloc()函數(shù)原型:void*calloc(unsignedintn,unsignedintsize);函數(shù)功能:在內(nèi)存的動(dòng)態(tài)存儲(chǔ)區(qū)中分配n塊長(zhǎng)度為size字節(jié)的連續(xù)區(qū)域;函數(shù)參數(shù):n表示要申請(qǐng)的內(nèi)存塊的個(gè)數(shù),size表示每個(gè)內(nèi)存塊的字節(jié)數(shù);函數(shù)返回值:void型指針。8.4簡(jiǎn)單鏈表操作8.4.1鏈表概述例如:structstu*ps=(structstu*)calloc(2,sizeof(structstu));③釋放內(nèi)存空間函數(shù)free()函數(shù)原型:voidfree(void*ptr);函數(shù)功能:釋放ptr所指向的內(nèi)存空間;函數(shù)參數(shù):ptr是一個(gè)任意類(lèi)型的指針變量,它指向被釋放區(qū)域的首地址。該指針變量是由malloc()函數(shù)或者calloc()函數(shù)生成的。8.4簡(jiǎn)單鏈表操作8.4.1鏈表概述(2)鏈表的概念

數(shù)組屬于靜態(tài)內(nèi)存分配,特點(diǎn)是邏輯關(guān)系上相鄰的兩個(gè)元素在物理存儲(chǔ)的位置上也相鄰;數(shù)組的優(yōu)點(diǎn)是可以隨機(jī)存取表中任一元素,方便快捷;缺點(diǎn)是在插入或刪除某一元素時(shí),需要移動(dòng)大量元素并可能造成內(nèi)存空間的浪費(fèi),鏈表則能很好地解決數(shù)組的這個(gè)缺點(diǎn)。

鏈表是一種物理存儲(chǔ)單元上非連續(xù)、非順序的存儲(chǔ)結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過(guò)鏈表中的指針鏈接次序?qū)崿F(xiàn)的。鏈表由一系列節(jié)點(diǎn)(鏈表中每一個(gè)元素稱(chēng)為節(jié)點(diǎn))組成,節(jié)點(diǎn)可以在運(yùn)行時(shí)動(dòng)態(tài)生成。每個(gè)節(jié)點(diǎn)包括一個(gè)存儲(chǔ)數(shù)據(jù)元素的數(shù)據(jù)域和一個(gè)存儲(chǔ)下一個(gè)節(jié)點(diǎn)地址的指針域。

使用鏈表結(jié)構(gòu)可以較好的克服數(shù)組需要預(yù)先知道數(shù)據(jù)大小的缺點(diǎn),鏈表結(jié)構(gòu)可以充分利用內(nèi)存空間,實(shí)現(xiàn)靈活的內(nèi)存動(dòng)態(tài)管理。但是鏈表失去了數(shù)組通過(guò)下標(biāo)隨機(jī)讀取的優(yōu)點(diǎn),同時(shí)鏈表由于增加了節(jié)點(diǎn)的指針域,空間開(kāi)銷(xiāo)也比較大。

鏈表有很多種不同的類(lèi)型:?jiǎn)蜗蜴湵?,雙向鏈表以及循環(huán)鏈表8.4簡(jiǎn)單鏈表操作8.4.1鏈表概述(2)鏈表的概念一個(gè)鏈表主要由若干節(jié)點(diǎn)組成,每個(gè)節(jié)點(diǎn)包括數(shù)據(jù)域和地址域兩部分。形式如下:structnode{ 數(shù)據(jù)成員的定義;//數(shù)據(jù)域,可以是多個(gè)成員

structnode*next;//地址域};鏈表的示意圖如下圖所示:8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作(1)建立簡(jiǎn)單的靜態(tài)鏈表建立鏈表就是鏈表從無(wú)到有的過(guò)程,例8.6建立了一個(gè)有三個(gè)固定節(jié)點(diǎn)的鏈表?!纠?.6】建立一個(gè)簡(jiǎn)單鏈表,它由3個(gè)學(xué)生數(shù)據(jù)的節(jié)點(diǎn)組成,要求輸出各節(jié)點(diǎn)中的數(shù)據(jù)。#include<stdio.h>structstudent{intnum;floatscore;structstudent*next;};

intmain(){ structstudenta,b,c; structstudent*head,*p;8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作 a.num=80630; a.score=87.0f; b.num=80632; b.score=97.5f; c.num=80635; c.score=67.5f; head=&a; a.next=&b; b.next=&c; c.next=NULL; p=head; while(p!=NULL){ printf("學(xué)號(hào):%d\t成績(jī):%.1f\n",p->num,p->score); p=p->next; } return0;}

8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作程序運(yùn)行結(jié)果如下圖所示:鏈表結(jié)構(gòu)示意圖如下圖所示:

上圖是一個(gè)具有3個(gè)固定節(jié)點(diǎn)的鏈表,通常情況下,鏈表的節(jié)點(diǎn)數(shù)都是未知的,因此就需要程序具有能夠動(dòng)態(tài)創(chuàng)建節(jié)點(diǎn)的能力。8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作(2)動(dòng)態(tài)鏈表的建立【例8.7】動(dòng)態(tài)創(chuàng)建一個(gè)鏈表,鏈表包含n個(gè)節(jié)點(diǎn),節(jié)點(diǎn)數(shù)據(jù)從鍵盤(pán)輸入。#include<stdio.h>#include<stdlib.h>structnode{intnum;floatscore;structnode*next;};intmain(){intn;structnode*head=NULL,*p1,*p2;printf("請(qǐng)輸入節(jié)點(diǎn)的個(gè)數(shù):");scanf("%d",&n);

8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作

for(inti=1;i<=n;i++)

{printf("請(qǐng)輸入第%d個(gè)節(jié)點(diǎn)的數(shù)據(jù):",i);p1=(structnode*)malloc(sizeof(structnode));scanf("%d%f",&p1->num,&p1->score);

if(i==1)head=p1;elsep2->next=p1;p2=p1;}p2->next=NULL;if(head!=NULL){p1=head;while(p1!=NULL)

{printf("學(xué)號(hào):%d\t成績(jī):%.1f\n",p1->num,p1->score);8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作p1=p1->next;}}elseprintf("此鏈表為空");return0;}程序運(yùn)行結(jié)果如下圖所示:8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作(2)動(dòng)態(tài)鏈表的建立【例8.8】將例8.7的創(chuàng)建鏈表的過(guò)程封裝成一個(gè)函數(shù),打印鏈表的過(guò)程封裝成一個(gè)函數(shù),最后編寫(xiě)main()函數(shù)調(diào)用創(chuàng)建和打印函數(shù),完成跟例題8.7一樣的操作。#include<stdio.h>#include<stdlib.h>typedefstructnode{intnum;floatscore;structnode*next;}NODE;NODE*create(intn);voidprint(NODE*head);

intmain(){intn;structnode*head=NULL;8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作

printf("請(qǐng)輸入節(jié)點(diǎn)的個(gè)數(shù):");

scanf("%d",&n);head=create(n);print(head);return0;}NODE*create(intn)

{NODE*head=NULL,*p1,*p2;for(inti=1;i<=n;i++){printf("請(qǐng)輸入第%d個(gè)節(jié)點(diǎn)的數(shù)據(jù):",i);p1=(structnode*)malloc(sizeof(NODE));

scanf("%d%f",&p1->num,&p1->score);if(i==1)head=p1;elsep2->next=p1;8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作p2=p1;}

p2->next=NULL;returnhead;}voidprint(NODE*head){NODE*p1;if(head!=NULL){p1=head;while(p1!=NULL)

{printf("學(xué)號(hào):%d\t成績(jī):%.1f\n",p1->num,p1->score);p1=p1->next;}}elseprintf("此鏈表為空");}8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作(3)動(dòng)態(tài)鏈表的排序建立

【例8.9】編寫(xiě)一個(gè)insert()函數(shù),完成將一個(gè)節(jié)點(diǎn)按學(xué)號(hào)大小順序插入到鏈表的功能。NODE*insert(NODE*head,NODE*newnode){NODE*p0=newnode,*p1=head,*p2=NULL;if(head==NULL){head=newnode;newnode->next=NULL;}else

{while((p0->num>p1->num)&&(p1->next!=NULL)){

p2=p1;

p1=p1->next;}8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作

if(p0->num<p1->num)

{if(head==p1)head=p0;elsep2->next=p0;p0->next=p1;}

else{p1->next=p0;p0->next=NULL;}}returnhead;}8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作(4)刪除節(jié)點(diǎn)【例8.10】編寫(xiě)一個(gè)del()函數(shù),完成將一個(gè)指定學(xué)號(hào)的節(jié)點(diǎn)從鏈表中刪除的功能。NODE*del(NODE*head,intdelnum){NODE*p1=head,*p2=NULL;if(head==NULL)printf("鏈表為空,不存在此節(jié)點(diǎn)!\n");else{while((delnum!=p1->num)&&(p1->next!=NULL)){p2=p1;p1=p1->next;}8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作

if(delnum==p1->num){if(head==p1)head=p1->next;elsep2->next=p1->next;free(p1);}elseprintf("不存在此節(jié)點(diǎn)!\n");}returnhead;}8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作(5)查詢(xún)節(jié)點(diǎn)

【例8.11】編寫(xiě)一個(gè)search()函數(shù),完成查詢(xún)一個(gè)指定學(xué)號(hào)的節(jié)點(diǎn)的功能。NODE*search(NODE*head,intsearchnum){NODE*p1=NULL;if(head==NULL){printf("此鏈表為空!");returnNULL;}else

{p1=head;while(p1!=NULL)8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作{if(p1->num==searchnum)returnp1;p1=p1->next;}}returnNULL;}

函數(shù)有兩個(gè)形參,head為鏈表頭節(jié)點(diǎn)指針,searchnum為待刪節(jié)點(diǎn)的學(xué)號(hào)。首先判斷鏈表是否為空(head==NULL),為空則不可能有查詢(xún)的節(jié)點(diǎn)。若不為空,則使p1指針指向鏈表的第一個(gè)節(jié)點(diǎn),進(jìn)入while語(yǔ)句后逐個(gè)查找是否存在要查詢(xún)的節(jié)點(diǎn),有則直接返回該節(jié)點(diǎn)的地址(returnp1),直到表尾若還沒(méi)查到,則返回空。8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作(6)修改節(jié)點(diǎn)【例8.12】編寫(xiě)一個(gè)modify()函數(shù),完成修改一個(gè)某個(gè)學(xué)號(hào)的學(xué)生成績(jī)的功能。NODE*modify(NODE*head,intmodifynum,floatmodifyscore){NODE*p;p=search(head,modifynum);if(p==NULL)returnNULL;elsep->score=modifyscore;returnp;}

此函數(shù)的參數(shù)還可以將modifynum和modifyscore封裝到一個(gè)NODE類(lèi)型的變量中,將函數(shù)聲明修改為:*modify(NODE*head,NODEmodifynode);。8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作(6)修改節(jié)點(diǎn)【例8.13】編寫(xiě)一個(gè)完整程序,調(diào)用以上的創(chuàng)建、插入、刪除、查詢(xún)和修改函數(shù),完成鏈表的全部操作。#include<stdio.h>#include<stdlib.h>typedefstructnode{intnum;floatscore;structnode*next;}NODE;NODE*create(intn);voidprint(NODE*head);NODE*insert(NODE*head,NODE*newnode);NODE*del(NODE*head,intdelnum);NODE*search(NODE*head,intsearchnum);NODE*modify(NODE*head,intmodifynum,floatmodifyscore);8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作intmenu();//菜單函數(shù)intmain(){intn,choice,num;;NODE*head=NULL;//頭指針NODE*newnode=NULL;//待插入節(jié)點(diǎn)指針NODE*searchresult=NULL;//查詢(xún)到的節(jié)點(diǎn)指針NODE*modifynode=NULL;//待修改節(jié)點(diǎn)指針while(1)

{choice=menu();switch(choice){case1://創(chuàng)建鏈表printf("請(qǐng)輸入節(jié)點(diǎn)的個(gè)數(shù):");scanf("%d",&n);head=create(n);break;8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作case2://插入節(jié)點(diǎn)newnode=(NODE*)malloc(sizeof(NODE));printf("請(qǐng)輸入待插入節(jié)點(diǎn)的數(shù)據(jù):");scanf("%d%f",&newnode->num,&newnode->score);head=insert(head,newnode);break;

case3://刪除節(jié)點(diǎn)printf("請(qǐng)輸入待刪除的節(jié)點(diǎn)的學(xué)號(hào):");scanf("%d",&num);head=del(head,num);break;case4://查找節(jié)點(diǎn)printf("請(qǐng)輸入待查詢(xún)的節(jié)點(diǎn)的學(xué)號(hào):");scanf("%d",&num);searchresult=search(head,num);if(searchresult==NULL)printf("查無(wú)此人!\n");else8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作 printf("學(xué)號(hào):%d成績(jī):%f\n",searchresult->num,searchresult->score);break;case5://輸出鏈表print(head);break;case6://修改節(jié)點(diǎn)printf("請(qǐng)輸入修改節(jié)點(diǎn)的學(xué)號(hào):");scanf("%d",&num);modifynode=search(head,num);if(modifynode==NULL)printf("查無(wú)此人!\n");else{printf("成績(jī):%.1f,請(qǐng)輸入修改后的成績(jī):",modifynode->score);floattscore;chartempinput;scanf("%f",&tscore);while(1)8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作

{printf("確認(rèn)修改(y/n)?");getchar();tempinput=getchar();if(tempinput=='n'||tempinput=='N')break;elseif(tempinput=='y'||tempinput=='Y'){modifynode->score=tscore;

modifynode=modify(head,num,tscore);if(modifynode!=NULL)printf("修改成功!\n");break;}}

}break;case7:return0;8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作}}return0;}intmenu(){intchoice=0;

printf("**********************\n");printf("*1.創(chuàng)建鏈表2.插入節(jié)點(diǎn)*\n");printf("*3.刪除節(jié)點(diǎn)4.查找節(jié)點(diǎn)*\n");

printf("*5.輸出鏈表6.修改節(jié)點(diǎn)*\n");printf("*7.退出*\n");printf("**********************\n");printf("請(qǐng)選擇操作(1-7):");while(1){8.4簡(jiǎn)單鏈表操作8.4.2鏈表的基本操作scanf("%d",&choice);if(choice>7||choice<1)printf("輸入錯(cuò)誤,選擇操作(1-7):");elsebreak;}returnchoice;}程序運(yùn)行的結(jié)果示意圖如圖所示。8.5共用體8.5.1共用體類(lèi)型和共用體變量

結(jié)構(gòu)體是一種構(gòu)造類(lèi)型或復(fù)雜類(lèi)型,它可以包含多個(gè)類(lèi)型不同的成員。在C語(yǔ)言中,還有另外一種和結(jié)構(gòu)體非常類(lèi)似的構(gòu)造類(lèi)型,共用體(union),其作用是相同的內(nèi)存位置存儲(chǔ)不同的數(shù)據(jù)成員。(1)共用體類(lèi)型定義使用關(guān)鍵字union來(lái)定義共用體,定義的一般格式如下:

union共用體名

{ 成員說(shuō)明;

};8.5共用體8.5.1共用體類(lèi)型和共用體變量(1)共用體類(lèi)型定義語(yǔ)法規(guī)則:①u(mài)nion是關(guān)鍵字,表示開(kāi)始定義共用體類(lèi)型;②共用體名要遵循標(biāo)識(shí)符定義的規(guī)則;③{}大括號(hào)不能省略,多個(gè)數(shù)據(jù)成員的定義用此大括號(hào)括起來(lái);④成員說(shuō)明的形式類(lèi)似變量、數(shù)組或者指針等的定義,但不能為成員進(jìn)行初始化;⑤{}大括號(hào)后的分號(hào)不能省略。8.5共用體

(2)共用體變量的定義1)將共用體類(lèi)型與變量同時(shí)定義:union共用體名{成員說(shuō)明;}共用體變量列表;語(yǔ)法規(guī)則:①共用體變量在共用體類(lèi)型定義的右大括號(hào)}后進(jìn)行定義,變量名要遵循標(biāo)識(shí)符命名規(guī)則;②可以同時(shí)定義多個(gè)變量,之間用逗號(hào)分隔;③共用體類(lèi)型定義最后的分號(hào),改在共用體變量名之后。例如:uniondata{charc_data;inti_data;}x,y;8.5.1共用體類(lèi)型和共用體變量8.5共用體

2)先定義共用體類(lèi)型,然后定義共用體變量。共用體變量定義的一般形式如下:共用體類(lèi)型變量名;語(yǔ)法規(guī)則:①共用體變量名要遵循標(biāo)識(shí)符命名規(guī)則;②可以同時(shí)定義多個(gè)變量,之間用逗號(hào)分隔;③關(guān)鍵字union要與共用體名一起使用,共同構(gòu)成共用體類(lèi)型名。例如:uniondatax,y;即先聲明一個(gè)uniondata類(lèi)型,再將x,y定義為該類(lèi)型的變量。8.5.1共用體類(lèi)型和共用體變量8.5共用體

3)省略共用體名,語(yǔ)法形式如下:union{成員說(shuō)明;}共用體變量;語(yǔ)法規(guī)則:①此種方式在定義共用體類(lèi)型時(shí)省略了共用體的名字,沒(méi)有完整的共用體類(lèi)型名,被稱(chēng)為無(wú)名稱(chēng)的共用體類(lèi)型;②使用無(wú)名稱(chēng)的共用體類(lèi)型定義共用體變量,共用體變量只能跟在右大括號(hào)}后,不能在其它位置再定義此共用體類(lèi)型的變量;③共用體類(lèi)型沒(méi)有名字,無(wú)法用它來(lái)聲明函數(shù)的形參類(lèi)型或者函數(shù)的返回值類(lèi)型。例如:union{

charc_data;

inti_data;}x,y;8.5.1共用體類(lèi)型和共用體變量8.5共用體8.5.2引用共用體變量的方式(1)共用體變量引用該共用體成員在定義共用體變量之后,就可以引用該共用體變量的某個(gè)成員。共用體變量的引用形式:共用體變量名.成員項(xiàng);例如:uniondata{ charc_data; inti_data;}x;a.c_data='W';a.i_data=200;(2)共用體類(lèi)型的字節(jié)長(zhǎng)度共用體的各個(gè)成員是以同一個(gè)地址開(kāi)始存放的,每一個(gè)時(shí)刻只可以存儲(chǔ)一個(gè)成員,這樣就要求它在分配內(nèi)存單元時(shí)候要滿足兩點(diǎn):①通常情況下,共用體類(lèi)型實(shí)際占用存儲(chǔ)空間為其最長(zhǎng)的成員所占的存儲(chǔ)空間;②若是該最長(zhǎng)的存儲(chǔ)空間對(duì)其他成員的類(lèi)型字節(jié)數(shù)不滿足整除關(guān)系,該最大空間自動(dòng)延伸;8.5共用體8.5.2引用共用體變量的方式【例8.14】閱讀程序,分析共用體類(lèi)型占用字節(jié)數(shù)的規(guī)則。#include<stdio.h>uniontest{chara[10];//字節(jié)長(zhǎng)度10shortintn;//字節(jié)長(zhǎng)度2floatf;//字節(jié)長(zhǎng)度4}t;intmain(){printf("shortint字節(jié)數(shù):%ld\n",sizeof(shortint));printf("共用體變量t字節(jié)數(shù):%ld\n",sizeof(t));return0;}程序運(yùn)行結(jié)果如下圖所示:8.5共用體8.5.2引用共用體變量的方式【例8.15】閱讀程序,分析共用體成員之間

溫馨提示

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

評(píng)論

0/150

提交評(píng)論