版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第9章結(jié)構(gòu)體、共用體和用戶定義類型前言9.1結(jié)構(gòu)體9.2共用體9.3用指針處理鏈表9.4用typedef聲明新類型名
前 言問題:一個學(xué)生的信息包括姓名(char型)、性別(char型)、年齡(int型)、學(xué)號(int型)、成績(float型)等。我們?nèi)绻謩e定義互相獨立的簡單變量,顯然難以反映這些數(shù)據(jù)信息的內(nèi)在聯(lián)系。而數(shù)據(jù)類型不同,也不能通過數(shù)組來存放。C語言允許用戶根據(jù)需要自己建立一些數(shù)據(jù)類型,比如可將上述一個學(xué)生的不同類型的數(shù)據(jù)信息共同存放于構(gòu)造類型——結(jié)構(gòu)體或者共用體中,同時,C語言也允許使用如typedef等來定義說明一個新的數(shù)據(jù)類型。9.1結(jié)構(gòu)體9.1.1結(jié)構(gòu)體類型數(shù)據(jù)的定義
9.1.2結(jié)構(gòu)體類型數(shù)據(jù)成員的引用
9.1.3結(jié)構(gòu)體數(shù)組
9.1.4結(jié)構(gòu)體指針9.1.1結(jié)構(gòu)體類型數(shù)據(jù)的定義用戶建立由不同類型數(shù)據(jù)組成的組合型的數(shù)據(jù)結(jié)構(gòu),稱之為結(jié)構(gòu)體類型,組成結(jié)構(gòu)體類型的每一個數(shù)據(jù)稱之為該結(jié)構(gòu)體類型的成員。在使用結(jié)構(gòu)體類型時,首先要對結(jié)構(gòu)體類型的組成進行說明,稱之為結(jié)構(gòu)體類型的定義。格式:struct結(jié)構(gòu)體標(biāo)識名
{
數(shù)據(jù)類型結(jié)構(gòu)體成員名1;數(shù)據(jù)類型結(jié)構(gòu)體成員名2;
…
數(shù)據(jù)類型結(jié)構(gòu)體成員名n;
};其中:“struct”為定義結(jié)構(gòu)體類型的關(guān)鍵字。例如:以上學(xué)生的信息可定義為下列一個名為Student的結(jié)構(gòu)體類型:structStudent//Student為結(jié)構(gòu)體標(biāo)識名
{charname[20];//每個成員項以分號(;)結(jié)束
charsex;
intage;
intnum;
floatscore;
};//結(jié)構(gòu)體定義以分號(;)結(jié)束以上定義中,結(jié)構(gòu)體類型Student由5個成員組成。9.1.1結(jié)構(gòu)體類型數(shù)據(jù)的定義結(jié)構(gòu)體類型的成員也可以包含另一個結(jié)構(gòu)體類型,形成結(jié)構(gòu)類型嵌套。例如:structDate{intmonth;
intday;
intyear;
};structStudent{charname[20];
charsex;
structDatebirthday;floatscore;
intnum;
};structStudent類型的結(jié)構(gòu)如右圖:9.1.1結(jié)構(gòu)體類型數(shù)據(jù)的定義當(dāng)結(jié)構(gòu)體類型定義后,就可以指定該結(jié)構(gòu)體類型的具體對象,即定義結(jié)構(gòu)體類型的變量,稱之為結(jié)構(gòu)體變量。定義結(jié)構(gòu)體變量可采取以下三種形式:1.聲明結(jié)構(gòu)體標(biāo)識名后,再定義結(jié)構(gòu)體變量2.聲明結(jié)構(gòu)體標(biāo)識的同時定義結(jié)構(gòu)體變量3.不指定結(jié)構(gòu)體標(biāo)識名而直接定義結(jié)構(gòu)體變量9.1.1結(jié)構(gòu)體類型數(shù)據(jù)的定義1.聲明結(jié)構(gòu)體標(biāo)識名后,再定義結(jié)構(gòu)體變量格式:struct結(jié)構(gòu)體標(biāo)識名結(jié)構(gòu)體變量名表例如:在前面聲明了結(jié)構(gòu)體類型Student后,再來定義結(jié)構(gòu)體變量stu1和stu2。structStudentstu1,stu2;這種形式和定義其它類型變量形式相似(如inta,b;)。變量stu1和stu2則具有Student類型的數(shù)據(jù)結(jié)構(gòu),是由多個數(shù)據(jù)成員組成的構(gòu)造類型的變量,如下圖所示:在定義了結(jié)構(gòu)體變量后,系統(tǒng)會為之分配內(nèi)存單元,stu1和stu2分別占據(jù)一段連續(xù)的存儲單元,在VisualC++環(huán)境中,stu1和stu2分別占據(jù)33字節(jié)(name20個字節(jié),sex1個字節(jié),age4個字節(jié),num4個字節(jié),score4個字節(jié))。9.1.1結(jié)構(gòu)體類型數(shù)據(jù)的定義2.聲明結(jié)構(gòu)體標(biāo)識的同時定義結(jié)構(gòu)體變量格式:struct結(jié)構(gòu)體標(biāo)識名
{
數(shù)據(jù)類型結(jié)構(gòu)體成員名1;數(shù)據(jù)類型結(jié)構(gòu)體成員名2;
…
數(shù)據(jù)類型結(jié)構(gòu)體成員名n;
}結(jié)構(gòu)體變量名表;例如:在前面聲明了結(jié)構(gòu)體類型Student的同時定義結(jié)構(gòu)體變量stu1和stu2。structStudent{charname[20];
charsex;
intage;
intnum;
floatscore;
}stu1,stu2;9.1.1結(jié)構(gòu)體類型數(shù)據(jù)的定義3.不指定結(jié)構(gòu)體標(biāo)識名而直接定義結(jié)構(gòu)體變量格式:struct//不需要指定結(jié)構(gòu)體標(biāo)識名
{
數(shù)據(jù)類型結(jié)構(gòu)體成員名1;數(shù)據(jù)類型結(jié)構(gòu)體成員名2;
…
數(shù)據(jù)類型結(jié)構(gòu)體成員名n;
}結(jié)構(gòu)體變量名表;例如:采用此方法定義結(jié)構(gòu)體變量stu1和stu2。struct{charname[20];
charsex;
intage;
intnum;
floatscore;
}stu1,stu2;【注意】此方法指定的是個無名的結(jié)構(gòu)體類型,所以該結(jié)構(gòu)體類型不能再定義其它變量?!菊f明】①結(jié)構(gòu)體類型與結(jié)構(gòu)體變量是不同的概念,不要混同。只能對變量賦值、存取或運算,而不能對一個類型賦值、存取或運算。②結(jié)構(gòu)體變量中的成員可以單獨使用,運算方式和普通變量相同。③結(jié)構(gòu)體類型中的成員名可以與程序中的變量名相同,但二者不代表同一對象。9.1.1結(jié)構(gòu)體類型數(shù)據(jù)的定義例9.1下面結(jié)構(gòu)體的定義語句中,錯誤的是(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)采用的先聲明結(jié)構(gòu)體類型,再定義結(jié)構(gòu)體變量的方式,格式正確;C)采用的聲明結(jié)構(gòu)體類型的同時定義結(jié)構(gòu)體變量的方式,格式正確;D)采用的不指定結(jié)構(gòu)體類型而直接定義結(jié)構(gòu)體變量的方式,格式正確;B)在聲明結(jié)構(gòu)體類型后沒有用分號結(jié)束,選B。返回9.1.2結(jié)構(gòu)體類型數(shù)據(jù)成員的引用在定義了結(jié)構(gòu)體變量后,就可以引用該結(jié)構(gòu)體變量,執(zhí)行賦值、存取和運算等操作。在引用結(jié)構(gòu)體變量時,主要是通過引用結(jié)構(gòu)體變量的各個成員來實現(xiàn)各種操作。引用結(jié)構(gòu)體變量的成員的方式為:格式:結(jié)構(gòu)體變量名.成員名9.1.2結(jié)構(gòu)體類型數(shù)據(jù)成員的引用例9.2把一個學(xué)生的信息(包括姓名、性別、年齡、學(xué)號、成績)放在一個結(jié)構(gòu)體變量中,然后輸出這個學(xué)生的信息。#include<stdio.h>intmain(){structStudent//聲明Student為結(jié)構(gòu)體類型
{charname[20];//以下五行為結(jié)構(gòu)體的成員
charsex;intage;intnum;floatscore;}a={“LiLin”,‘M’,18,10101,86.5};//定義結(jié)構(gòu)體變量a并初始化
printf("name:%s\nsex:%c\nage:%d\nNO.:%d\nscore:%4.1f\n",,a.sex,a.age,a.num,a.score);return0;}運行結(jié)果:name:LiLinsex:Mage:18NO.:10101score:結(jié)構(gòu)體類型數(shù)據(jù)成員的引用【例9.2說明】①“.”是成員運算符,它在所有運算符中優(yōu)先級最高??烧J為a.XX為一個整體。②在定義結(jié)構(gòu)體變量的同時可以對它的成員初始化,初始化方式和數(shù)組的初始化類似,用花括號括起來一些常量,這些常量依次對結(jié)構(gòu)體變量中的各成員賦值。③在引用結(jié)構(gòu)體變量時,不能將一個結(jié)構(gòu)體變量作為一個整體處理,而應(yīng)當(dāng)通過對該結(jié)構(gòu)體變量的各個成員項的引用實現(xiàn)相應(yīng)操作。若上述例題中輸出寫成printf("name:%s\nsex:%c\nage:%d\nNO.:%d\nscore:%4.1f\n",a)錯誤。④可以引用結(jié)構(gòu)體成員地址和結(jié)構(gòu)體變量地址。如:scanf(“%d“,&a.num);作用是從鍵盤為成員a.num提供值。printf(“%o“,&a);作用是輸出a的首地址。但不能用以下方法整體讀入結(jié)構(gòu)體變量:scanf(”%s,%c,%d,%d,%f“,&a)。⑤若成員本身又屬于一個結(jié)構(gòu)體類型,只能對最低級的成員進行賦值、存取以及運算。如:stu1.birthday.year=1986⑥結(jié)構(gòu)體變量成員可以象普通變量一樣進行各種運算,如:stu1.age=stu2.age(賦值運算);sum==stu1.age+stu2.age(加法運算)。同類的結(jié)構(gòu)體變量可以互相賦值,如stu1=stu2。9.1.2結(jié)構(gòu)體類型數(shù)據(jù)成員的引用例9.3設(shè)有定義:(2009年9月全國計算機等級考試二級C試題填空題第12題)structperson{intID;charname[12];}p;請將scanf(“%d”,
);語句補充完整,使其能夠為結(jié)構(gòu)體變量p的成員ID正確讀入數(shù)據(jù)。分析:在對結(jié)構(gòu)體成員提供值時,應(yīng)分別對各成員按變量方式處理。此題中,變量p的成員ID為int型數(shù)據(jù),輸入時,把p.ID看做一個整體,引用其地址,所以輸入格式為:scanf(“%d”,&p.ID)。例9.4設(shè)有定義:(2011年3月全國計算機等級考試二級C試題選擇題第36題)struct{charmark[12];intnum1;doublenum2;}t1,t2;設(shè)有若變量均已正確賦初值,則以下語句中錯誤的是A)t1=t2; B)t2.num1=t1.num1;C)t2.mark=t1.mark;D)t2.num2=t1.num2;分析:定義為同類型的結(jié)構(gòu)體變量可互相賦值,A)正確;結(jié)構(gòu)體變量成員和普通變量的運算規(guī)則相同,所以整型數(shù)據(jù)、雙精度實數(shù)型數(shù)據(jù)都可直接賦值,B)、D)正確。用賦值語句將一個字符數(shù)組直接給一個字符數(shù)組是不合法的,C)錯誤。選C9.1.2結(jié)構(gòu)體類型數(shù)據(jù)成員的引用例9.5有以下程序:(2010年3月全國計算機等級考試二級C試題選擇題第37題)#include<stdio.h>#include<string.h>structA//定義結(jié)構(gòu)體類型A{inta;charb[10];doublec;};voidf(structAt);//定義函數(shù)fmain(){structAa={1001,"ZhangDa",1098.0};//定義結(jié)構(gòu)體變量a并進行初始化操作f(a);//調(diào)用f函數(shù),結(jié)構(gòu)體變量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;}程序運行后的輸出結(jié)果是A)1001,zhangDa,1098.0 B)1002,changRong,1202.0C)1001,ehangRong,1098.0 D)1002,ZhangDa,1202.09.1.2結(jié)構(gòu)體類型數(shù)據(jù)成員的引用例9.5分析:本題中函數(shù)調(diào)用的形式為傳值調(diào)用,不會改變?nèi)魏沃?。所以輸出結(jié)果仍是結(jié)構(gòu)體變量a原來的成員的初始值。選A。【說明】將一個結(jié)構(gòu)體變量的值傳遞給另一個函數(shù)有三種形式:①結(jié)構(gòu)體變量的成員作為參數(shù),如用a.a作為實參,將實參值傳遞給形成。用法同普通變量作實參相同,是“按值傳遞”。需要保持實參和形參類型一致。②用結(jié)構(gòu)體變量作為實參,同樣采用“按值傳遞”的方式,不過是將結(jié)構(gòu)體變量所有成員值按順序傳遞給形參。注意形參和實參的結(jié)構(gòu)類型相同,但運行時占用不同的存儲空間,調(diào)用時,被調(diào)函數(shù)不能修改調(diào)用函數(shù)實參的值。③用結(jié)構(gòu)體指針變量作為實參,即將結(jié)構(gòu)體變量的首地址傳遞給形參,即“按地址傳遞”。此時,實參和形參所指向的是同一組內(nèi)存單元。返回9.1.3結(jié)構(gòu)體數(shù)組結(jié)構(gòu)體數(shù)組就是指數(shù)組中的每一個數(shù)組元素都是結(jié)構(gòu)體類型變量。定義結(jié)構(gòu)體數(shù)組方式和定義結(jié)構(gòu)體變量相同。格式:struct結(jié)構(gòu)體名{結(jié)構(gòu)體成員表列}數(shù)組名【數(shù)組長度】也可以先聲明結(jié)構(gòu)體類型,如structPerson,然后再用此類型定義結(jié)構(gòu)體數(shù)組:結(jié)構(gòu)體類型數(shù)組名【數(shù)組長度】結(jié)構(gòu)體數(shù)組初始化形式和數(shù)組賦初值的方式相同。在定義數(shù)組的后面加上:={初值表列};由于數(shù)組中的每個元素都是一個結(jié)構(gòu)體變量,通常將一個數(shù)組元素的成員放在一對花括號中,以區(qū)分各個元素。結(jié)構(gòu)體數(shù)組的引用指對結(jié)構(gòu)體數(shù)組元素的引用,引用結(jié)構(gòu)體變量的方法適用于結(jié)構(gòu)體數(shù)組元素。格式:數(shù)組元素名稱.成員名結(jié)構(gòu)體數(shù)組元素可賦值給同一結(jié)構(gòu)體數(shù)組中的另一個元素,或者賦值給同類型的變量。9.1.3結(jié)構(gòu)體數(shù)組例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));}程序運行后的輸出結(jié)果是A)10 B)11 C)20 D)21分析:定義結(jié)構(gòu)體數(shù)組變量data賦初值后,相當(dāng)于data[0].a=10,data[0].b=100,data[1].a=20,data[1].b=200;將data[1]賦值給結(jié)構(gòu)體變量p,即p.a=20,p.b=200。所以,++(p.a)的值為21,選D9.1.3結(jié)構(gòu)體數(shù)組例9.7輸入三個學(xué)生的信息,包括姓名,學(xué)號,性別,成績,輸出成績在90分以上(含90)的男生信息#include<stdio.h>structstudent//聲明結(jié)構(gòu)體類型student{charxm[20];intxh;charxb;floatcj;};voidmain(){structstudentstu[3];//聲明結(jié)構(gòu)體數(shù)組
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函數(shù)輸入每個學(xué)生的姓名、學(xué)號、性別、成績
}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);//按學(xué)號、姓名、性別、成績的順序輸出學(xué)生信息}9.1.3結(jié)構(gòu)體數(shù)組例9.7運行結(jié)果:liyang<回車>001,m,92.5<回車>wangling<回車>1002,f,95<回車>chenyang<回車>1003,m,86.5<回車>1001 liyang m 92.5【注意】本例中用scanf函數(shù)輸入各成員時,字符數(shù)組以回車作為字符串的輸入結(jié)束,其它變量都用“,”隔開。返回9.1.4結(jié)構(gòu)體指針指向結(jié)構(gòu)體的指針稱為結(jié)構(gòu)體指針變量。一個結(jié)構(gòu)體變量的起始地址就是這個結(jié)構(gòu)體變量的指針,結(jié)構(gòu)體指針也可以指向結(jié)構(gòu)體數(shù)組中的元素,即將結(jié)構(gòu)體數(shù)組的起始地址賦給指針變量。結(jié)構(gòu)體指針變量定義方式如下格式:struct結(jié)構(gòu)體類型*結(jié)構(gòu)體指針例如:structStudent*p;//p可以指向structStudent類型的變量或者數(shù)組元素9.1.4結(jié)構(gòu)體指針例9.8有以下定義和語句(2010年3月全國計算機等級考試二級C試題選擇題第38題)structworkers//聲明結(jié)構(gòu)體類型structworkers{intnum;charname[20];charc;struct{intday;intmonth;intyear;}s;
//成員s為另一個結(jié)構(gòu)體類型};structworkersw,*pw;//定義structworkers類型變量w,以及指向structworkers類型數(shù)據(jù)的指針變量pwpw=&w;//pw指向w,即將結(jié)構(gòu)體變量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結(jié)構(gòu)體指針例9.8分析:year屬于結(jié)構(gòu)體類型structworkers的成員結(jié)構(gòu)體類型s,所以要訪問到y(tǒng)ear需要逐級訪問,訪問方式為w.s.year.。D選項可以正確賦值。對year賦值,也可采取以下方式:(*pw).s.year=1980;pw->s->year=1980【說明】①(*pw)表示pw指向的結(jié)構(gòu)體變量,(*pw).s.year則表示pw指向的結(jié)構(gòu)體成員s的成員year。由于成員運算符“.”優(yōu)先于“*”,*pw兩側(cè)括號不能省。②為直觀方便,C語言允許把“(*pw).”形式用“pw->”形式替代,“->”稱為指向運算符,用于連接指針變量與其指向的結(jié)構(gòu)體變量的成員。所以,如果pw指向結(jié)構(gòu)體變量w,以下3種用法等價:1)w.成員名(如w.num)2)(*pw).成員名(如(*pw).num)3)pw->成員名(如pw->num)③指向運算符“->”優(yōu)先級最高,例如++p->num等同于++(p->num),即對p->num的值做自增運算。9.1.4結(jié)構(gòu)體指針例9.9有以下程序(2011年3月全國計算機等級考試二級C試題選擇題第37題)#include<stdio.h>structord//定義結(jié)構(gòu)體類型structord{intx,y;}dt[2]={1,2,3,4};//定義結(jié)構(gòu)體數(shù)組dt并對數(shù)組初始化main(){structord*p=dt;//定義指向structord類型數(shù)據(jù)的指針變量p,并且p指向結(jié)構(gòu)體數(shù)組dt的第一個元素的首地址printf("%d,",++(p->x));printf("%d\n",++(p->y));}程序運行后的輸出結(jié)果是A)1,2 B)4,1 C)3,4 D)2,39.1.4結(jié)構(gòu)體指針例9.9分析:此題中,定義的結(jié)構(gòu)體數(shù)組dt有兩個元素,每個元素包含兩個成員x和y。初始化值表示dt[0].x=1,dt[0].y=2,d[1].x=3,dt[1].y=4,p指向數(shù)組dt的第一個元素,即p->x=1,p->y=2,所以,++(p->x)=2,++(p->y)=3。選D【說明】①由于指向運算符“->”優(yōu)先級最高,++(p->x)等價于++p->x。②但如果要求輸出“(++p)->x”的值,則表示先使p增加1,此時,p指向的是數(shù)組的第2個元素的x成員值,輸出結(jié)果為3,,指針p的變化如圖9.4
指針p的變化示意圖9.2共用體9.2.1共用體類型數(shù)據(jù)的定義9.2.2共用體類型數(shù)據(jù)成員的引用
9.2.1共用體類型數(shù)據(jù)的定義C語言中,共用體類型數(shù)據(jù)和結(jié)構(gòu)體類型數(shù)據(jù)都屬于構(gòu)造類型。共用體類型數(shù)據(jù)在定義上與結(jié)構(gòu)體相似。區(qū)別在于,結(jié)構(gòu)體變量是各類型數(shù)據(jù)成員的集合,每個成員占用不同的存儲空間,結(jié)構(gòu)體變量所占內(nèi)存是各成員占的內(nèi)存和。而共用體變量所有成員共享同一段內(nèi)存單元,以最長的成員所占的內(nèi)存作為共用體變量的存儲空間;所有成員從同一地址開始存儲,采用覆蓋技術(shù),在某一時刻只能讓一個成員起作用。9.2.1共用體類型數(shù)據(jù)的定義定義共用體類型可采取以下方式:格式:union共用體標(biāo)識名{
數(shù)據(jù)類型1共用體成員名1;數(shù)據(jù)類型2共用體成員名2;
…
數(shù)據(jù)類型n共用體成員名n;};例如:unionData{inta;charc;floatx;};9.2.1共用體類型數(shù)據(jù)的定義共用體變量的定義和結(jié)構(gòu)體變量的定義相似,可采用以下三種形式:1.聲明共用體類型名后,再定義共用體變量2.聲明共用體標(biāo)識的同時定義共用體變量3.不指定共用體標(biāo)識名而直接定義共用體變量9.2.1共用體類型數(shù)據(jù)的定義1.聲明共用體類型名后,再定義共用體變量例如:unionData{inta;charc;floatx;};unionDatam,n;9.2.1共用體類型數(shù)據(jù)的定義2.聲明共用體標(biāo)識的同時定義共用體變量例如:unionData{inta;charc;floatx;}m,n;9.2.1共用體類型數(shù)據(jù)的定義3.不指定共用體標(biāo)識名而直接定義共用體變量例如:union{inta;charc;floatx;}m,n;9.2.1共用體類型數(shù)據(jù)的定義以上幾種定義形式中,共用體m和n等價,共用體m和n所占存儲空間相同。VC環(huán)境中,存儲空間分配方式如下圖所示:共用體變量m(n)在內(nèi)存中所占字節(jié)數(shù)是成員中最長的(整型和實型都是4個字節(jié))4個字節(jié);如果定義的是結(jié)構(gòu)體變量,所占內(nèi)存則為(4+1+4)=9個字節(jié)。返回9.2.2共用體類型數(shù)據(jù)成員的引用在定義了共用體變量后才能引用它,引用形式為引用共用體變量的成員,一般不能整體引用共用體變量(C99標(biāo)準中有例外)。引用共用體變量的一個成員方式為:格式:共用體變量名.成員名如在前面定義了m、n為共用體變量,可以引用其成員:m.c(引用共用體變量m中的字符變量c)【注意】C99標(biāo)準中允許同類型的共用體變量互相賦值。如:m=n9.2.2共用體類型數(shù)據(jù)成員的引用定義共用體變量的同時,只能對第一個成員的類型進行初始化。一般格式:union共用體標(biāo)識名共用體變量={第一個數(shù)據(jù)成員的類型值};例如:unionData{inta;charc;floatx;}m={6,‘a(chǎn)’,3.5}//錯誤,不能初始化三個成員,它們占用同一段內(nèi)存unionDatam={6};//正確,對共用體第一個成員整型a賦初值unionDatam={.c=‘M’};//C99允許對指定的成員賦初值【說明】①共用體類型在同一內(nèi)存單元可以存放不同類型的數(shù)據(jù),但在每一瞬間只能存放其中一個成員,即共用體變量只能存放一個值。9.2.2共用體類型數(shù)據(jù)成員的引用例如:unionData{inta;charc;floatx;}m;m.a=97;//將97按整數(shù)形式存放在共用體變量中,在內(nèi)存中最后一個字節(jié)存儲形式為“01100001”執(zhí)行輸出語句:printf(”%d”,m.a);//輸出整數(shù)97。將存儲信息按整數(shù)形式處理printf(”%c”,m.c);//輸出字符’a’。將存儲信息按字符形式處理printf(”%f”,m.x);//輸出實數(shù)0.000000。將存儲信息按浮點數(shù)形式處理②共用體存儲空間保留的是最后一次被賦值的成員的值。例如執(zhí)行以下賦值語句:m.c=’M’;m.f=3.5;m.a=6;共用體變量存放的是最后輸入的6,在引用時應(yīng)特別注意當(dāng)前共用體變量的存儲成員。③共用體變量的地址和它各成員的地址都是同一地址,都是從共用體變量空間的起點開始。④共用體類型可以出現(xiàn)在結(jié)構(gòu)體類型定義中,數(shù)組也可以是共用體的成員。⑤以前的C不能使用共用體變量作為函數(shù)參數(shù),也不能使用函數(shù)返回共用體變量,但可以用指向共用體變量的指針。C99允許共用體變量作為函數(shù)參數(shù)
9.2.2共用體類型數(shù)據(jù)成員的引用例9.10分析下列程序的運行結(jié)果#include<stdio.h>union//聲明共用體類型{inti;//以下兩行指定共用體成員
charc[2];}a;//聲明共用體變量aintmain(){charx;//定義字符變量xa.i=259;//對共用體變量成員整型i賦初值x=a.c[0];//以下三行交換數(shù)組元素a.c[0]和a.c[1]的值
a.c[0]=a.c[1];a.c[1]=x;printf("%d\n",a.i);return0;}運行結(jié)果:769分析:共用體變量成員a.i賦初值259,在共用體變量的內(nèi)存中存儲方式為“0000000100000011”,交換a.c[0]和a.c[1]的值后,內(nèi)存的存儲變?yōu)椤?000001100000001”,轉(zhuǎn)換成十進制輸出為769。9.3用指針處理鏈表9.3.1什么是鏈表
9.3.2建立簡單的靜態(tài)鏈表
9.3.3建立動態(tài)鏈表
9.3.4結(jié)點數(shù)據(jù)的輸出、刪除與插入
9.3.1什么是鏈表在前面的學(xué)習(xí)中,我們認識到數(shù)組是一批有先后次序的元素所組成的序列。在使用數(shù)組存放數(shù)據(jù)時,必須先定義固定的數(shù)組長度,而當(dāng)數(shù)組元素不確定時,需要開辟足夠大的存儲空間,顯然這會造成內(nèi)存空間的浪費。并且在數(shù)組中,插入或刪除元素時,需要移動其它元素。鏈表是一種常見而重要的數(shù)據(jù)結(jié)構(gòu)類型。鏈表和數(shù)組類似,也是一批有先后次序的序列。但是鏈表中的元素可動態(tài)的分配存儲單元,并且鏈表中的各元素在內(nèi)存中的地址可以不連續(xù),所以在鏈表中插入和刪除元素時也不需要移動其它元素。鏈表中,每一個元素稱為結(jié)點。結(jié)點是鏈表的基本存儲單位,每個結(jié)點之間可以占用不連續(xù)的內(nèi)存。結(jié)點與結(jié)點之間通過指針鏈接在一起,一個元素指向下一個元素,直到最后一個元素,該元素不再指向其它元素,稱之為“表尾”,“表尾”的地址存放一個空指針(NULL)。所以,每個結(jié)點至少應(yīng)包括兩部分:用戶需要用的實際數(shù)據(jù)和下一個結(jié)點的地址(用指針變量存放)。9.3.1什么是鏈表如圖9.6為最簡單的一種鏈表(單向鏈表)的結(jié)構(gòu)。如圖所示,鏈表有一個“頭指針”變量(圖中以head表示),它是指向鏈表表頭結(jié)點的指針。每個結(jié)點都包含數(shù)據(jù)信息(圖中的A、B、C、D)和下一結(jié)點的地址(圖中的1259、1326等)兩部分信息??梢?,鏈表結(jié)構(gòu)中,邏輯相連的數(shù)據(jù),其結(jié)點間的物理地址并不連續(xù)。要訪問某個元素,需要先找到它的上個元素提供的地址,逐個往前,所以最終需要通過“頭指針”(head)才可以訪問整個鏈表中的元素。9.3.1什么是鏈表由于結(jié)點可包含不同的數(shù)據(jù)類型,根據(jù)前面所學(xué),定義結(jié)點應(yīng)采用結(jié)構(gòu)體類型。一般形式:structnode{intdata;//用戶需要用的實際數(shù)據(jù)(數(shù)據(jù)域),注意不僅僅是整型structnode*next//下一個結(jié)點的地址(指針域)}9.3.1什么是鏈表例如:structStudent//定義結(jié)構(gòu)體類型Student{charname[20];//name和score存放用戶要用的數(shù)據(jù)
floatscore;structStudent*next;//next是指針變量,指向結(jié)構(gòu)體變量}每個結(jié)點都屬于structStudent類型,next是structStudent類型的成員,同時又指向structStudent類型的數(shù)據(jù),通過此方法,可建立鏈表。鏈表存儲具有以下特點:1)插入、刪除結(jié)點時,只用改變結(jié)點中指針域的值即可。2)查找操作需要從“頭指針”開始順序查找,不適合有頻繁查找操作的表。3)可實現(xiàn)動態(tài)分配和擴展空間(需用到和動態(tài)內(nèi)存分配相關(guān)的函數(shù):malloc、calloc、realloc、free等)。返回9.3.2建立簡單的靜態(tài)鏈表所有結(jié)點都在程序中定義,不臨時開辟,也不能用完后釋放,這種鏈表稱為靜態(tài)鏈表。例9.11在以下程序(2011年9月全國計算機等級考試二級C試題選擇題第37題)#include<stdio.h>main(){structnode//聲明結(jié)構(gòu)體類型structnode{intn;structnode*next;//next為指針變量,指向結(jié)構(gòu)體變量}*p;structnodex[3]={{2,x+1},{4,x+2},{6,NULL}};//定義結(jié)構(gòu)體數(shù)組p=x;//p指向數(shù)組x的第一個成員printf(“%d,”,p->n);printf(“%d\n”,p->next->n);}程序運行后的輸出結(jié)果是A)2,3 B)2,4 C)3,4 D)4,69.3.2建立簡單的靜態(tài)鏈表例9.11分析:此題中,結(jié)構(gòu)體數(shù)組初始化值后相當(dāng)于:x[0].n=2,結(jié)點x[1]的起始地址賦給x[0]的next成員;x[1].n=4,結(jié)點x[2]的起始地址賦給x[1]的next成員;x[2].n=6,x[2]的next成員不存儲其它結(jié)點地址,這樣就形成了鏈表?!皃->n”,表示p指向的結(jié)點的數(shù)據(jù),因為p指向的是數(shù)組的x的第一個元素x[0],所以p->n的值為2?!皃->next”,表示p指向下一個結(jié)點。p->next指向的是x+1,即指向的是數(shù)組x的第二個元素x[1],所以,p->next->n的值為4。所以選B。返回9.3.3建立動態(tài)鏈表所謂建立動態(tài)鏈表,是指程序執(zhí)行過程中一個一個的開辟結(jié)點和輸入各結(jié)點數(shù)據(jù),并建立起前后鏈接的關(guān)系。建立過程中,要首先定義一個包含數(shù)據(jù)域和指針域的結(jié)構(gòu)類型,然后定義一個“頭指針”,最后要調(diào)用前面所學(xué)的malloc函數(shù)動態(tài)申請結(jié)點的方法建立整個鏈表。9.3.3建立動態(tài)鏈表例9.12建立學(xué)生信息鏈表,學(xué)生信息包括學(xué)號和成績。學(xué)號輸入為零時結(jié)束鏈表建立。#include<stdio.h>#include<malloc.h>//調(diào)用動態(tài)存儲分配函數(shù)#defineLENsizeof(structstudent)//定義符號常量LENstructstudent//定義結(jié)構(gòu)體類型structstudent{longnum;floatscore;structstudent*next;};intn;//n為全局變量,表示結(jié)點個數(shù)(后續(xù)。。。)9.3.3建立動態(tài)鏈表structstudent*creat(void)//定義函數(shù),此函數(shù)返回一個指向鏈表頭的指針{structstudent*head;//定義指針head指向structstudent類型數(shù)據(jù)
structstudent*p1,*p2;//定義指針p1和p2指向structstudent類型數(shù)據(jù)
n=0;//結(jié)點數(shù)目為0p1=p2=(structstudent*)malloc(LEN);//用malloc函數(shù)開辟第一結(jié)點,并使p1和p2指向它
scanf("%ld,%f",&p1->num,&p1->score);//從鍵盤輸入一個學(xué)生的信息給p1所指的第1個結(jié)點
head=NULL;//使head為空,即head不指向任何結(jié)點,鏈表中無結(jié)點
while(p1->num!=0)//控制p1->num不為0(約定輸入的學(xué)號為0,則表示鏈表建立的過程完成,該結(jié)點不鏈接到鏈表中)
{n=n+1;if(n==1)head=p1;//n==1,輸入的是第1個結(jié)點數(shù)據(jù),把p1的值賦給head,即使head指向新開辟的結(jié)點elsep2->next=p1;//把p1所指的結(jié)點鏈接到表尾(p2所指的結(jié)點)p2=p1;//將p2移動到表尾p1=(structstudent*)malloc(LEN);//再開辟一個新結(jié)點,使p1指向新結(jié)點scanf("%ld,%f",&p1->num,&p1->score);//讀入新的學(xué)生數(shù)據(jù)給p1所指結(jié)點}p2->next=NULL;//指向表尾結(jié)點的指針變量置NULLreturn(head);//返回鏈表中第1個結(jié)點的起始地址}9.3.3建立動態(tài)鏈表可以編寫主函數(shù),調(diào)用creat函數(shù),如要輸出第2個結(jié)點成員的值intmain(){structstudent*pt;pt=creat();//函數(shù)返回鏈表第一個結(jié)點的地址printf("\nnum:%ld\nscore:%5.1f\n",pt->next->num,pt->next->score);//輸出第二個結(jié)點的成員值
return0;};運行結(jié)果:1001,85.51002,921003,65.50,0num:1002score:92返回9.3.4結(jié)點數(shù)據(jù)的輸出、刪除與插入1.結(jié)點數(shù)據(jù)的輸出2.結(jié)點數(shù)據(jù)的刪除3.結(jié)點數(shù)據(jù)的插入9.3.4結(jié)點數(shù)據(jù)的輸出、刪除與插入1.結(jié)點數(shù)據(jù)的輸出將鏈表中各結(jié)點的數(shù)據(jù)依次輸出,首先要知道鏈表第一個結(jié)點的地址,也就是要知道head的地址,然后設(shè)置一個指針變量p,指向第一個結(jié)點,輸出p所指的結(jié)點,然后使p移到下一個結(jié)點并輸出,直到鏈表的尾結(jié)點。結(jié)點數(shù)據(jù)輸出操作程序為:voidprint(structstudent*head)//定義print函數(shù),輸出structstudent鏈表中的數(shù)據(jù){structstudent*p;//在函數(shù)中定義structstudent類型的變量pprintf("\nNow,These%drecordsare:\n",n);p=head;//使p指向第一個結(jié)點
if(head!=NULL)//若不是空表
do{printf("%ld%5.1f\n",p->num,p->score//輸出一個結(jié)點中的學(xué)號與成績
p=p->next;//p指向下一個結(jié)點
}while(p!=NULL);//當(dāng)p不是“空地址”
}9.3.4結(jié)點數(shù)據(jù)的輸出、刪除與插入2.結(jié)點數(shù)據(jù)的刪除如圖所示,在單鏈表L中,要刪除第i個結(jié)點,只需將第i-1個結(jié)點的指針域指向第i+1個結(jié)點,并且釋放第i個結(jié)點所占的存儲空間(調(diào)用free函數(shù))。所以,刪除操作程序可表示如下:voidDelete_L(NODE*L,inti,intx)//定義Delete_L函數(shù),在線性鏈表L中,刪除第i個元素{NODE*p=L,*q;intj=0;while(p->next&&j<i-1){p=p->next;++j};//尋找第i個結(jié)點,并令p指向其前驅(qū)
if(!(p->next)||j>i-1)return(0);//表示刪除位置錯誤
q=p->next;p->next=q->next;free(q);//刪除并釋放結(jié)點
return(1);}9.3.4結(jié)點數(shù)據(jù)的輸出、刪除與插入3.結(jié)點數(shù)據(jù)的插入如圖9.8所示,要在鏈表L中的第i-1個結(jié)點和第i個結(jié)點中插入數(shù)據(jù)元素x,首先應(yīng)將指針指向結(jié)點i-1,然后生成一個新結(jié)點(調(diào)用malloc函數(shù)),數(shù)據(jù)域存放x,結(jié)點i-1的指針域指向新結(jié)點x,x的指針域指向結(jié)點i。所以,插入操作程序可表示如下:9.3.4結(jié)點數(shù)據(jù)的輸出、刪除與插入voidInsert_L(NODE*L,inti,intx)//定義Insert_L函數(shù),在鏈表L中第i個位置之前插入元素x{NODE*p=L.*s;intj=0;while(p&&j<i-1){p=p->next;++j};//尋找第i-1個結(jié)點
if(!p||j>i-1)return(0);//表示插入位置錯誤
s=(NODE*)malloc(sizeof(NODE));//生成新結(jié)點
s->data=x;s->next=p->next;p->next=s;//將結(jié)點插入到鏈表中
return(1);}}【注意】以上結(jié)點輸出、刪除和插入的函數(shù)可單獨編譯,但都不能單獨運行。在具體的鏈表結(jié)構(gòu)中,根據(jù)實際情況改變函數(shù)中的結(jié)構(gòu)體類型并調(diào)用相應(yīng)函數(shù)以完成輸出、刪除和插入的操作。9.4用typedef聲明新類型名C語言中,除了可使用C提供的標(biāo)準類型名(如int、float)等,以及使用編寫者自己構(gòu)造的結(jié)構(gòu)體、共用體類型外,還可以用typedef指定新的類型名來替代已有的類型名。一般格式:typedef類型名新名稱類似于定義變量,將變量名稱換為新類型名,并且在最前面加上“typedef”即可。例如:typedefintInteger//指定Integer代表int,作用同int相同此時,“intm,n;”與“Integerm,n;”等價typedeffloatReal//指定Real代表int,作用同float相同此時,“floata,b;”與“Reala,b;”等價9.4用typedef聲明新類型名使用typedef,也可以用簡單的類型名替代復(fù)雜的類型,比如替代結(jié)構(gòu)體類型、共用體類型、指針類型、數(shù)組類型等。主要有以下幾種形式:1.定義一個新的類型名代表結(jié)構(gòu)體類型2.定義一個新的類型名代表數(shù)組類型3.定義一個新的類型名代表指針類型4.定義一個新的類型名代表指向函數(shù)的指針類型9.4用typedef聲明新類型名1.定義一個新的類型名代表結(jié)構(gòu)體類型:例如:typedefstruct//定義類型名Date表示結(jié)構(gòu)體類型{intmonth;
intday;intyear;}Date;Datebirthday;//用Date定義結(jié)構(gòu)體變量birthdayDate*p;//用Date定義結(jié)構(gòu)體指針變量p,指向此結(jié)構(gòu)體類型數(shù)據(jù)9.4用typedef聲明新類型名2.定義一個新的類型名代表數(shù)組類型:例如:typedefintArr[20];//定義類型名Arr表示整型數(shù)組類型Arra,b;//定義a,b都為包含20個元素的一維數(shù)組9.4用typedef聲明新類型名3.定義一個新的類型名代表指針類型例如:typedefchar*String;//定義類型名String表示字符指針類型Stringp,s[10];//定義p為字符指針變量,s為字符指針數(shù)組9.4用typedef聲明新類型名4.定義一個新的類型名代表指向函數(shù)的指針類型例如:typedefint(*Pointer)();//定義類型名Pointer表示指向函數(shù)的指針類型Pointerp1,p2;//定義P1,p2為Pointer類型的指針變量【說明】①用typedef可以定義各種類型名,但不能直接用來定義變量。②用typedef只是對已存在的類型增加一個新的類型名稱,并不構(gòu)造新類型。③在不同源文件中使用同一類型數(shù)據(jù),常使用typedef說明這些數(shù)據(jù)類型,并單獨存放在一個文件中,在需要時,用#include命令包含進來。9.4用typedef聲明新類型名例9.13:若有以下語句(2010年9月全國計算機等級考試二級C試題選擇題第39題)typedefstructS
{intg;charh;}T;以下敘述中正確的是A)可用S定義結(jié)構(gòu)體變量 B)可用T定義結(jié)構(gòu)體變量C)S是struct
溫馨提示
- 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)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 工會福利招標(biāo)后合同書
- 《多發(fā)傷的救治》課件
- 2025年福州貨運從業(yè)資格考試題目和答案大全
- 2025年常州貨運資格證500道題庫
- 《復(fù)習(xí)免疫調(diào)節(jié)》課件
- 酒店業(yè)應(yīng)收款項回收策略
- 獨立辦公室租賃合同
- 商業(yè)中心卷簾門施工合同
- 酒店客戶信息移交辦法
- 釀酒廠食堂外包服務(wù)評估
- 2024-2025學(xué)年上學(xué)期天津六年級英語期末模擬卷1
- 餐飲行業(yè)智能點餐與外賣系統(tǒng)開發(fā)方案
- 2024-2025學(xué)年九年級數(shù)學(xué)上學(xué)期期末考試卷
- 水利工程特點、重點、難點及應(yīng)對措施
- 物業(yè)經(jīng)理轉(zhuǎn)正述職
- 24秋國家開放大學(xué)《企業(yè)信息管理》形考任務(wù)1-4參考答案
- 2024年共青團團課培訓(xùn)考試題庫及答案
- 2024年共青團入團考試測試題庫及答案
- 工程項目管理-001-國開機考復(fù)習(xí)資料
- 2022年全國應(yīng)急普法知識競賽試題庫大全-下(判斷題庫-共4部分-2)
- 第20課《人民英雄永垂不朽》課件+2024-2025學(xué)年統(tǒng)編版語文八年級上冊
評論
0/150
提交評論