版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第9章結構體、共用體和用戶定義類型前言9.1結構體9.2共用體9.3用指針處理鏈表9.4用typedef聲明新類型名
前 言問題:一個學生的信息包括姓名(char型)、性別(char型)、年齡(int型)、學號(int型)、成績(float型)等。我們如果分別定義互相獨立的簡單變量,顯然難以反映這些數據信息的內在聯系。而數據類型不同,也不能通過數組來存放。C語言允許用戶根據需要自己建立一些數據類型,比如可將上述一個學生的不同類型的數據信息共同存放于構造類型——結構體或者共用體中,同時,C語言也允許使用如typedef等來定義說明一個新的數據類型。9.1結構體9.1.1結構體類型數據的定義
9.1.2結構體類型數據成員的引用
9.1.3結構體數組
9.1.4結構體指針9.1.1結構體類型數據的定義用戶建立由不同類型數據組成的組合型的數據結構,稱之為結構體類型,組成結構體類型的每一個數據稱之為該結構體類型的成員。在使用結構體類型時,首先要對結構體類型的組成進行說明,稱之為結構體類型的定義。格式:struct結構體標識名
{
數據類型結構體成員名1;數據類型結構體成員名2;
…
數據類型結構體成員名n;
};其中:“struct”為定義結構體類型的關鍵字。例如:以上學生的信息可定義為下列一個名為Student的結構體類型:structStudent//Student為結構體標識名
{charname[20];//每個成員項以分號(;)結束
charsex;
intage;
intnum;
floatscore;
};//結構體定義以分號(;)結束以上定義中,結構體類型Student由5個成員組成。9.1.1結構體類型數據的定義結構體類型的成員也可以包含另一個結構體類型,形成結構類型嵌套。例如:structDate{intmonth;
intday;
intyear;
};structStudent{charname[20];
charsex;
structDatebirthday;floatscore;
intnum;
};structStudent類型的結構如右圖:9.1.1結構體類型數據的定義當結構體類型定義后,就可以指定該結構體類型的具體對象,即定義結構體類型的變量,稱之為結構體變量。定義結構體變量可采取以下三種形式:1.聲明結構體標識名后,再定義結構體變量2.聲明結構體標識的同時定義結構體變量3.不指定結構體標識名而直接定義結構體變量9.1.1結構體類型數據的定義1.聲明結構體標識名后,再定義結構體變量格式:struct結構體標識名結構體變量名表例如:在前面聲明了結構體類型Student后,再來定義結構體變量stu1和stu2。structStudentstu1,stu2;這種形式和定義其它類型變量形式相似(如inta,b;)。變量stu1和stu2則具有Student類型的數據結構,是由多個數據成員組成的構造類型的變量,如下圖所示:在定義了結構體變量后,系統會為之分配內存單元,stu1和stu2分別占據一段連續的存儲單元,在VisualC++環境中,stu1和stu2分別占據33字節(name20個字節,sex1個字節,age4個字節,num4個字節,score4個字節)。9.1.1結構體類型數據的定義2.聲明結構體標識的同時定義結構體變量格式:struct結構體標識名
{
數據類型結構體成員名1;數據類型結構體成員名2;
…
數據類型結構體成員名n;
}結構體變量名表;例如:在前面聲明了結構體類型Student的同時定義結構體變量stu1和stu2。structStudent{charname[20];
charsex;
intage;
intnum;
floatscore;
}stu1,stu2;9.1.1結構體類型數據的定義3.不指定結構體標識名而直接定義結構體變量格式:struct//不需要指定結構體標識名
{
數據類型結構體成員名1;數據類型結構體成員名2;
…
數據類型結構體成員名n;
}結構體變量名表;例如:采用此方法定義結構體變量stu1和stu2。struct{charname[20];
charsex;
intage;
intnum;
floatscore;
}stu1,stu2;【注意】此方法指定的是個無名的結構體類型,所以該結構體類型不能再定義其它變量。【說明】①結構體類型與結構體變量是不同的概念,不要混同。只能對變量賦值、存取或運算,而不能對一個類型賦值、存取或運算。②結構體變量中的成員可以單獨使用,運算方式和普通變量相同。③結構體類型中的成員名可以與程序中的變量名相同,但二者不代表同一對象。9.1.1結構體類型數據的定義例9.1下面結構體的定義語句中,錯誤的是(2009年9月全國計算機等級考試二級C試題選擇題第36題)A)structord{intx;inty;intz;};structorda;B)structord{intx;inty;intz;}structorda;C)structord{intx;inty;intz;}a;D)struct{intx;inty;intz;}a;分析:A)采用的先聲明結構體類型,再定義結構體變量的方式,格式正確;C)采用的聲明結構體類型的同時定義結構體變量的方式,格式正確;D)采用的不指定結構體類型而直接定義結構體變量的方式,格式正確;B)在聲明結構體類型后沒有用分號結束,選B。返回9.1.2結構體類型數據成員的引用在定義了結構體變量后,就可以引用該結構體變量,執行賦值、存取和運算等操作。在引用結構體變量時,主要是通過引用結構體變量的各個成員來實現各種操作。引用結構體變量的成員的方式為:格式:結構體變量名.成員名9.1.2結構體類型數據成員的引用例9.2把一個學生的信息(包括姓名、性別、年齡、學號、成績)放在一個結構體變量中,然后輸出這個學生的信息。#include<stdio.h>intmain(){structStudent//聲明Student為結構體類型
{charname[20];//以下五行為結構體的成員
charsex;intage;intnum;floatscore;}a={“LiLin”,‘M’,18,10101,86.5};//定義結構體變量a并初始化
printf("name:%s\nsex:%c\nage:%d\nNO.:%d\nscore:%4.1f\n",,a.sex,a.age,a.num,a.score);return0;}運行結果:name:LiLinsex:Mage:18NO.:10101score:結構體類型數據成員的引用【例9.2說明】①“.”是成員運算符,它在所有運算符中優先級最高。可認為a.XX為一個整體。②在定義結構體變量的同時可以對它的成員初始化,初始化方式和數組的初始化類似,用花括號括起來一些常量,這些常量依次對結構體變量中的各成員賦值。③在引用結構體變量時,不能將一個結構體變量作為一個整體處理,而應當通過對該結構體變量的各個成員項的引用實現相應操作。若上述例題中輸出寫成printf("name:%s\nsex:%c\nage:%d\nNO.:%d\nscore:%4.1f\n",a)錯誤。④可以引用結構體成員地址和結構體變量地址。如:scanf(“%d“,&a.num);作用是從鍵盤為成員a.num提供值。printf(“%o“,&a);作用是輸出a的首地址。但不能用以下方法整體讀入結構體變量:scanf(”%s,%c,%d,%d,%f“,&a)。⑤若成員本身又屬于一個結構體類型,只能對最低級的成員進行賦值、存取以及運算。如:stu1.birthday.year=1986⑥結構體變量成員可以象普通變量一樣進行各種運算,如:stu1.age=stu2.age(賦值運算);sum==stu1.age+stu2.age(加法運算)。同類的結構體變量可以互相賦值,如stu1=stu2。9.1.2結構體類型數據成員的引用例9.3設有定義:(2009年9月全國計算機等級考試二級C試題填空題第12題)structperson{intID;charname[12];}p;請將scanf(“%d”,
);語句補充完整,使其能夠為結構體變量p的成員ID正確讀入數據。分析:在對結構體成員提供值時,應分別對各成員按變量方式處理。此題中,變量p的成員ID為int型數據,輸入時,把p.ID看做一個整體,引用其地址,所以輸入格式為:scanf(“%d”,&p.ID)。例9.4設有定義:(2011年3月全國計算機等級考試二級C試題選擇題第36題)struct{charmark[12];intnum1;doublenum2;}t1,t2;設有若變量均已正確賦初值,則以下語句中錯誤的是A)t1=t2; B)t2.num1=t1.num1;C)t2.mark=t1.mark;D)t2.num2=t1.num2;分析:定義為同類型的結構體變量可互相賦值,A)正確;結構體變量成員和普通變量的運算規則相同,所以整型數據、雙精度實數型數據都可直接賦值,B)、D)正確。用賦值語句將一個字符數組直接給一個字符數組是不合法的,C)錯誤。選C9.1.2結構體類型數據成員的引用例9.5有以下程序:(2010年3月全國計算機等級考試二級C試題選擇題第37題)#include<stdio.h>#include<string.h>structA//定義結構體類型A{inta;charb[10];doublec;};voidf(structAt);//定義函數fmain(){structAa={1001,"ZhangDa",1098.0};//定義結構體變量a并進行初始化操作f(a);//調用f函數,結構體變量a作為實參printf("%d,%s,%6.1f\n",a.a,a.b,a.c);}voidf(structAt){t.a=1002;strcpy(t.b,"ChangRong");t.c=1202.0;}程序運行后的輸出結果是A)1001,zhangDa,1098.0 B)1002,changRong,1202.0C)1001,ehangRong,1098.0 D)1002,ZhangDa,1202.09.1.2結構體類型數據成員的引用例9.5分析:本題中函數調用的形式為傳值調用,不會改變任何值。所以輸出結果仍是結構體變量a原來的成員的初始值。選A。【說明】將一個結構體變量的值傳遞給另一個函數有三種形式:①結構體變量的成員作為參數,如用a.a作為實參,將實參值傳遞給形成。用法同普通變量作實參相同,是“按值傳遞”。需要保持實參和形參類型一致。②用結構體變量作為實參,同樣采用“按值傳遞”的方式,不過是將結構體變量所有成員值按順序傳遞給形參。注意形參和實參的結構類型相同,但運行時占用不同的存儲空間,調用時,被調函數不能修改調用函數實參的值。③用結構體指針變量作為實參,即將結構體變量的首地址傳遞給形參,即“按地址傳遞”。此時,實參和形參所指向的是同一組內存單元。返回9.1.3結構體數組結構體數組就是指數組中的每一個數組元素都是結構體類型變量。定義結構體數組方式和定義結構體變量相同。格式:struct結構體名{結構體成員表列}數組名【數組長度】也可以先聲明結構體類型,如structPerson,然后再用此類型定義結構體數組:結構體類型數組名【數組長度】結構體數組初始化形式和數組賦初值的方式相同。在定義數組的后面加上:={初值表列};由于數組中的每個元素都是一個結構體變量,通常將一個數組元素的成員放在一對花括號中,以區分各個元素。結構體數組的引用指對結構體數組元素的引用,引用結構體變量的方法適用于結構體數組元素。格式:數組元素名稱.成員名結構體數組元素可賦值給同一結構體數組中的另一個元素,或者賦值給同類型的變量。9.1.3結構體數組例9.6有以下程序:(2011年3月全國計算機等級考試二級C試題選擇題第38題)#include<stdio.h>structS{inta,b;}data[2]={10,100,20,200};voidmain(){structSp=data[1];printf("%d\n",++(p.a));}程序運行后的輸出結果是A)10 B)11 C)20 D)21分析:定義結構體數組變量data賦初值后,相當于data[0].a=10,data[0].b=100,data[1].a=20,data[1].b=200;將data[1]賦值給結構體變量p,即p.a=20,p.b=200。所以,++(p.a)的值為21,選D9.1.3結構體數組例9.7輸入三個學生的信息,包括姓名,學號,性別,成績,輸出成績在90分以上(含90)的男生信息#include<stdio.h>structstudent//聲明結構體類型student{charxm[20];intxh;charxb;floatcj;};voidmain(){structstudentstu[3];//聲明結構體數組
inti;for(i=0;i<3;i++){scanf("%s%d,%c,%f",stu[i].xm,&stu[i].xh,&stu[i].xb,&stu[i].cj);//用scanf函數輸入每個學生的姓名、學號、性別、成績
}for(i=0;i<3;i++)if(stu[i].xb=='m'&&stu[i].cj>=90.0)//判定性別和成績
printf("%d\t%s\t%4c\t%5.1f\n",stu[i].xh,stu[i].xm,stu[i].xb,stu[i].cj);//按學號、姓名、性別、成績的順序輸出學生信息}9.1.3結構體數組例9.7運行結果:liyang<回車>001,m,92.5<回車>wangling<回車>1002,f,95<回車>chenyang<回車>1003,m,86.5<回車>1001 liyang m 92.5【注意】本例中用scanf函數輸入各成員時,字符數組以回車作為字符串的輸入結束,其它變量都用“,”隔開。返回9.1.4結構體指針指向結構體的指針稱為結構體指針變量。一個結構體變量的起始地址就是這個結構體變量的指針,結構體指針也可以指向結構體數組中的元素,即將結構體數組的起始地址賦給指針變量。結構體指針變量定義方式如下格式:struct結構體類型*結構體指針例如:structStudent*p;//p可以指向structStudent類型的變量或者數組元素9.1.4結構體指針例9.8有以下定義和語句(2010年3月全國計算機等級考試二級C試題選擇題第38題)structworkers//聲明結構體類型structworkers{intnum;charname[20];charc;struct{intday;intmonth;intyear;}s;
//成員s為另一個結構體類型};structworkersw,*pw;//定義structworkers類型變量w,以及指向structworkers類型數據的指針變量pwpw=&w;//pw指向w,即將結構體變量w的起始地址賦給指針變量w能給w中year成員賦值1980的語句是A)*pw.year=198O; B)w.year=1980;C)pw->year=1980; D)w.s.year=1980;9.1.4結構體指針例9.8分析:year屬于結構體類型structworkers的成員結構體類型s,所以要訪問到year需要逐級訪問,訪問方式為w.s.year.。D選項可以正確賦值。對year賦值,也可采取以下方式:(*pw).s.year=1980;pw->s->year=1980【說明】①(*pw)表示pw指向的結構體變量,(*pw).s.year則表示pw指向的結構體成員s的成員year。由于成員運算符“.”優先于“*”,*pw兩側括號不能省。②為直觀方便,C語言允許把“(*pw).”形式用“pw->”形式替代,“->”稱為指向運算符,用于連接指針變量與其指向的結構體變量的成員。所以,如果pw指向結構體變量w,以下3種用法等價:1)w.成員名(如w.num)2)(*pw).成員名(如(*pw).num)3)pw->成員名(如pw->num)③指向運算符“->”優先級最高,例如++p->num等同于++(p->num),即對p->num的值做自增運算。9.1.4結構體指針例9.9有以下程序(2011年3月全國計算機等級考試二級C試題選擇題第37題)#include<stdio.h>structord//定義結構體類型structord{intx,y;}dt[2]={1,2,3,4};//定義結構體數組dt并對數組初始化main(){structord*p=dt;//定義指向structord類型數據的指針變量p,并且p指向結構體數組dt的第一個元素的首地址printf("%d,",++(p->x));printf("%d\n",++(p->y));}程序運行后的輸出結果是A)1,2 B)4,1 C)3,4 D)2,39.1.4結構體指針例9.9分析:此題中,定義的結構體數組dt有兩個元素,每個元素包含兩個成員x和y。初始化值表示dt[0].x=1,dt[0].y=2,d[1].x=3,dt[1].y=4,p指向數組dt的第一個元素,即p->x=1,p->y=2,所以,++(p->x)=2,++(p->y)=3。選D【說明】①由于指向運算符“->”優先級最高,++(p->x)等價于++p->x。②但如果要求輸出“(++p)->x”的值,則表示先使p增加1,此時,p指向的是數組的第2個元素的x成員值,輸出結果為3,,指針p的變化如圖9.4
指針p的變化示意圖9.2共用體9.2.1共用體類型數據的定義9.2.2共用體類型數據成員的引用
9.2.1共用體類型數據的定義C語言中,共用體類型數據和結構體類型數據都屬于構造類型。共用體類型數據在定義上與結構體相似。區別在于,結構體變量是各類型數據成員的集合,每個成員占用不同的存儲空間,結構體變量所占內存是各成員占的內存和。而共用體變量所有成員共享同一段內存單元,以最長的成員所占的內存作為共用體變量的存儲空間;所有成員從同一地址開始存儲,采用覆蓋技術,在某一時刻只能讓一個成員起作用。9.2.1共用體類型數據的定義定義共用體類型可采取以下方式:格式:union共用體標識名{
數據類型1共用體成員名1;數據類型2共用體成員名2;
…
數據類型n共用體成員名n;};例如:unionData{inta;charc;floatx;};9.2.1共用體類型數據的定義共用體變量的定義和結構體變量的定義相似,可采用以下三種形式:1.聲明共用體類型名后,再定義共用體變量2.聲明共用體標識的同時定義共用體變量3.不指定共用體標識名而直接定義共用體變量9.2.1共用體類型數據的定義1.聲明共用體類型名后,再定義共用體變量例如:unionData{inta;charc;floatx;};unionDatam,n;9.2.1共用體類型數據的定義2.聲明共用體標識的同時定義共用體變量例如:unionData{inta;charc;floatx;}m,n;9.2.1共用體類型數據的定義3.不指定共用體標識名而直接定義共用體變量例如:union{inta;charc;floatx;}m,n;9.2.1共用體類型數據的定義以上幾種定義形式中,共用體m和n等價,共用體m和n所占存儲空間相同。VC環境中,存儲空間分配方式如下圖所示:共用體變量m(n)在內存中所占字節數是成員中最長的(整型和實型都是4個字節)4個字節;如果定義的是結構體變量,所占內存則為(4+1+4)=9個字節。返回9.2.2共用體類型數據成員的引用在定義了共用體變量后才能引用它,引用形式為引用共用體變量的成員,一般不能整體引用共用體變量(C99標準中有例外)。引用共用體變量的一個成員方式為:格式:共用體變量名.成員名如在前面定義了m、n為共用體變量,可以引用其成員:m.c(引用共用體變量m中的字符變量c)【注意】C99標準中允許同類型的共用體變量互相賦值。如:m=n9.2.2共用體類型數據成員的引用定義共用體變量的同時,只能對第一個成員的類型進行初始化。一般格式:union共用體標識名共用體變量={第一個數據成員的類型值};例如:unionData{inta;charc;floatx;}m={6,‘a’,3.5}//錯誤,不能初始化三個成員,它們占用同一段內存unionDatam={6};//正確,對共用體第一個成員整型a賦初值unionDatam={.c=‘M’};//C99允許對指定的成員賦初值【說明】①共用體類型在同一內存單元可以存放不同類型的數據,但在每一瞬間只能存放其中一個成員,即共用體變量只能存放一個值。9.2.2共用體類型數據成員的引用例如:unionData{inta;charc;floatx;}m;m.a=97;//將97按整數形式存放在共用體變量中,在內存中最后一個字節存儲形式為“01100001”執行輸出語句:printf(”%d”,m.a);//輸出整數97。將存儲信息按整數形式處理printf(”%c”,m.c);//輸出字符’a’。將存儲信息按字符形式處理printf(”%f”,m.x);//輸出實數0.000000。將存儲信息按浮點數形式處理②共用體存儲空間保留的是最后一次被賦值的成員的值。例如執行以下賦值語句:m.c=’M’;m.f=3.5;m.a=6;共用體變量存放的是最后輸入的6,在引用時應特別注意當前共用體變量的存儲成員。③共用體變量的地址和它各成員的地址都是同一地址,都是從共用體變量空間的起點開始。④共用體類型可以出現在結構體類型定義中,數組也可以是共用體的成員。⑤以前的C不能使用共用體變量作為函數參數,也不能使用函數返回共用體變量,但可以用指向共用體變量的指針。C99允許共用體變量作為函數參數
9.2.2共用體類型數據成員的引用例9.10分析下列程序的運行結果#include<stdio.h>union//聲明共用體類型{inti;//以下兩行指定共用體成員
charc[2];}a;//聲明共用體變量aintmain(){charx;//定義字符變量xa.i=259;//對共用體變量成員整型i賦初值x=a.c[0];//以下三行交換數組元素a.c[0]和a.c[1]的值
a.c[0]=a.c[1];a.c[1]=x;printf("%d\n",a.i);return0;}運行結果:769分析:共用體變量成員a.i賦初值259,在共用體變量的內存中存儲方式為“0000000100000011”,交換a.c[0]和a.c[1]的值后,內存的存儲變為“0000001100000001”,轉換成十進制輸出為769。9.3用指針處理鏈表9.3.1什么是鏈表
9.3.2建立簡單的靜態鏈表
9.3.3建立動態鏈表
9.3.4結點數據的輸出、刪除與插入
9.3.1什么是鏈表在前面的學習中,我們認識到數組是一批有先后次序的元素所組成的序列。在使用數組存放數據時,必須先定義固定的數組長度,而當數組元素不確定時,需要開辟足夠大的存儲空間,顯然這會造成內存空間的浪費。并且在數組中,插入或刪除元素時,需要移動其它元素。鏈表是一種常見而重要的數據結構類型。鏈表和數組類似,也是一批有先后次序的序列。但是鏈表中的元素可動態的分配存儲單元,并且鏈表中的各元素在內存中的地址可以不連續,所以在鏈表中插入和刪除元素時也不需要移動其它元素。鏈表中,每一個元素稱為結點。結點是鏈表的基本存儲單位,每個結點之間可以占用不連續的內存。結點與結點之間通過指針鏈接在一起,一個元素指向下一個元素,直到最后一個元素,該元素不再指向其它元素,稱之為“表尾”,“表尾”的地址存放一個空指針(NULL)。所以,每個結點至少應包括兩部分:用戶需要用的實際數據和下一個結點的地址(用指針變量存放)。9.3.1什么是鏈表如圖9.6為最簡單的一種鏈表(單向鏈表)的結構。如圖所示,鏈表有一個“頭指針”變量(圖中以head表示),它是指向鏈表表頭結點的指針。每個結點都包含數據信息(圖中的A、B、C、D)和下一結點的地址(圖中的1259、1326等)兩部分信息。可見,鏈表結構中,邏輯相連的數據,其結點間的物理地址并不連續。要訪問某個元素,需要先找到它的上個元素提供的地址,逐個往前,所以最終需要通過“頭指針”(head)才可以訪問整個鏈表中的元素。9.3.1什么是鏈表由于結點可包含不同的數據類型,根據前面所學,定義結點應采用結構體類型。一般形式:structnode{intdata;//用戶需要用的實際數據(數據域),注意不僅僅是整型structnode*next//下一個結點的地址(指針域)}9.3.1什么是鏈表例如:structStudent//定義結構體類型Student{charname[20];//name和score存放用戶要用的數據
floatscore;structStudent*next;//next是指針變量,指向結構體變量}每個結點都屬于structStudent類型,next是structStudent類型的成員,同時又指向structStudent類型的數據,通過此方法,可建立鏈表。鏈表存儲具有以下特點:1)插入、刪除結點時,只用改變結點中指針域的值即可。2)查找操作需要從“頭指針”開始順序查找,不適合有頻繁查找操作的表。3)可實現動態分配和擴展空間(需用到和動態內存分配相關的函數:malloc、calloc、realloc、free等)。返回9.3.2建立簡單的靜態鏈表所有結點都在程序中定義,不臨時開辟,也不能用完后釋放,這種鏈表稱為靜態鏈表。例9.11在以下程序(2011年9月全國計算機等級考試二級C試題選擇題第37題)#include<stdio.h>main(){structnode//聲明結構體類型structnode{intn;structnode*next;//next為指針變量,指向結構體變量}*p;structnodex[3]={{2,x+1},{4,x+2},{6,NULL}};//定義結構體數組p=x;//p指向數組x的第一個成員printf(“%d,”,p->n);printf(“%d\n”,p->next->n);}程序運行后的輸出結果是A)2,3 B)2,4 C)3,4 D)4,69.3.2建立簡單的靜態鏈表例9.11分析:此題中,結構體數組初始化值后相當于:x[0].n=2,結點x[1]的起始地址賦給x[0]的next成員;x[1].n=4,結點x[2]的起始地址賦給x[1]的next成員;x[2].n=6,x[2]的next成員不存儲其它結點地址,這樣就形成了鏈表。“p->n”,表示p指向的結點的數據,因為p指向的是數組的x的第一個元素x[0],所以p->n的值為2。“p->next”,表示p指向下一個結點。p->next指向的是x+1,即指向的是數組x的第二個元素x[1],所以,p->next->n的值為4。所以選B。返回9.3.3建立動態鏈表所謂建立動態鏈表,是指程序執行過程中一個一個的開辟結點和輸入各結點數據,并建立起前后鏈接的關系。建立過程中,要首先定義一個包含數據域和指針域的結構類型,然后定義一個“頭指針”,最后要調用前面所學的malloc函數動態申請結點的方法建立整個鏈表。9.3.3建立動態鏈表例9.12建立學生信息鏈表,學生信息包括學號和成績。學號輸入為零時結束鏈表建立。#include<stdio.h>#include<malloc.h>//調用動態存儲分配函數#defineLENsizeof(structstudent)//定義符號常量LENstructstudent//定義結構體類型structstudent{longnum;floatscore;structstudent*next;};intn;//n為全局變量,表示結點個數(后續。。。)9.3.3建立動態鏈表structstudent*creat(void)//定義函數,此函數返回一個指向鏈表頭的指針{structstudent*head;//定義指針head指向structstudent類型數據
structstudent*p1,*p2;//定義指針p1和p2指向structstudent類型數據
n=0;//結點數目為0p1=p2=(structstudent*)malloc(LEN);//用malloc函數開辟第一結點,并使p1和p2指向它
scanf("%ld,%f",&p1->num,&p1->score);//從鍵盤輸入一個學生的信息給p1所指的第1個結點
head=NULL;//使head為空,即head不指向任何結點,鏈表中無結點
while(p1->num!=0)//控制p1->num不為0(約定輸入的學號為0,則表示鏈表建立的過程完成,該結點不鏈接到鏈表中)
{n=n+1;if(n==1)head=p1;//n==1,輸入的是第1個結點數據,把p1的值賦給head,即使head指向新開辟的結點elsep2->next=p1;//把p1所指的結點鏈接到表尾(p2所指的結點)p2=p1;//將p2移動到表尾p1=(structstudent*)malloc(LEN);//再開辟一個新結點,使p1指向新結點scanf("%ld,%f",&p1->num,&p1->score);//讀入新的學生數據給p1所指結點}p2->next=NULL;//指向表尾結點的指針變量置NULLreturn(head);//返回鏈表中第1個結點的起始地址}9.3.3建立動態鏈表可以編寫主函數,調用creat函數,如要輸出第2個結點成員的值intmain(){structstudent*pt;pt=creat();//函數返回鏈表第一個結點的地址printf("\nnum:%ld\nscore:%5.1f\n",pt->next->num,pt->next->score);//輸出第二個結點的成員值
return0;};運行結果:1001,85.51002,921003,65.50,0num:1002score:92返回9.3.4結點數據的輸出、刪除與插入1.結點數據的輸出2.結點數據的刪除3.結點數據的插入9.3.4結點數據的輸出、刪除與插入1.結點數據的輸出將鏈表中各結點的數據依次輸出,首先要知道鏈表第一個結點的地址,也就是要知道head的地址,然后設置一個指針變量p,指向第一個結點,輸出p所指的結點,然后使p移到下一個結點并輸出,直到鏈表的尾結點。結點數據輸出操作程序為:voidprint(structstudent*head)//定義print函數,輸出structstudent鏈表中的數據{structstudent*p;//在函數中定義structstudent類型的變量pprintf("\nNow,These%drecordsare:\n",n);p=head;//使p指向第一個結點
if(head!=NULL)//若不是空表
do{printf("%ld%5.1f\n",p->num,p->score//輸出一個結點中的學號與成績
p=p->next;//p指向下一個結點
}while(p!=NULL);//當p不是“空地址”
}9.3.4結點數據的輸出、刪除與插入2.結點數據的刪除如圖所示,在單鏈表L中,要刪除第i個結點,只需將第i-1個結點的指針域指向第i+1個結點,并且釋放第i個結點所占的存儲空間(調用free函數)。所以,刪除操作程序可表示如下:voidDelete_L(NODE*L,inti,intx)//定義Delete_L函數,在線性鏈表L中,刪除第i個元素{NODE*p=L,*q;intj=0;while(p->next&&j<i-1){p=p->next;++j};//尋找第i個結點,并令p指向其前驅
if(!(p->next)||j>i-1)return(0);//表示刪除位置錯誤
q=p->next;p->next=q->next;free(q);//刪除并釋放結點
return(1);}9.3.4結點數據的輸出、刪除與插入3.結點數據的插入如圖9.8所示,要在鏈表L中的第i-1個結點和第i個結點中插入數據元素x,首先應將指針指向結點i-1,然后生成一個新結點(調用malloc函數),數據域存放x,結點i-1的指針域指向新結點x,x的指針域指向結點i。所以,插入操作程序可表示如下:9.3.4結點數據的輸出、刪除與插入voidInsert_L(NODE*L,inti,intx)//定義Insert_L函數,在鏈表L中第i個位置之前插入元素x{NODE*p=L.*s;intj=0;while(p&&j<i-1){p=p->next;++j};//尋找第i-1個結點
if(!p||j>i-1)return(0);//表示插入位置錯誤
s=(NODE*)malloc(sizeof(NODE));//生成新結點
s->data=x;s->next=p->next;p->next=s;//將結點插入到鏈表中
return(1);}}【注意】以上結點輸出、刪除和插入的函數可單獨編譯,但都不能單獨運行。在具體的鏈表結構中,根據實際情況改變函數中的結構體類型并調用相應函數以完成輸出、刪除和插入的操作。9.4用typedef聲明新類型名C語言中,除了可使用C提供的標準類型名(如int、float)等,以及使用編寫者自己構造的結構體、共用體類型外,還可以用typedef指定新的類型名來替代已有的類型名。一般格式:typedef類型名新名稱類似于定義變量,將變量名稱換為新類型名,并且在最前面加上“typedef”即可。例如:typedefintInteger//指定Integer代表int,作用同int相同此時,“intm,n;”與“Integerm,n;”等價typedeffloatReal//指定Real代表int,作用同float相同此時,“floata,b;”與“Reala,b;”等價9.4用typedef聲明新類型名使用typedef,也可以用簡單的類型名替代復雜的類型,比如替代結構體類型、共用體類型、指針類型、數組類型等。主要有以下幾種形式:1.定義一個新的類型名代表結構體類型2.定義一個新的類型名代表數組類型3.定義一個新的類型名代表指針類型4.定義一個新的類型名代表指向函數的指針類型9.4用typedef聲明新類型名1.定義一個新的類型名代表結構體類型:例如:typedefstruct//定義類型名Date表示結構體類型{intmonth;
intday;intyear;}Date;Datebirthday;//用Date定義結構體變量birthdayDate*p;//用Date定義結構體指針變量p,指向此結構體類型數據9.4用typedef聲明新類型名2.定義一個新的類型名代表數組類型:例如:typedefintArr[20];//定義類型名Arr表示整型數組類型Arra,b;//定義a,b都為包含20個元素的一維數組9.4用typedef聲明新類型名3.定義一個新的類型名代表指針類型例如:typedefchar*String;//定義類型名String表示字符指針類型Stringp,s[10];//定義p為字符指針變量,s為字符指針數組9.4用typedef聲明新類型名4.定義一個新的類型名代表指向函數的指針類型例如:typedefint(*Pointer)();//定義類型名Pointer表示指向函數的指針類型Pointerp1,p2;//定義P1,p2為Pointer類型的指針變量【說明】①用typedef可以定義各種類型名,但不能直接用來定義變量。②用typedef只是對已存在的類型增加一個新的類型名稱,并不構造新類型。③在不同源文件中使用同一類型數據,常使用typedef說明這些數據類型,并單獨存放在一個文件中,在需要時,用#include命令包含進來。9.4用typedef聲明新類型名例9.13:若有以下語句(2010年9月全國計算機等級考試二級C試題選擇題第39題)typedefstructS
{intg;charh;}T;以下敘述中正確的是A)可用S定義結構體變量 B)可用T定義結構體變量C)S是struct
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026年秋季初中新生軍訓 軍訓中的感恩教育
- 2026年電子商務行業新模式與新業態發展報告
- 2027年云南林業職院高職單招職業技能考試模擬試卷帶答案詳解(培優A卷)
- 2024年龍湖智造職業學院高職單招職業技能考試題庫附參考答案詳解(預熱題)
- 2024年巴盛職業學院高職單招職業技能考試題庫及答案詳解(真題匯編)
- 2025年柘林湖職業學院單招職業技能考試模擬試卷含答案詳解(綜合卷)
- 2026年菏澤家政職業學院高職單招職業適應性測試考試題庫含答案詳解【預熱題】
- 2024年江西外語外貿職業學院單招綜合素質考試題庫及答案詳解(典優)
- 2026年武當山文旅職業學院高職單招職業適應性測試考試題庫1套附答案詳解
- 2025年長沙黑麋峰職業學院單招綜合素質考試模擬試卷(模擬題)附答案詳解
- 2025-2030商業航天產業發展政策環境與市場增長空間報告
- 乙醇(酒精)化學品安全技術說明書(MSDS-SDS)
- 2026年高速公路監控考試題庫及答案
- 初中九年級物理上冊期中考試題及答案【完整版】
- 企業年度評優與表彰管理辦法
- 高處作業人員安全教育培訓
- 初中歷史材料分析題答題技巧
- 輸液安全警示教育
- 學院學生宿舍管理服務項目方案投標文件(技術方案)
- 2026青島東鼎產業發展集團有限公司招聘筆試備考題庫及答案解析
- 社會組織內部薪酬制度
評論
0/150
提交評論