




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第7章結(jié)構(gòu)體7.1結(jié)構(gòu)體類型與結(jié)構(gòu)體變量
7.2結(jié)構(gòu)體數(shù)組
7.3結(jié)構(gòu)體和函數(shù)
7.4鏈表
7.1結(jié)構(gòu)體類型與結(jié)構(gòu)體變量
7.1.1結(jié)構(gòu)體類型的定義
結(jié)構(gòu)體類型中可以包含若干相同或不同類型的成員,這些成員代表相關(guān)的信息。例如:日期結(jié)構(gòu)體類型可由均為整型的年、月、日三個成員組成;學(xué)生結(jié)構(gòu)體類型可由整型的學(xué)號、字符串類型的姓名、字符型的性別、實(shí)型數(shù)組的考試成績組成。
例如,日期結(jié)構(gòu)體類型可定義為說明:
(1)?struct是結(jié)構(gòu)體類型的標(biāo)識,是關(guān)鍵字。struct和后面的結(jié)構(gòu)體名共同構(gòu)成結(jié)構(gòu)體類型名。結(jié)構(gòu)體名應(yīng)符合標(biāo)識符的命名規(guī)則。結(jié)構(gòu)體類型和系統(tǒng)提供的其他標(biāo)準(zhǔn)數(shù)據(jù)類型(如整型、實(shí)型、字符型等)具有一樣的地位和作用,都可以用來定義某個變量的類型,只是結(jié)構(gòu)體類型需要由用戶自己制定。
(2)結(jié)構(gòu)體所有成員的定義用花括號括起來。結(jié)構(gòu)體成員的定義方式和變量的定義方式一樣,成員類型可以是基本類型的,也可以是構(gòu)造類型。各成員之間用分號隔開。
(3)結(jié)構(gòu)體內(nèi)的各個成員名不能重復(fù),但成員名可以與結(jié)構(gòu)體外其他標(biāo)識符同名而不產(chǎn)生沖突。7.1.2結(jié)構(gòu)體變量的定義
可用以下三種方式定義結(jié)構(gòu)體變量:
(1)用已經(jīng)定義的結(jié)構(gòu)體類型定義結(jié)構(gòu)體變量。例如,用前面已經(jīng)定義的structstudent定義變量stu:
structstudentstu;
(2)定義結(jié)構(gòu)體類型的同時定義結(jié)構(gòu)體變量。例如,定義結(jié)構(gòu)類型structstudent的同時定義變量stu1,stu2:7.1.3結(jié)構(gòu)體變量的指針
可以定義指針變量指向結(jié)構(gòu)體類型變量。例如,語句“structstudent*p=&stu;”定義了指向結(jié)構(gòu)體的指針變量p,并且使其指向結(jié)構(gòu)體變量stu。stu的存儲結(jié)構(gòu)和p指針的示意圖如圖7.1所示。圖7.1結(jié)構(gòu)體變量的存儲結(jié)構(gòu)及其指針7.1.4結(jié)構(gòu)體變量的初始化
結(jié)構(gòu)體變量同樣既可以在定義之后進(jìn)行初始化,也可以在定義的同時進(jìn)行初始化。若在定義之后進(jìn)行初始化操作,只能對每個成員單獨(dú)進(jìn)行賦值。若在定義變量的同時進(jìn)行初始化,則用一對花括號括起各個成員值的列表并用賦值號和變量連接,成員值之間用逗號隔開,具體格式為
結(jié)構(gòu)體類型名結(jié)構(gòu)體變量={成員值列表};7.1.5結(jié)構(gòu)體變量的引用
對于結(jié)構(gòu)體變量,只能引用結(jié)構(gòu)體變量的成員,不能引用整個結(jié)構(gòu)體變量。引用結(jié)構(gòu)體變量成員有以下兩種形式:
(1)通過結(jié)構(gòu)體變量名引用:
結(jié)構(gòu)體變量名.成員名
其中“.”稱為成員運(yùn)算符,它在所有運(yùn)算符中具有最高的優(yōu)先級,可以把“結(jié)構(gòu)體變量名.成員名”作為一個整體看待。
(2)通過指向結(jié)構(gòu)體變量的指針引用:
(*指針變量名).成員名
或
指針變量名
成員名
這兩種表示形式完全等價。結(jié)構(gòu)體成員的運(yùn)算規(guī)則與同類型變量的運(yùn)算規(guī)則相同。
【例7.1】
輸入學(xué)生的各項(xiàng)信息,計(jì)算總分和平均成績后輸出。
程序如下:圖7.2例7.1的運(yùn)行結(jié)果
7.2結(jié)?構(gòu)?體?數(shù)?組
7.2.1結(jié)構(gòu)體數(shù)組的定義和初始化
若數(shù)組元素的類型為結(jié)構(gòu)體類型,則稱該數(shù)組為結(jié)構(gòu)體數(shù)組。定義結(jié)構(gòu)體數(shù)組的同時也可對數(shù)組進(jìn)行初始化,例如:可以定義指向結(jié)構(gòu)體數(shù)組元素的指針變量,然后通過指針對數(shù)組元素操作。例如:
structstudent*p=&stu[2];這條語句定義了指針變量p,并使其指向結(jié)構(gòu)體數(shù)組stu的第2個元素。圖7.3結(jié)構(gòu)體數(shù)組stu的邏輯示意圖7.2.2結(jié)構(gòu)體數(shù)組的引用
結(jié)構(gòu)體數(shù)組也只能引用其數(shù)組元素。結(jié)構(gòu)體數(shù)組元素也是通過數(shù)組名和下標(biāo)來引用的,但要注意只能對最低級的成員進(jìn)行存取和運(yùn)算。引用的一般形式為
數(shù)組名[下標(biāo)].成員名
例如,stu[1].number、stu[0].score[2]和stu[2].ave等是合法的引用形式。
通過指針引用結(jié)構(gòu)體數(shù)組元素的形式和通過指針引用結(jié)構(gòu)變量形式一樣:
(*指針變量名).成員名或指針變量名
成員名例如,語句“p=&stu[1];”之后,(*p).number(第1個學(xué)生的學(xué)號)、(p-1)-
score[2](第0個學(xué)生的第2門課的成績)、p
ave;(第1個學(xué)生的平均成績)是合法的引用形式。
【例7.2】
計(jì)算某班期末考試中所有學(xué)生的總分和平均成績。為了調(diào)試方便,先假定該班只有3個學(xué)生,等程序調(diào)通之后,再把學(xué)生人數(shù)定義為實(shí)際人數(shù)。
程序如下:圖7.4例7.2的運(yùn)行結(jié)果程序說明:main函數(shù)中“floatarg,*point2=&arg;”語句告訴TC需要做浮點(diǎn)數(shù)輸入轉(zhuǎn)換,以便TC把浮點(diǎn)轉(zhuǎn)換格式安裝到可執(zhí)行程序里。因?yàn)門C開發(fā)時(80年代),DOS下的存儲資源緊缺,因此TC在編譯時盡量不加入無關(guān)部分。在沒發(fā)現(xiàn)需要做浮點(diǎn)轉(zhuǎn)換時,就不將這個浮點(diǎn)轉(zhuǎn)換格式安裝到可執(zhí)行程序里。但有時TC不能正確識別,實(shí)際確實(shí)需要浮點(diǎn)轉(zhuǎn)換,因此就會出現(xiàn)“scanf:floatingpointformatsnotlinked。Abnormalprogramtermination”的錯誤信息,使程序無法正常運(yùn)行。為了避免這種情況,在小程序中,往往要加入這樣的語句提醒TC。
7.3結(jié)構(gòu)體和函數(shù)
7.3.1結(jié)構(gòu)體指針變量作為函數(shù)參數(shù)
C語言允許函數(shù)之間傳遞結(jié)構(gòu)體變量,但是形參結(jié)構(gòu)體變量占用內(nèi)存空間,而且接收實(shí)參數(shù)據(jù)將帶來空間和時間的巨大開銷。因此語法上雖然允許,但一般很少采用這種方式,而采用結(jié)構(gòu)體指針作為函數(shù)參數(shù)。參數(shù)傳遞時只需傳遞一個地址,空間和時間的代價都很小。而且,可以通過指針對實(shí)參結(jié)構(gòu)體變量的空間操作,從而改變實(shí)參的值。
【例7.3】
重新編寫例7.2。
程序如下:7.3.2結(jié)構(gòu)體數(shù)組作函數(shù)參數(shù)
向函數(shù)傳遞結(jié)構(gòu)體數(shù)組與傳遞其他數(shù)組一樣,實(shí)質(zhì)上也是傳遞數(shù)組的首地址。形參數(shù)組與實(shí)參數(shù)組使用共同的內(nèi)存單元。形參和實(shí)參是同類型的結(jié)構(gòu)體數(shù)組名或結(jié)構(gòu)體指針。
【例7.4】
重新編寫例7.2。
程序如下: 7.4鏈表
鏈表是一種常見的重要的數(shù)據(jù)結(jié)構(gòu),可以根據(jù)需要動態(tài)地分配存儲單元,因此不會浪費(fèi)內(nèi)存空間。圖7.5表示了一種最簡單的鏈表——單向鏈表。圖7.5最簡單的一種鏈表由圖7.5可知,鏈表有一個“頭指針(head)”變量,其中的地址指向鏈表的第一個元素(稱為“結(jié)點(diǎn)”)。鏈表的每個結(jié)點(diǎn)都包括兩個部分:一為用戶的實(shí)際數(shù)據(jù),二為下一個結(jié)點(diǎn)的地址。所以,在鏈表中,頭指針指向第一個結(jié)點(diǎn),第一個結(jié)點(diǎn)又指向第二個結(jié)點(diǎn),……,最后一個結(jié)點(diǎn)稱為“表尾”,它的地址部分存放“NULL”,表示地址為空,即不再指向任何結(jié)點(diǎn),因此鏈表到此結(jié)束。顯然,鏈表的各個結(jié)點(diǎn)在內(nèi)存中可以不是連續(xù)存放的。觀察鏈表的結(jié)點(diǎn),我們自然會想到,利用結(jié)構(gòu)體變量來表示結(jié)點(diǎn)是最合適不過的。對于圖7.5的鏈表結(jié)點(diǎn),顯然可以用以下結(jié)構(gòu)體表示:7.4.1靜態(tài)鏈表的建立與輸出
【例7.5】
建立圖7.5所示的簡單鏈表,并輸出各結(jié)點(diǎn)中的數(shù)據(jù)。程序如下:
在本程序中,所有結(jié)點(diǎn)都是在程序中定義的,而不是動態(tài)申請空間建立的,所以不能用完后自動釋放,這種鏈表稱為靜態(tài)鏈表。圖7.6例7.5的運(yùn)行結(jié)果7.4.2處理動態(tài)鏈表需要的函數(shù)
動態(tài)鏈表的結(jié)點(diǎn)是動態(tài)分配的,即在需要的時候才開辟某個結(jié)點(diǎn)的存儲單元。為了動態(tài)地開辟和釋放存儲單元,C語言編譯系統(tǒng)提供了以下函數(shù)。
1.?malloc函數(shù)
函數(shù)原形:
void*malloc(unsignedintsize);
作用:在內(nèi)存的動態(tài)存區(qū)分配一個長度為size個字節(jié)的連續(xù)存區(qū),函數(shù)的返回值是一個指向該存區(qū)首地址的指針(其類型為void型)。如果由于內(nèi)存不足等原因使該函數(shù)未能成功執(zhí)行,則返回空指針NULL。
2.?calloc函數(shù)
函數(shù)原形:
void*calloc(unsignedn,unsignedsize);
作用:在內(nèi)存的動態(tài)存區(qū)分配n個長度為size個字節(jié)的連續(xù)存區(qū),函數(shù)的返回值是一個指向該存區(qū)首地址的指針(其類型為void型)。如果由于內(nèi)存不足等原因使該函數(shù)未能成功執(zhí)行,則返回空指針NULL。使用calloc函數(shù)能夠?yàn)橐痪S數(shù)組開辟動態(tài)存儲空間,n為數(shù)組元素的個數(shù),每個元素的長度為size個字節(jié)。
3.?free函數(shù)
函數(shù)原形:
voidfree(void*p);
作用:釋放p指向的內(nèi)存區(qū),使這部分內(nèi)存區(qū)域能夠被其他變量使用,p為最近一次malloc/calloc的返回值,即最近一次分配的空間。free函數(shù)沒有返回值。
7.4.3建立動態(tài)鏈表
所謂建立動態(tài)鏈表,是指在程序執(zhí)行過程中逐個建立鏈表的各個結(jié)點(diǎn),即逐個開辟結(jié)點(diǎn)的內(nèi)存空間,再輸入該結(jié)點(diǎn)的數(shù)據(jù),然后建立起前后結(jié)點(diǎn)之間的相連關(guān)系。
【例7.6】
用建立單向動態(tài)鏈表的方法建立圖7.5所示的鏈表。
為了建立一個單向動態(tài)鏈表,需要設(shè)置3個指針變量:head、p1和p2,它們都指向structstudent類型數(shù)據(jù),p1指向新開的結(jié)點(diǎn),p2指向鏈表中最后一個結(jié)點(diǎn)。先使head的值為NULL,即不指向任何結(jié)點(diǎn),鏈表為空。圖7.7建立第一個結(jié)點(diǎn)首先建立圖7.7所示的第一個結(jié)點(diǎn)。先用malloc函數(shù)開辟第一個結(jié)點(diǎn),即在內(nèi)存的動態(tài)存區(qū)分配一個一定長度的連續(xù)存區(qū),并且使p1指向它,由于當(dāng)前鏈表為空,所以p2也指向剛分配的連續(xù)存區(qū)。再從鍵盤上讀入第一個學(xué)生的數(shù)據(jù)(學(xué)號和成績)給p1指向的結(jié)點(diǎn)。由于實(shí)際上沒有學(xué)號為0的學(xué)生,所以以輸入的學(xué)號為0表示學(xué)生數(shù)據(jù)已經(jīng)讀完,鏈表建成,不再繼續(xù)建立新結(jié)點(diǎn)的循環(huán)。在輸入第一個學(xué)生的數(shù)據(jù)之前,鏈表中沒有結(jié)點(diǎn),所以頭指針head為NULL。當(dāng)輸入的學(xué)號不為0時,就開始為這個學(xué)生建立結(jié)點(diǎn),當(dāng)n=1時,表示當(dāng)時的結(jié)點(diǎn)為第一個結(jié)點(diǎn),所以把這個結(jié)點(diǎn)的指針p1的值賦給head,head就指向了鏈表的頭部。當(dāng)圖7.7所示的第1個結(jié)點(diǎn)建立以后,為了建立下一個學(xué)生的結(jié)點(diǎn),再用malloc函數(shù)開辟一個結(jié)點(diǎn),并且用p1指向這個新結(jié)點(diǎn),如圖7.8(a)所示;接著讀入第二個學(xué)生的數(shù)據(jù),由于讀入的學(xué)號非0,所以第二次進(jìn)入建立結(jié)點(diǎn)的循環(huán),由于結(jié)點(diǎn)數(shù)n不為1,所以將p1的值賦給p2->next,使第一個結(jié)點(diǎn)連到了第二個結(jié)點(diǎn),如圖7.8(b)所示,然后,又將p1的值賦給p2,使第二個結(jié)點(diǎn)的p1、p2兩個指針又回到圖7.7第一個結(jié)點(diǎn)剛建立的狀態(tài),準(zhǔn)備建立下一個結(jié)點(diǎn)。如此周而復(fù)始,就可以建立第三、第四或者更多的結(jié)點(diǎn),如圖7.9和圖7.10所示。圖7.8建立第2個結(jié)點(diǎn)圖7.9建立第3個結(jié)點(diǎn)圖7.10建立第4個結(jié)點(diǎn)當(dāng)讀入的學(xué)號為0時,表示學(xué)生數(shù)據(jù)已經(jīng)輸入完畢,所以不再進(jìn)入建立新結(jié)點(diǎn)的while循環(huán),而置p2->next為NULL,表示剛才建立的結(jié)點(diǎn)是尾結(jié)點(diǎn),此時,雖然p1指向新開辟的結(jié)點(diǎn),但是這個“新結(jié)點(diǎn)”并不包含在鏈表之內(nèi),從鏈表中不可能找到這個結(jié)點(diǎn)。
7.4.4對鏈表的刪除
所謂刪除動態(tài)鏈表的某個結(jié)點(diǎn),其實(shí)并不是真的從內(nèi)存中把這個結(jié)點(diǎn)抹掉,只是撤銷原來的連接關(guān)系,把這個結(jié)點(diǎn)從鏈表中分離出去。
【例7.7】
寫一個函數(shù)刪除例7.5建立的動態(tài)鏈表中指定學(xué)號的結(jié)點(diǎn)。
所謂刪除指定學(xué)號的結(jié)點(diǎn),就是從頭結(jié)點(diǎn)開始,逐個比較每個結(jié)點(diǎn)的num是否等于該指定的學(xué)號,如果相等就將該結(jié)點(diǎn)刪除,否則就比較下一個結(jié)點(diǎn),直到檢查到鏈表的表尾為止。為此先設(shè)置兩個指針p1和p2,使p1指向第1個結(jié)點(diǎn)如圖7.11(a)所示。首先檢查第一個結(jié)點(diǎn),如果要刪除的結(jié)點(diǎn)不是第1個結(jié)點(diǎn),首先將p1的值賦給p2,使p2指向剛才檢查過的結(jié)點(diǎn),然后使p1指向下一個結(jié)點(diǎn)(即p1=p1->next),如圖7.11(b)所示,如此一次一次地使指針后移,直到查到要刪除的結(jié)點(diǎn)或者一直查到表尾都沒有找到要刪除的結(jié)點(diǎn)為止。
如果找到了要刪除的結(jié)點(diǎn),而且是第一個結(jié)點(diǎn),則將p1->next賦給head,如圖7.11(c)所示,于是第1個結(jié)點(diǎn)就被刪除了(實(shí)際是和鏈表脫離了,而不再是鏈表的一部分)。如果找到了要刪除的結(jié)點(diǎn),但不是第一個結(jié)點(diǎn),譬如查到圖7.11(a)的第2個結(jié)點(diǎn)時(現(xiàn)在p1指向第2個結(jié)點(diǎn)),發(fā)現(xiàn)它是要刪除的結(jié)點(diǎn),則將p1->next賦給p2->next,如圖7.11(d)所示,于是第1個結(jié)點(diǎn)不再指向第2個結(jié)點(diǎn),而是指向第3個結(jié)點(diǎn)了,因此把第2個結(jié)點(diǎn)與鏈表脫離了。
如果直到查到表尾都沒有找到要刪除的結(jié)點(diǎn),則輸出“找不到要刪除的結(jié)點(diǎn)”。
如果所查找的鏈表一個結(jié)點(diǎn)都沒有,即頭指針為空,完全是個空表,則輸出“空表”信息。圖7.11刪除結(jié)點(diǎn)圖7.12是刪除結(jié)點(diǎn)的算法框圖。圖7.12刪除結(jié)點(diǎn)的算法框圖7.4.5對鏈表的插入操作
所謂對鏈表的插入,是指將一個新結(jié)點(diǎn)插入到一個已經(jīng)存在的鏈表中。
如果已有一個學(xué)生鏈表,各結(jié)點(diǎn)是按照其成員項(xiàng)num的數(shù)值按升序排列的,現(xiàn)在要求將一個新生的結(jié)點(diǎn)按學(xué)號插入到鏈表的適當(dāng)位置。
為了實(shí)現(xiàn)結(jié)點(diǎn)的插入,首先要找到插入的位置,然后用適當(dāng)?shù)姆椒▽⒔Y(jié)點(diǎn)插入到這個位置。由于已有的鏈表是按照學(xué)號的升序排列的,所以從第一個結(jié)點(diǎn)開始比較,新結(jié)點(diǎn)應(yīng)該插在第一次比新結(jié)點(diǎn)的學(xué)號大的學(xué)生之前,設(shè)該結(jié)點(diǎn)是第i+1個結(jié)點(diǎn),那么新結(jié)點(diǎn)應(yīng)該插在第i和第i+1個結(jié)點(diǎn)之間。即使第i個結(jié)點(diǎn)和第i+1個結(jié)點(diǎn)的連接斷開,讓第i個結(jié)點(diǎn)指向新結(jié)點(diǎn),然后再使新結(jié)點(diǎn)指向第i+1個
溫馨提示
- 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 高性能氫燃料電池測試工程師崗位聘用合同
- 抖音短視頻內(nèi)容違約金計(jì)算及責(zé)任界定合同
- 環(huán)保產(chǎn)業(yè)投資風(fēng)控完善補(bǔ)充協(xié)議
- 紡織服裝企業(yè)股權(quán)分割與品牌合作協(xié)議
- 煤炭安全生產(chǎn)責(zé)任與經(jīng)營管理委托協(xié)議
- 撕毀合約機(jī)協(xié)議書
- 夢見捐器官協(xié)議書
- 找工人拆墻協(xié)議書
- 無責(zé)任傷殘協(xié)議書
- 歐洲城市公寓托管租賃全權(quán)委托合同
- GB/T 28583-2025供電服務(wù)規(guī)范
- 設(shè)備故障應(yīng)急維修預(yù)案
- 四川西華師范大學(xué)招聘輔導(dǎo)員考試真題2024
- 貴州游船傾覆防災(zāi)減災(zāi)安全教育時事熱點(diǎn)
- 公務(wù)員法律考試題及答案
- 黑龍江省大慶市石油高級中學(xué)2024-2025學(xué)年高二上學(xué)期期末語文試題 含解析
- 呼吸性酸中毒試題及答案
- 基于深度學(xué)習(xí)的手術(shù)機(jī)器人在后交叉韌帶斷裂中的導(dǎo)航優(yōu)化-洞察闡釋
- 檢察院相關(guān)試題及答案
- 安全生產(chǎn)管理機(jī)制
- 遴選公務(wù)員筆試真題及答案
評論
0/150
提交評論