C語言程序設(shè)計(第三版)_第1頁
C語言程序設(shè)計(第三版)_第2頁
C語言程序設(shè)計(第三版)_第3頁
C語言程序設(shè)計(第三版)_第4頁
C語言程序設(shè)計(第三版)_第5頁
已閱讀5頁,還剩95頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、結(jié)構(gòu)體的概念結(jié)構(gòu)體的概念結(jié)構(gòu)體的定義和引用結(jié)構(gòu)體的定義和引用結(jié)構(gòu)體數(shù)組結(jié)構(gòu)體數(shù)組 11.1 11.1 概述概述11.2 11.2 定義結(jié)構(gòu)體類型變量的方法定義結(jié)構(gòu)體類型變量的方法11.3 11.3 結(jié)構(gòu)體變量的引用結(jié)構(gòu)體變量的引用11.4 11.4 結(jié)構(gòu)體變量的初始化結(jié)構(gòu)體變量的初始化11.5 11.5 結(jié)構(gòu)體數(shù)組結(jié)構(gòu)體數(shù)組 11.11.指向結(jié)構(gòu)體類型數(shù)據(jù)的指針指向結(jié)構(gòu)體類型數(shù)據(jù)的指針 11.7 11.7 用指針處理鏈表用指針處理鏈表11.8 11.8 共用體共用體 11.9 11.9 枚舉類型枚舉類型 11.10 11.10 用用typedeftypedef定義類型定義類型n問題定義:問題定

2、義: 有時需要將不同類型的數(shù)據(jù)組合成一個有機的整體,以便于引用。如:如:一個學(xué)生有學(xué)號/姓名/性別/年齡/地址等屬性 int num; char name20; char sex; int age; int char addr30; 應(yīng)當(dāng)把它們組織成一個組合項,在一個組合項中包含若干個類型不同(當(dāng)然也可以相同)的數(shù)據(jù)項。 圖11-1100101 Li Fun M 18 87.5 Beijing Num name sex age score addrn 聲明一個結(jié)構(gòu)體類型的一般形式為:聲明一個結(jié)構(gòu)體類型的一般形式為: struct 結(jié)構(gòu)體名 成員表列;如:如:struct student int

3、 num;char name20;char sex; int age;float score;char addr30; 結(jié)構(gòu)體名類型名成員名n可以采取以下可以采取以下3 3種方法定義結(jié)構(gòu)體類型變種方法定義結(jié)構(gòu)體類型變量:量:(1)(1)先聲明結(jié)構(gòu)體類型再定義變量名先聲明結(jié)構(gòu)體類型再定義變量名例如:例如:struct student student1, student2; | | | 結(jié)構(gòu)體類型名 結(jié)構(gòu)體變量名 定義了student1和student2為struct student類型的變量,即它們具有struct student類型的結(jié)構(gòu). 圖11-2student1100101 ZhangX

4、in M 19 90.5 Shanghai100102 WangLi F 20 98 Beijingstudent2 在定義了結(jié)構(gòu)體變量后,系統(tǒng)會為之分配內(nèi)存單元。 例如例如: :student1和student2在內(nèi)存中各占59個字節(jié)(2+20+1+2+4+30=59)。 將一個變量定義為標(biāo)準(zhǔn)類型(基本數(shù)據(jù)類型)與定義為結(jié)構(gòu)體類型不同之處在于后者不僅要求指定變量為結(jié)構(gòu)體類型,而且要求指定為某一特定的結(jié)構(gòu)體類型,因為可以定義出許許多多種具體的結(jié)構(gòu)體類型。(2)(2)在聲明類型的同時定義變量在聲明類型的同時定義變量 這種形式的定義的一般形式為: structstruct結(jié)構(gòu)體名 成員表列 變量名

5、表列; 例如:例如:struct student int num; char name20; char sex; int age; float score; char addr30; student1,student2; 它的作用與第一它的作用與第一種方法相同,即種方法相同,即定義了兩個定義了兩個struct student 類型的變類型的變量量student1,student2 (3)(3) 直接定義結(jié)構(gòu)體類型變量直接定義結(jié)構(gòu)體類型變量其一般形式為: structstruct 成員表列 變量名表列;變量名表列;即不出現(xiàn)結(jié)構(gòu)體名。 (1) 類型與變量是不同的概念,不要混同。只能對變量賦值、存取

6、或運算,而不能對一個類型賦值、存取或運算。在編譯時,對類型是不分配空間的,只對變量分配空間。(2)對結(jié)構(gòu)體中的成員(即“域”),可以單獨使用,它的作用與地位相當(dāng)于普通變量。(3)成員也可以是一個結(jié)構(gòu)體變量。(4) 成員名可以與程序中的變量名相同,二者不代表同一對象。例如:例如:structstruct date date / /* *聲明一個結(jié)構(gòu)體類型聲明一個結(jié)構(gòu)體類型* */ / intint numnum; charchar name20name20; charchar sexsex; intint ageage; floatfloat scorescore; structstruct d

7、atedate birthdaybirthday; / /* *birthdaybirthday是是struct datestruct date類型類型* */ / char char addr30addr30; student1,student2;student1,student2;先聲明一個先聲明一個struct date類型,它代表類型,它代表“日期日期”,包括,包括3個成員:個成員:month(月)、(月)、day(日)、日)、year(年)。(年)。然后在聲明然后在聲明struct student類型時,將成類型時,將成員員birthday指定為指定為struct date類型。類型

8、。 圖11-3 birthday addrNum name sex age Month day yearn 在定義了結(jié)構(gòu)體變量以后,當(dāng)然可以引用這個變量。但應(yīng)遵守以下規(guī)則: (1)不能將一個結(jié)構(gòu)體變量作為一個整體進(jìn)行輸入和輸出。例如例如: 已定義student1和student2為結(jié)構(gòu)體變量并且它們已有值。printf(%d,%s,%c,%d,%f,%n,student1); 引用結(jié)構(gòu)體變量中成員的方式為結(jié)構(gòu)體變量名結(jié)構(gòu)體變量名. .成員名成員名例如,例如, student1.num表示student1變量中的num成員,即student1的num(學(xué)號)項??梢?對 變 量 的 成 員 賦

9、值 , 例 如:student1.num=10010;“.”是成員(分量)運算符,它在所有的運算符中優(yōu)先級最高,因此可以把student1.num作為一個整體來看待。上面賦值語句的作用是將整數(shù)10010賦給student1變量中的成員num。 (2) 如果成員本身又屬一個結(jié)構(gòu)體類型,則要用若干個成員運算符,一級一級地找到最低的一級的成員。只能對最低級的成員進(jìn)行賦值或存取以及運算。例如例如: : 對上面定義的結(jié)構(gòu)體變量student1, 可以這樣訪問各成員: student1.num (3) 對結(jié)構(gòu)體變量的成員可以像普通變量一樣進(jìn)行各種運算(根據(jù)其類型決定可以進(jìn)行的運算)。例如:例如: stud

10、ent2.score=student1.score; sum=student1.score+student2.score; student1.age+; +student2.age;由于由于“”運算符的運算符的優(yōu)先級最高,因此優(yōu)先級最高,因此是對是對進(jìn)行自加運算,而不進(jìn)行自加運算,而不是先對進(jìn)行自是先對進(jìn)行自加運算。加運算。(4) 可以引用結(jié)構(gòu)體變量成員的地址,也可以引用結(jié)構(gòu)體變量的地址。例如:例如: scanf(%d,&student1.num); (輸入student1.num的值) printf(%o,student1); (輸出student1的首地址)但不能用以下語句整體讀入

11、結(jié)構(gòu)體變量,例如:例如: scanf(%d,s,c,d,f,s,student1); 結(jié)構(gòu)體變量的地址主要用作函數(shù)參數(shù),結(jié)構(gòu)體變量的地址主要用作函數(shù)參數(shù),傳遞結(jié)構(gòu)體變量的地址。傳遞結(jié)構(gòu)體變量的地址。 但不能用以下語句整體讀入結(jié)構(gòu)體變量,例如:例如: scanf(%d,s,c,d,f,s,student1); 結(jié)構(gòu)體變量的地址主要用作函數(shù)參數(shù),結(jié)構(gòu)體變量的地址主要用作函數(shù)參數(shù),傳遞結(jié)構(gòu)體變量的地址。傳遞結(jié)構(gòu)體變量的地址。 運行結(jié)果:運行結(jié)果:No.:10101name:LiLinsex:address:123 Beijing Road 一個結(jié)構(gòu)體變量中可以存放一組數(shù)據(jù)(如一個學(xué)生的學(xué)號、姓名、成

12、績等數(shù)據(jù))。如果有個學(xué)生的數(shù)據(jù)需要參加運算,顯然應(yīng)該用數(shù)組,這就是結(jié)構(gòu)體數(shù)組。結(jié)構(gòu)體數(shù)組與以前介紹過的數(shù)值型數(shù)組不同之處在于每個數(shù)組元素都是一個結(jié)構(gòu)體類型的數(shù)據(jù),它們都分別包括各個成員(分量)項。 和定義結(jié)構(gòu)體變量的方法相仿,只需說明其為數(shù)組即可。例如:struct studentint num;char name20;char sex;int age; float score;char addr30; ;struct student3;struct student3; 以上定義了一個數(shù)以上定義了一個數(shù)組組stu,數(shù)組有個元,數(shù)組有個元素,均為素,均為struct student類型數(shù)據(jù)。類型

13、數(shù)據(jù)。也可以直接定義一個結(jié)構(gòu)體數(shù)組,例如例如: struct studentstruct student int num; int num; ;stu3; ;stu3;或:或: strcut studentstrcut student int num; int num; ;stu3; ;stu3;圖11-4 與其他類型的數(shù)組一樣,對結(jié)構(gòu)體數(shù)組可以初始化。例如例如:struct studentstruct studentint num;char name20; char sex; int age; float score; char addr30; ;stustu2 21010110101,Li

14、LinLiLin,MM,1818,87.587.5,103 103 BeijingRoadBeijingRoad,1010210102,Zhang Zhang FunFun,MM,1919,9999,130 130 Shanghai RoadShanghai Road; 圖11-5當(dāng)然,數(shù)組的初始化也可以用以下形式:struct student int num; ; struct studentstruct studentstr,str,; 即先聲明結(jié)構(gòu)體類型,然后定義數(shù)組為該結(jié)構(gòu)體類型,在定義數(shù)組時初始化。 結(jié)構(gòu)體數(shù)組初始化的一般形結(jié)構(gòu)體數(shù)組初始化的一般形式是在定義數(shù)組的后面加上式是在定義數(shù)

15、組的后面加上“初值表列;初值表列;”。運行結(jié)果:運行結(jié)果: : 程序定義一個全局的結(jié)構(gòu)體數(shù)組leader,它有個元素,每一個元素包含兩個成員name(姓名)和count(票數(shù))。在定義數(shù)組時使之初始化,使3位候選人的票數(shù)都先置零。 在主函數(shù)中定義字符數(shù)組leader-name,它代表被選人的姓名,在10次循環(huán)中每次先輸入一個被選人的具體人名,然后把它與3個候選人姓名相比,看它和哪一個候選人的名字相同。在輸入和統(tǒng)計結(jié)束之后,將3人的名字和得票數(shù)輸出。 圖11-6Li 0Zhang 0Fun 0 name count 一個結(jié)構(gòu)體變量的指針就是該變量所占據(jù)的內(nèi)存段的起始地址??梢栽O(shè)一個指針變量,用來

16、指向一個結(jié)構(gòu)體變量,此時該指針變量的值是結(jié)構(gòu)體變量的起始地址。指針變量也可以用來指向結(jié)構(gòu)體數(shù)組中的元素。 下面通過一個簡單例子來說明指向結(jié)構(gòu)體變量的指針變量的應(yīng)用。 定義指針變量p,指向struct student 類型的數(shù)據(jù)指向的結(jié)構(gòu)體變量中的成員 運行結(jié)果:運行結(jié)果:89101 name:LiLin sex: score:89.500000:89101 name:LiLin sex: score:89.500000程序分析: 在函數(shù)的執(zhí)行部分將結(jié)構(gòu)體變量-的起始地址賦給指針變量,也就是使指向-,然后對-的各成員賦值。第一個函數(shù)是輸出-的各個成員的值。用-表示-中的成員,依此類推。第二個函數(shù)

17、也是用來輸出-各成員的值,但使用的是(*)這樣的形式。圖11-7以下以下3 3種形式等價:種形式等價: 結(jié)構(gòu)體變量成員名(*)成員名-成員名其中-稱為指向運算符。 請分析以下幾種運算:-得到指向的結(jié)構(gòu)體變量中的成員的值。-得到指向的結(jié)構(gòu)體變量中的成員的值,用完該值后使它加。-得到指向的結(jié)構(gòu)體變量中的成員的值加,然后再使用它。運行結(jié)果:運行結(jié)果: LiLin 18 Zhang Fun 19 WangMing 20程序分析: 是指向struct student結(jié)構(gòu)體類型數(shù)據(jù)的指針變量。在for語句中先使的初值為stu,也就是數(shù)組stu第一個元素的起始地址。在第一次循環(huán)中輸出stu0的各個成員值。然

18、后執(zhí)行,使自加。加意味著p所增加的值為結(jié)構(gòu)體數(shù)組stu的一個元素所占的字節(jié)數(shù)。執(zhí)行+后p的值等于stu 1,指向stu1。在第二次循環(huán)中輸出stu1的各成員值。在執(zhí)行后,p的值等于stu+2,再輸出stu 2的各成員值。在執(zhí)行+后,的值變?yōu)閟tu +, 已不再小于stu+3了,不再執(zhí)行循環(huán)。 圖11-8注意: (1) 如果的初值為stu,即指向第一個元素,則加后p就指向下一個元素。例如例如: : (+p)-num先使自加,然后得到它指向的元素中的num成員值(即10102)。 (p+)-num先得到-num的值(即10101),然后使自加,指向stu1。 請注意以上二者的不同。 注意: (2)

19、 程序已定義了是一個指向struct student類型數(shù)據(jù)的指針變量,它用來指向一個struct student類型的數(shù)據(jù),不應(yīng)用來指向stu數(shù)組元素中的某一成員。例如例如: : 1a; 如果要將某一成員的地址賦給p,可以用強制類型轉(zhuǎn)換,先將成員的地址轉(zhuǎn)換成p的類型。例如:( *)0a; 作函數(shù)參數(shù)作函數(shù)參數(shù) 將一個結(jié)構(gòu)體變量的值傳遞給另一個函數(shù),有3個方法:n用結(jié)構(gòu)體變量的成員作參數(shù)。n(2) 用結(jié)構(gòu)體變量作實參。n(3) 用指向結(jié)構(gòu)體變量(或數(shù)組)的指針作實參,將結(jié)構(gòu)體變量(或數(shù)組)的地址傳給形參。 運行結(jié)果運行結(jié)果: 67.50000089.00000078.599998運行結(jié)果運行結(jié)

20、果: 67.50000089.00000078.599998程序分析: 此程序改用在定義結(jié)構(gòu)體變量stu時賦初值,這樣程序可簡化些。print函數(shù)中的形參被定義為指向struct student類型數(shù)據(jù)的指針變量。注意在調(diào)用print函數(shù)時,用結(jié)構(gòu)體變量str的起始地址stu作實參。在調(diào)用函數(shù)時將該地址傳送給形參p(p是指針變量)。這樣就指向stu。在print函數(shù)中輸出所指向的結(jié)構(gòu)體變量的各個成員值,它們也就是stu的成員值。main函數(shù)中的對各成員賦值也可以改用scanf函數(shù)輸入。圖11-9 鏈表是一種常見的重要的數(shù)據(jù)結(jié)構(gòu),是動態(tài)地進(jìn)行存儲分配的一種結(jié)構(gòu)。鏈表的組成:頭指針:存放一個地址,

21、該地址指向一個元素 結(jié)點:用戶需要的實際數(shù)據(jù)和鏈接節(jié)點的指針圖11-10用結(jié)構(gòu)體建立鏈表:struct student int num; float score; struct student *next ;; 其中成員num和score用來存放結(jié)點中的有用數(shù)據(jù)(用戶需要用到的數(shù)據(jù)),next是指針類型的成員,它指向struct student類型數(shù)據(jù)(這就是next所在的結(jié)構(gòu)體類型)圖11-11 運行結(jié)果:運行結(jié)果:1010189.51010390.01010785.0程序分析: 開始時使head指向a結(jié)點,a.next指向b結(jié)點,b.next指向c結(jié)點,這就構(gòu)成鏈表關(guān)系?!癱.next=N

22、ULL” 的作用是使c.next不指向任何有用的存儲單元。在輸出鏈表時要借助p,先使p指向a結(jié)點,然后輸出a結(jié)點中的數(shù)據(jù),“p=p-next” 是為輸出下一個結(jié)點作準(zhǔn)備。p-next的值是b結(jié)點的地址,因此執(zhí)行“p=p-next”后p就指向b結(jié)點,所以在下一次循環(huán)時輸出的是b結(jié)點中的數(shù)據(jù)。 庫函數(shù)提供動態(tài)地開辟和釋放存儲單元的有關(guān)函數(shù):malloc函數(shù)其函數(shù)原型為void *malloc(unsigned int size);其作用是在內(nèi)存的動態(tài)存儲區(qū)中分配一個長度為size的連續(xù)空間。此函數(shù)的值(即“返回值”)是一個指向分配域起始地址的指針(類型為void)。如果此函數(shù)未能成功地執(zhí)行(例如內(nèi)

23、存空間不足),則返回空指針(NULL)。 (2) calloc函數(shù) 其函數(shù)原型為void *calloc(unsigned ,unsigned size);其作用是在內(nèi)存的動態(tài)存儲區(qū)中分配個長度為size的連續(xù)空間。函數(shù)返回一個指向分配域起始地址的指針;如果分配不成功,返回NULL。 用calloc函數(shù)可以為一維數(shù)組開辟動態(tài)存儲空間,n為數(shù)組元素個數(shù),每個元素長度為Size。(3) free函數(shù) 其函數(shù)原型為void free(void *p);其作用是釋放由指向的內(nèi)存區(qū),使這部分內(nèi)存區(qū)能被其他變量使用。是最近一次調(diào)用calloc或malloc函數(shù)時返回的值。free函數(shù)無返回值。 以前的版本

24、提供的malloc和calloc函數(shù)得到的是指向字符型數(shù)據(jù)的指針。 ANSI 提供的malloc和calloc函數(shù)規(guī)定為void類型。 所謂建立動態(tài)鏈表是指在程序執(zhí)行過程中從無到有地建立起一個鏈表,即一個一個地開辟結(jié)點和輸入各結(jié)點數(shù)據(jù),并建立起前后相鏈的關(guān)系例11.5 寫一函數(shù)建立一個有3名學(xué)生數(shù)據(jù)的單向動態(tài)鏈表。算法如圖圖11-12算法的實現(xiàn): 我們約定學(xué)號不會為零,如果輸入的學(xué)號為,則表示建立鏈表的過程完成,該結(jié)點不應(yīng)連接到鏈表中。 如果輸入的p1-num不等于,則輸入的是第一個結(jié)點數(shù)據(jù)(n=1),令headp1,即把p1的值賦給head,也就是使head也指向新開辟的結(jié)點p1所指向的新開

25、辟的結(jié)點就成為鏈表中第一個結(jié)點圖11-13算法的實現(xiàn): 再開辟另一個結(jié)點并使p1指向它,接著輸入該結(jié)點的數(shù)據(jù).如果輸入的p1-num,則應(yīng)鏈入第個結(jié)點(n=2), 將新結(jié)點的地址賦給第一個結(jié)點的next成員.接著使,也就是使指向剛才建立的結(jié)點圖11-14算法的實現(xiàn):再開辟一個結(jié)點并使p1指向它,并輸入該結(jié)點的數(shù)據(jù)。在第三次循環(huán)中,由于(),又將的值賦給-,也就是將第個結(jié)點連接到第個結(jié)點之后,并使,使指向最后一個結(jié)點.圖11-15算法的實現(xiàn): 再開辟一個新結(jié)點,并使p1指向它,輸入該結(jié)點的數(shù)據(jù)。由于p1-num的值為,不再執(zhí)行循環(huán),此新結(jié)點不應(yīng)被連接到鏈表中.將NULL賦給p2-next.建立鏈

26、表過程至此結(jié)束,p1最后所指的結(jié)點未鏈入鏈表中,第三個結(jié)點的next成員的值為NULL,它不指向任何結(jié)點。圖11-16建立鏈表的函數(shù)如下: #include #include #define NULL 0 /令令NULL代表,用它表示代表,用它表示“空地址空地址#define LEN sizeof(struct student) /令令LEN代表代表struct /student類型數(shù)據(jù)的長度類型數(shù)據(jù)的長度 struct student long num; float score; struct student *next; ;int n; /n/n為全局變量,本文件模塊中各函數(shù)均可使用它為全

27、局變量,本文件模塊中各函數(shù)均可使用它struct student *creat() struct student *head; struct student *p1,*p2; n=0; p1=p2=( struct student*) malloc(LEN); scanf(%ld,%f,&p1-num,&p1-score); head=NULL; while(p1-num!=0) n=n+1; if(n=1)head=p1; else p2-next=p1; p2=p1; p1=(struct student*)malloc(LEN); scanf(%ld,%f,&p1

28、-num,&p1-score); p2-next=NULL; return(head); 首先要知道鏈表第一個結(jié)點的地址,也就是要知道head的值。然后設(shè)一個指針變量p,先指向第一個結(jié)點,輸出所指的結(jié)點,然后使后移一個結(jié)點,再輸出,直到鏈表的尾結(jié)點。 圖11-17,11-18例例1 19 9 編寫一個輸出鏈表的函數(shù)編寫一個輸出鏈表的函數(shù)print.print. void print(struct student *head) struct student *p; printf(nNow,These %d records are:n,n); p=head; if(head!=NULL)

29、do printf(%ld %5.1fn,p-num,p-score); p=p-next; while(p!=NULL); 從一個動態(tài)鏈表中刪去一個結(jié)點,并不是真正從內(nèi)存中把它抹掉,而是把它從鏈表中分離開來,只要撤銷原來的鏈接關(guān)系即可。圖11-19例例11.1011.10寫一函數(shù)以刪除動態(tài)鏈表中指定的結(jié)點寫一函數(shù)以刪除動態(tài)鏈表中指定的結(jié)點. .n 解題思路: 從p指向的第一個結(jié)點開始,檢查該結(jié)點中的num值是否等于輸入的要求刪除的那個學(xué)號。如果相等就將該結(jié)點刪除,如不相等,就將p后移一個結(jié)點,再如此進(jìn)行下去,直到遇到表尾為止。 可以設(shè)兩個指針變量p1和p2,先使p1指向第一個結(jié)點 。 如果要

30、刪除的不是第一個結(jié)點,則使p1后移指向下一個結(jié)點(將p1-next賦給p1),在此之前應(yīng)將p1的值賦給p2 ,使p2指向剛才檢查過的那個結(jié)點 。注意: 要刪的是第一個結(jié)點(的值等于的值,如圖1-0()那樣),則應(yīng)將-賦給。這時指向原來的第二個結(jié)點。第一個結(jié)點雖然仍存在,但它已與鏈表脫離,因為鏈表中沒有一個結(jié)點或頭指針指向它。雖然還指向它,它仍指向第二個結(jié)點,但仍無濟于事,現(xiàn)在鏈表的第一個結(jié)點是原來的第二個結(jié)點,原來第一個結(jié)點已“丟失” ,即不再是鏈表中的一部分了。注意: 如果要刪除的不是第一個結(jié)點,則將-賦給-,見圖10()。-原來指向指向的結(jié)點(圖中第二個結(jié)點),現(xiàn)在-改為指向-所指向的結(jié)點

31、(圖中第三個結(jié)點)。所指向的結(jié)點不再是鏈表的一部分。還需要考慮鏈表是空表(無結(jié)點)和鏈表中找不到要刪除的結(jié)點的情況。圖11-20 算法:圖11-21 刪除結(jié)點的函數(shù)刪除結(jié)點的函數(shù)del:del:struct student *del(struct student *head,long num) struct student *p1,*p2; if (head=NULL)printf(nlist null!n);goto end; p1=head; while(num!=p1-num & p1-next!=NULL) p2=p1;p1=p1-next;if(num=p1-num) if(

32、p1=head) head=p1-next; else p2-next=p1-next; printf(delete:%ldn,num); n=n-1; else printf(%ld not been found!n,num);end;return(head); 對鏈表的插入是指將一個結(jié)點插入到一個已有的鏈表中。為了能做到正確插入,必須解決兩個問題: 怎樣找到插入的位置; 怎樣實現(xiàn)插入。 先用指針變量p0指向待插入的結(jié)點,p1指向第一個結(jié)點。將p0-num與p1-num相比較,如果p0-nump1- num ,則待插入的結(jié)點不應(yīng)插在p1所指的結(jié)點之前。此時將p1后移,并使p2指向剛才p1所指

33、的結(jié)點。 再將p1-num與p0-num比,如果仍然是p0-num大,則應(yīng)使p1繼續(xù)后移,直到p0-p1- num為止。這時將p0所指的結(jié)點插到p1所指結(jié)點之前。但是如果p1所指的已是表尾結(jié)點,則p1就不應(yīng)后移了。如果p0- num比所有結(jié)點的num都大,則應(yīng)將p0所指的結(jié)點插到鏈表末尾。 如果插入的位置既不在第一個結(jié)點之前,又不在表尾結(jié)點之后,則將p0的值賦給p2-next,使p2-next指向待插入的結(jié)點,然后將p1的值賦給p0-next,使得p0-next指向p1指向的變量。 如果插入位置為第一個結(jié)點之前(即p1等于head時),則將p0賦給head,將p1賦給p0-next如果要插到表

34、尾之后,應(yīng)將p0賦給p1-next,NULL賦給p0-next圖11-22 算法:圖11-23 例例11.1111.11插入結(jié)點的函數(shù)插入結(jié)點的函數(shù)insertinsert如下。如下。 struct student *insert(struct student *head, struct student *stud)struct student *p0,*p1,*p2; p1=head;p0=stud; if(head=NULL) head=p0; p0-next=NULL;elsewhile(p0-nump1-num) & (p1-next!=NULL) p2=p1; p1=p1-n

35、ext; if(p0-numnum) if(head=p1) head=p0; else p2-next=p0; p0-next=p1; else p1-next=p0; p0-next=NULL; n=n+1; return(head); 將以上建立、輸出、刪除、插入的函數(shù)組織將以上建立、輸出、刪除、插入的函數(shù)組織在一個在一個C C程序中,用函數(shù)作主調(diào)函數(shù)。程序中,用函數(shù)作主調(diào)函數(shù)。 此程序運行結(jié)果是正確的。它只刪除一個結(jié)此程序運行結(jié)果是正確的。它只刪除一個結(jié)點,插入一個結(jié)點。但如果想再插入一個結(jié)點,點,插入一個結(jié)點。但如果想再插入一個結(jié)點,重復(fù)寫上程序最后重復(fù)寫上程序最后4 4行,共插入兩

36、個結(jié)點,運行結(jié)行,共插入兩個結(jié)點,運行結(jié)果卻是錯誤的。果卻是錯誤的。Input recordsInput records:(建立鏈表):(建立鏈表)1010,1010,1010,Now,these 3 records are:101010101010 intput the deleted number :10103(刪除):1010Now,these 4 records are:10101010 input the inserted record (插入第一個結(jié)點)1010210102,9090Now,these 3 records are:101010101010input the inse

37、rted record (插入第二個結(jié)點)1010410104,9999Now,these 4 records are:1010101010101010 出現(xiàn)以上結(jié)果的原因是:出現(xiàn)以上結(jié)果的原因是: stu是一個有固定地址的結(jié)構(gòu)體變量。第一次把stu結(jié)點插入到鏈表中,第二次若再用它來插入第二個結(jié)點,就把第一次結(jié)點的數(shù)據(jù)沖掉了,實際上并沒有開辟兩個結(jié)點。為了解決這個問題,必須在每插入一個結(jié)點時新開辟一個內(nèi)存區(qū)。我們修改main函數(shù),使之能刪除多個結(jié)點(直到輸入要刪的學(xué)號為0),能插入多個結(jié)點(直到輸入要插入的學(xué)號為0)。 stu定義為指針變量,在需要插入時先用malloc函數(shù)開辟一個內(nèi)存區(qū),將其

38、起始地址經(jīng)強制類型轉(zhuǎn)換后賦給stu,然后輸入此結(jié)構(gòu)體變量中各成員的值。對不同的插入對象,stu的值是不同的,每次指向一個新的struct student變量。在調(diào)用insert函數(shù)時,實參為head和stu,將已建立的鏈表起始地址傳給insert函數(shù)的形參,將stu(即新開辟的單元的地址)傳給形參stud,返回的函數(shù)值是經(jīng)過插入之后的鏈表的頭指針(地址)運行結(jié)果:運行結(jié)果: :10,10,10, :10 10 10 intput the deleted number 10103(刪除):1010Now,these 4 records are1010 9 91010 intput the del

39、eted number 10103(刪除):10105 5Now,these 4 records are1010 9 9 intput the deleted number:0input the inserted record 1010410104,8787Now,these 3 records are10101 99.010101 99.010104 8710104 87 input the inserted record 1010610106,6565Now,these 3 records are10101 99.010101 99.010104 8710104 8710106 65.0

40、10106 65.0 共用體的概念共用體的概念 使幾個不同的變量共占同一段內(nèi)存的結(jié)構(gòu)稱為 “共用體”類型的結(jié)構(gòu)。定義共用體類型變量的一般形式為:unionunion共用體名 成員表列 變量表列;圖11-24例如:例如:union data union data int i; int i; char ch; 或或 char ch; float f; float f;a,b,c; ;union data a,b,c;共用體和結(jié)構(gòu)體的比較:共用體和結(jié)構(gòu)體的比較: 結(jié)構(gòu)體變量所占內(nèi)存長度是各成員占的內(nèi)存長度之和。每個成員分別占有其自己的內(nèi)存單元。 共用體變量所占的內(nèi)存長度等于最長的成員的長度。 共用體

41、和結(jié)構(gòu)體的比較:共用體和結(jié)構(gòu)體的比較: 結(jié)構(gòu)體變量所占內(nèi)存長度是各成員占的內(nèi)存長度之和。每個成員分別占有其自己的內(nèi)存單元。 共用體變量所占的內(nèi)存長度等于最長的成員的長度。 例如例如: :上面定義的“共用體”變量、各占個字節(jié)(因為一個實型變量占個字節(jié)),而不是各占個字節(jié)。 只有先定義了共用體變量才能引用它,而且不能引用共用體變量,而只能引用共用體變量中的成員。例如例如:前面定義了前面定義了a、b、c為共用體變量為共用體變量 a.i (引用共用體變量中的整型變量) a.ch(引用共用體變量中的字符變量) a.f (引用共用體變量中的實型變量) (1)同一個內(nèi)存段可以用來存放幾種不同類型的成員,但在

42、每一瞬時只能存放其中一種,而不是同時存放幾種。(2) 共用體變量中起作用的成員是最后一次存放的成員,在存入一個新的成員后原有的成員就失去作用。 (3) 共用體變量的地址和它的各成員的地址都是同一地址。 (4) 不能對共用體變量名賦值,也不能企圖引用變量名來得到一個值,又不能在定義共用體變量時對它初始化。(5) 不能把共用體變量作為函數(shù)參數(shù),也不能使函數(shù)帶回共用體變量,但可以使用指向共用體變量的指針 (6) 共用體類型可以出現(xiàn)在結(jié)構(gòu)體類型定義中,也可以定義共用體數(shù)組。反之,結(jié)構(gòu)體也可以出現(xiàn)在共用體類型定義中,數(shù)組也可以作為共用體的成員。例例1 112 12 設(shè)有若干個人員的數(shù)據(jù),其中有學(xué)生和教師

43、。學(xué)生的數(shù)據(jù)中包括:姓名、號碼、性別、職業(yè)、班級。教師的數(shù)據(jù)包括:姓名、號碼、性別、職業(yè)、職務(wù)??梢钥闯觯瑢W(xué)生和教師所包含的數(shù)據(jù)是不同的。現(xiàn)要求把它們放在同一表格中。圖11-25算法:圖11-26 #include structint num;char name10;char sex;char job;unionint banji;char position10;category;person2;/*先設(shè)人數(shù)為2*/void main()int i;for(i=0;i2;i+)scanf(%d %s %c %c, &personi.num, &,&

44、;personi.sex, &personi.job);if(personi.job = S)scanf(%d, &personi.category.banji);else if(personi.job = T)scanf(%s, personi.category.position);else printf(“Input error!”); printf(n);printf(No. name sex job class/positionn);for(i=0;i2;i+)if (personi.job = S)printf(“%-6d%-10s%-3c%-3c%-6dn”,per

45、soni.num, , personi.sex, personi.job, personi.category.banji);else printf(“%-6d%-10s%-3c%-3c%-6sn”,personi.num, ,personi.sex, personi.job, personi.category.position);運行情況如下:運行情況如下: 枚舉:將變量的值一一列舉出來,變量的值只限于列舉出來的值的范圍內(nèi)。申明枚舉類型用enumenum weekdaysun,mon,tue,wed,thu,fri,sat; 定義變量:enum weekday workday,week-day;enumsun,mon,tue,wed,thu,fri,satworkday;變量值只能是sun到sat之一 。枚舉元素枚舉常量說明: 在編譯中,對枚舉元素按常量處理,故稱枚舉 常量。它們不是變量,不能對它們賦值。 (2) 枚舉元素作為常量,它們是有值的,語言編譯 按定義時的順序使它們的值為, (3) 枚舉值可以用來作判斷比較。 (4) 一個整數(shù)不能直接賦給一個枚舉變量。 例13口袋中有紅、黃、藍(lán)、白、黑5種顏色的球若干個。每次從口袋中先后取出個球,問得到3種不同色的球的可能取法,輸出每種排列

溫馨提示

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

最新文檔

評論

0/150

提交評論