C語言程序設計-09結構體_第1頁
C語言程序設計-09結構體_第2頁
C語言程序設計-09結構體_第3頁
C語言程序設計-09結構體_第4頁
C語言程序設計-09結構體_第5頁
已閱讀5頁,還剩38頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第9章結構體

9.1結構體類型的定義

9.2結構體變量

9.3結構體數組

9.4結構體類型的指針

9.5結構體與函數

9.6鏈表

9.7結構體應用舉例

本章小結

9.1結構體類型的定義

結構體類型的定義格式為:

STRUCT結構體類型名

{

成員說明列表

};

其中,花括號內的內容是該結構體類型的成員說明。每個成員說明的形式為:

類型符成員名;

9.2結構體變量

9.2.1結構體變量的定義

要定義一個結構體類型的變量,可以采取以下3種方法。

(1)先定義結構體類型,再定義體類型變量。

(2)在定義類型的同時定義變量。

它的作用與前面定義的相同。即定義了兩個STRUCTSTUDENT類型的變量STUDENT1和STUDENT2。這種定義方法的一般格式為:

STRUCT結構體類型名

{

成員說明列表

}變量名列表;

(3)直接定義結構體類型變量。

其一般格式為:

STRUCT

{

成員說明列表

}變量名列表;

即在結構體定義時不出現(xiàn)結構體類型名。這種形式雖然簡單,但不能在再需要使用時,使用所定義的結構體類型。關于結構體類型,有幾點需要說明:

(1)類型與變量是不同的概念,不要混同。對結構體變量來說,在定義時一般先定義一個結構體類型,然后定義變量為該類型。只能對變量賦值、存取或運算,而不能對一個類型賦值、存取或運算。在編譯時,對類型是不分配存儲空間的,只對變量分配存儲空間。

(2)對結構體中的成員,可以單獨使用,它的作用與地位相當于普通變量。

(3)成員也可以是一個結構體變量。

(4)成員名可以與程序中的變量名相同,兩者代表不同的對象。

9.2.2結構體變量的使用

由結構體變量名引用其成員的標記形式為:

結構體變量名.成員名

由指向結構體的指針變量引用結構體成員的標記形式為:

指針變量名->成員名9.2.3結構體變量的初始化

結構體變量和其他變量一樣,可以在變量定義的同時進行初始化。

1.對外部存儲類型的結構體變量進行初始化

【例9.1】分析下列程序的輸出結果。

2.對靜態(tài)存儲類型的結構體變量進行初始化

9.2.4結構體變量的輸入和輸出

C語言不允許把一個結構體變量作為一個整體進行輸入或輸出,而應按成員變量輸入或輸出。例如,若有一個結構體變量:

STRUCT

{

CHARNAME[15];

CHARADDR[20];

LONGNUM;

}STUD={“WANGDAWEI”,“125BEIJINGROAD”,3021118};

變量STUD在內存中存儲情況如圖9-2所示,是按成員變量存放的。由于變量STUD包含兩個字符串數據和一個長整型數據,因此輸出STUD變量,應該使用如下方式:

PRINTF(“%S,%S,%LD\N”,STUD.NAME,STUD.ADDR,STUD.NUM);

輸入STUD變量的各成員值,則用:

SCANF(“%S%S%LD”,STUD.NAME,STUD.ADDR,&STUD.NUM);

由于成員項NAME和ADDR是字符數組,按%S字符串格式輸入,故不要寫成&STUD.NAME和&STUD.ADDR,而NUM成員是LONG型,故應當用&STUD.NUM。

當然也可以用GETS函數和PUTS函數輸入和輸出一個結構體變量中的字符數組成員。例如:

GETS(STUD.NAME);

PUTS(STUD.NAME);

GETS函數輸入一個字符串給STUD.NAME,PUTS函數輸出STUD.NAME數組中的字符串。

9.3結構體數組

9.3.1結構體數組的定義

與定義結構體變量的方法一樣,在結構體變量名之后指定元素個數,就能定義結構體數組。結構體數組定義的一般格式為:

結構體類型名數組名[常量表達式];

如同元素為標準數據類型的數組一樣,結構體數組各元素在內存中也按順序存放,也可初始化,對結構體數組元素的訪問也要利用元素的下標。訪問結構體數組元素的成員的標記方法為:

結構體數組名[元素下標].結構體成員名

9.3.2結構體數組的初始化

在對結構體數組初始化時,要將每個元素的數據分別用花括弧括起來,一般格式是:

結構類型數組名[常量表達式]={初始化表};

9.3.3結構體數組的使用

一個結構體數組的元素相當于一個結構體變量,引用結構體數組元素有如下規(guī)則。

(1)引用某一元素的一個成員。

(2)可以將一個結構體數組元素賦給同一結構體類型數組中的另一個元素,或賦給同一類型的變量。

(3)不能把結構體數組元素作為一個整體直接進行輸入或輸出,只能以單個成員對象進行輸入或輸出。

【例9.2】結構體數組的應用。

9.4結構體類型的指針

9.4.1指向結構體變量的指針

指向結構體的指針變量定義的一般格式為:

STRUCT類型名*指針變量名;

通過指向結構體的指針變量引用結構體成員的方法是:

指針變量->結構體成員名

“*指針變量”表示指針變量所指對象,所以通過指向結構體的指針變量引用結構體成員也可寫成以下形式:

(*指針變量).結構體成員名

【例9.3】寫出下列程序的執(zhí)行結果。

9.4.2指向結構體數組元素的指針

一個指針變量可以指向一個結構體數組元素,也就是將該結構體數組的數組元素地址賦給此指針變量。例如:

STRUCT

{

INTA;

FLOATB;

}ARR[3],*P;

P=ARR;

此時使P指向ARR數組的第一個元素,

“P=ARR;”等價于“P=&ARR[0];”。

若執(zhí)行“P++;”則此時指針變量P

此時指向ARR[1],指針指向關系如

圖9-3所示。

【例9.4】輸入3個學生的信息并輸出。

9.5結構體與函數

9.5.1結構體變量作為函數參數

舊的C標準不允許用結構體變量作為函數參數,只允許指向結構體變量的指針作為函數參數,即傳遞結構體變量的首地址。新的標準以及許多C語言編譯系統(tǒng)都允許用結構體變量作為函數參數,即直接將實參結構體變量的各個成員的值全部傳遞給形參的結構體變量。當然,實參和形參的結構體變量類型應當完全一致。

【例9.5】將例9.4中的輸出的功能用函數實現(xiàn)。

9.5.2指向結構體變量的指針作為函數參數

用結構體變量作為函數參數,這是ANSIC新標準的擴充功能。在過去的C版本中不能這樣使用,而是通過指針來傳遞結構體變量的地址給形參,再通過形參指針變量引用結構體變量中成員的值。

【例9.6】有一結構體變量STU,內含學生學號、姓名和3門課的成績。要求在MAIN函數中給變量賦值,在另一函數PRINT中將它們輸出。

9.5.3返回結構體類型值的函數

函數的返回值可以是結構體類型。例如,定義了結構體數組:

STRUCTSTUDENTSTUD[100];

數據輸入可由如下形式的語句實現(xiàn):

FOR(I=0;I<100;I++)

STUD[I]=INPUT();

函數INPUT的功能是輸入一個結構體數據,并將輸入結構體數據作為返回值,返回給第I個學生記錄,實現(xiàn)第I個學生的數據輸入。

函數INPUT定義如下:

STRUCTSTUDENTINPUT()

{

INTI;

STRUCTSTUDENTSTUD;

SCANF(“%LD”,&STUD.NO);

/*輸入學號*/

GETS(STUD.NAME);

/*輸入學生姓名*/

FOR(I=0;I<3;I++)

/*輸入學生的3門成績*/

SCANF(“%F”,&STUD.SCORE[I]);

RETURNSTUD; /*返回結構體數據*/

}

9.6鏈表

9.6.1鏈表概述

鏈表是最簡單也是最常用的一種數據結構。它是對動態(tài)獲得的內存進行組織的一種結構。如圖9-4所示為最簡單的一種鏈表(單向鏈表)結構。鏈表有一個頭指針變量,圖中以HEAD表示,它存放一個地址。該地址指向一個鏈表元素。鏈表中每一個元素稱為結點,每個結點都包括兩部分:一是用戶需要用的實際數據,二是下一個結點的地址(指針)??梢钥闯?,HEAD指向第一個結點,第一個結點又指向第二個結點,一直到最后一個結點,該結點不再指向其他結點,它稱為表尾,它的地址部分放一個NULL(表示“空地址”),鏈表到此結束。

圖9-4鏈表結構示意圖

由圖9-4可見,一個結點的后繼結點位置由結點所包含的指針成員所指,鏈表中各結點在內存中的存放位置是任意的。如果尋找鏈表中的某一個結點,必須從鏈表頭指針所指的第一個結點開始,順序查找。另外,圖9-4所示的鏈表結構是單向的,即每個結點只知道它的后繼結點位置,而不能知道它的前驅結點。在某些應用中,要求鏈表的每個結點都能方便地知道它的前驅結點和后繼結點,這種鏈表的表示應設有兩個指針成員,分別指向它的前驅和后繼結點,這種鏈表稱為雙向鏈表。為適應不同問題的特定要求,鏈表結構也有多種變形。

9.6.2鏈表的基本操作

鏈表的基本操作包括建立鏈表,鏈表的插入、刪除、輸出和查找等。鏈表結點的存儲空間是程序根據需要向系統(tǒng)動態(tài)申請的,這時要用到8.7節(jié)中介紹的動態(tài)內存管理函數。

1.建立鏈表

如圖9-5所示為用插表頭方法建立鏈表,如圖9-6所示為用鏈表尾方法建立鏈表。

圖9-5用插表頭方法建立鏈表

插表頭算法抽象描述如下:

(1)HEAD=NULL; /*表頭指向空,表示鏈表為空*/

(2)產生新結點,地址賦給指針變量P。

(3)P->NEXT=HEAD;HEAD=P; /*插表頭操作*/

(4)循環(huán)執(zhí)行(2),繼續(xù)建立新結點。

圖9-6用鏈表尾方法建立鏈表

鏈表尾算法抽象描述如下:

(1)HEAD=LAST=NULL;

/*表頭指向空,表示鏈表為空,LAST是表尾指針*/

(2)產生新結點,地址賦給指針變量P,P->NEXT=NULL; /*新結點作為表尾*/

(3)如果HEAD為NULL,則

HEAD=P; /*新結點作為表頭,這時鏈表只有一個結點*/

否則

LAST->NEXT=P;

/*鏈表操作*/

(4)LAST=P;

/*表尾指針指向新結點*/

(5)循環(huán)執(zhí)行(2),繼續(xù)建立新結點。

【例9.7】編寫一個函數,建立一個有N名學生數據的單向鏈表。2.鏈表的插入操作

鏈表的插入操作是要將一個結點插入到一個已有鏈表中的某個位置。該操作可以分兩步完成,先找到插入點,再插入結點。操作步驟如圖9-8所示。圖9-8鏈表的插入操作

鏈表的插入操作算法描述如下:

指針HEAD指向鏈表的頭結點,P0指向待插入的結點,P1和P2一前一后指示插入點。

(1)最初P1=HEAD;。

(2)移動指針P2=P1,P1=P1->NEXT,直到找到插入點。

(3)插入結點P0->NEXT=P1,P2->NEXT=P0。

仍然以例9.7建立的有N名學生數據的單向鏈表為例,設已有的鏈表各結點是按學號由小到大順序排列的。

用指針變量P0指向待插入的結點,最初P1=HEAD,找插入點的操作如下:

當P0->NUM>P1->NUM且P1->NEXT!=NULL

{

P2=P1;

P1=P1->NEXT;

}

插入結點操作如下:

IFP1==HEAD則

結點作為表頭插入

ELSEIFP1->NEXT==NULL則

結點作為表尾插入

ELSE

插入在P2所指結點之后3.鏈表的刪除操作

從一個鏈表中刪去一個結點,只要改變鏈接關系即可,即修改結點指針成員的值,如圖9-9所示。圖9-9刪除結點操作

刪除結點算法描述如下:

用指針P1指向待刪結點,P2指向待刪結點的前一個結點。

(1)P1=HEAD,從第一個結點開始檢查。

(2)當P1指向的結點不是滿足刪除條件的結點且沒有到表尾時,P2=P1,P1=P1->NEXT(移動指針P1,繼續(xù)查找)。

(3)如果找到了刪除結點P1!=NULL,則要分兩種情形:

如果P1==HEAD(刪除的是頭結點)則

HEAD=HEAD->NEXT;

/*刪除頭結點*/

否則

P2->NEXT=P1->NEXT;

/*刪除P1指向的結點*/

(4)FREE(PL),釋放被刪除結點的內存空間。

4.鏈表的輸出操作

要依次輸出鏈表中各結點的數據比較容易處理。首先要知道鏈表頭結點的地址,也就是要知道HEAD的值,然后設一個指針變量P,先指向第一個結點,輸出P所指的結點,然后使P后移一個結點,再輸出。直到鏈表的尾結點。

5.鏈表的查找操作

鏈表的查找是指在已知鏈表中查找值為某指定值的結點。鏈表的查找過程是從鏈表的頭指針所指的第一個結點出發(fā),順序查找。若發(fā)現(xiàn)有指定值的結點,以指向該結點的指針值為查找結果;如果查找至鏈表結尾,未發(fā)現(xiàn)指定值的結點,查找結果為NULL,表示鏈表中沒有指定值的結點。為簡單起見,以指定的學號作為查找結點的關鍵字。

9.7結構體應用舉例

【例9.8】用結構體類型描述復數,編一程序,計算并輸出復數四則運算的結果,要求復數加、減、乘和除分別用4個函數實現(xiàn)。

【例9.9】設計一個洗牌和發(fā)牌的程序,用H代表紅桃,D代表方片,C代表梅花,S代表黑桃,用1~13代表每一種花色的面值。

【例9.10】結構體數組排序。

【例9.11】鏈表的結點信息包括學生學號、成績,結點定義如下:

STRUCTPLIST

{

INTNO;

FLOATSCORE;

STRUCTPLIST*NEXT;

};

設已經建立兩個具有上述結構的鏈表,且兩個鏈表都是按學號升序排列的,要求編寫一個函數,將兩個鏈表合并,仍按學號升序排列。

編寫程序時要考慮以下幾點:

(1)函數應有兩個鏈表指針形參P1、P2,它們指向各自的表頭。

(2)最初新鏈表的頭指針HEAD=NULL,新鏈表的當前結點指針P=NULL。

(3)產生新鏈表的頭結點。

IF(P1->NO<P2->NO)/*比較兩個鏈表中當前結點的學號*/

{HEAD=P=P1;P1=P1->NEXT;}

ELSE

{HEAD=P=P2;P2=P2->NEXT;}

(4)當兩個鏈表的指針均沒指向表尾,則選擇兩個鏈表中的結點并入到新鏈表。

IF(PL->NO<P2->NO)

將P1指向的結點接到新鏈表的表尾:P->NEXT=P1;

并移動P和P1;

ELSE

將P2指示的結點接到新鏈表的表尾:P->NEXT=P2;

并移動P和P2;

(5)當某一個鏈表已到表尾,則另一個鏈表的剩余部分直接鏈接到新鏈表的表尾。

IF(P1!=NULL)

P->NEXT=P1;

ELSE

P->NEXT=P2;

本章小結

1.結構體是一種構造類型,它由若干成員組成。每一個成員既可以是一個基本數據類型也可以是

溫馨提示

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

評論

0/150

提交評論