C語言程序設(shè)計(jì)課件:結(jié)構(gòu)_第1頁
C語言程序設(shè)計(jì)課件:結(jié)構(gòu)_第2頁
C語言程序設(shè)計(jì)課件:結(jié)構(gòu)_第3頁
C語言程序設(shè)計(jì)課件:結(jié)構(gòu)_第4頁
C語言程序設(shè)計(jì)課件:結(jié)構(gòu)_第5頁
已閱讀5頁,還剩55頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

結(jié)構(gòu)和聯(lián)合C語言程序設(shè)計(jì)目錄content結(jié)構(gòu)的定義和使用1結(jié)構(gòu)數(shù)組與結(jié)構(gòu)指針2結(jié)構(gòu)在函數(shù)間的傳遞3位字段結(jié)構(gòu)4聯(lián)合5類型定義語句typedef6枚舉類型7綜合舉例8結(jié)構(gòu)的定義在標(biāo)準(zhǔn)C語言中,使用結(jié)構(gòu)可以把不同類型的數(shù)據(jù)存儲在一起在C語言程序中先定義結(jié)構(gòu),才能進(jìn)行結(jié)構(gòu)變量的定義和使用結(jié)構(gòu)是由不同數(shù)據(jù)類型的數(shù)據(jù)組成的。組成結(jié)構(gòu)的每個數(shù)據(jù)稱為該結(jié)構(gòu)的成員項(xiàng),簡稱成員在程序中使用結(jié)構(gòu),先要對結(jié)構(gòu)的組成進(jìn)行描述,稱為結(jié)構(gòu)的定義8.1結(jié)構(gòu)的定義和使用struct結(jié)構(gòu)名

{

數(shù)據(jù)類型成員名1;數(shù)據(jù)類型成員名2;

...........

數(shù)據(jù)類型成員名n;

};結(jié)構(gòu)定義規(guī)則結(jié)構(gòu)的定義以關(guān)鍵字struct作為標(biāo)識符,其后是定義的結(jié)構(gòu)名,兩者為特定結(jié)構(gòu)的類型標(biāo)識符。結(jié)構(gòu)名命名原則與變量名相同8.1.1結(jié)構(gòu)的定義每個成員項(xiàng)由其數(shù)據(jù)類型和成員名組成。每個成員項(xiàng)后用分號“;”作為結(jié)束符。整個結(jié)構(gòu)的定義也用分號作為結(jié)束符structEmployee{

charname[20];

charsex;

intold;

intwage;};結(jié)構(gòu)定義規(guī)則結(jié)構(gòu)的定義明確地描述了其組織形式。在程序執(zhí)行時,結(jié)構(gòu)的定義并不引起系統(tǒng)為該結(jié)構(gòu)分配內(nèi)存空間結(jié)構(gòu)Employee的定義,僅僅指定了在使用這種結(jié)構(gòu)時應(yīng)該按下圖所示的配置情況占用內(nèi)存,但這時并沒有實(shí)際占用內(nèi)存空間。8.1.1結(jié)構(gòu)的定義structEmployee{

charname[20];

charsex;

intold;

intwage;};程序一旦定義了一個結(jié)構(gòu)體,就相當(dāng)于定義了一個新的結(jié)構(gòu)類型,那么就可以把結(jié)構(gòu)名當(dāng)作像int、double等關(guān)鍵字一樣使用,用說明語句定義該形式結(jié)構(gòu)體的具體結(jié)構(gòu)變量,其格式為:結(jié)構(gòu)變量的定義在程序的數(shù)據(jù)說明部分給出:8.1.2結(jié)構(gòu)變量的定義<存儲類型>struct結(jié)構(gòu)名結(jié)構(gòu)變量名;structEmployeewang;結(jié)構(gòu)變量的定義將引起系統(tǒng)按照結(jié)構(gòu)定義時制定的內(nèi)存模式,為被定義的結(jié)構(gòu)變量分配一定的內(nèi)存空間。當(dāng)多個結(jié)構(gòu)變量使用結(jié)構(gòu)時,它們可以在一起定義:結(jié)構(gòu)變量使用內(nèi)存空間,具有一定的存儲類型。結(jié)構(gòu)變量的存儲類型概念、它的壽命、可見性及使用范圍與普通變量、數(shù)組完全一致在程序中,結(jié)構(gòu)變量的定義在該結(jié)構(gòu)的定義之后,對于尚未定義的結(jié)構(gòu),不能用它對任何結(jié)構(gòu)進(jìn)行說明8.1.2結(jié)構(gòu)變量的定義structEmployeewang,li,zhang;結(jié)構(gòu)的定義和結(jié)構(gòu)變量的定義也可以同時進(jìn)行,被定義的結(jié)構(gòu)變量直接在結(jié)構(gòu)定義的大括號}后給出一個結(jié)構(gòu)變量占用內(nèi)存的實(shí)際大小,可以利用sizeof運(yùn)算求出。8.1.2結(jié)構(gòu)變量的定義sizeof(運(yùn)算量)structEmployee{charname[20];charsex;intold;intwage;}wang,song,zhou;structEmployee{charname[20];charsex;intold;intwage;};structEmployeewang,song,zhou;結(jié)構(gòu)是不同數(shù)據(jù)類型的若干數(shù)據(jù)的集合體。在程序中使用結(jié)構(gòu)時,一般情況下不能把結(jié)構(gòu)作為一整體參加數(shù)據(jù)處理,而參加各種運(yùn)算和操作的是結(jié)構(gòu)的各個成員項(xiàng)數(shù)據(jù)。結(jié)構(gòu)的成員項(xiàng)用以下一般形式表示:結(jié)構(gòu)變量wang具有下列四個成員項(xiàng):8.1.3結(jié)構(gòu)變量的使用形式和初始化結(jié)構(gòu)變量名.成員名wang.sexwang.oldwang.wagestructEmployee{charname[20];charsex;intold;intwage;}wang;8.1.3結(jié)構(gòu)變量的使用形式和初始化

運(yùn)行結(jié)果:namesexoldteladrwanghaim34010-12345678beijinggaoyangf42021-87654321shanghai#include<stdio.h>//結(jié)構(gòu)的定義structEmployee{char*name;charsex;intold;char*tel;char*adr;};voidmain(){//結(jié)構(gòu)變量的定義

structEmployeewang,gao;//結(jié)構(gòu)變量的成員賦值

=“wanghai”;wang.sex=’M’;wang.old=34;wang.tel=;wang.adr="beijing";

="gaoyang";gao.sex=’F’;gao.old=42;gao.tel=;gao.adr="shanghai";//顯示結(jié)構(gòu)變量的成員內(nèi)容

printf(“namesexoldteladdress\n");printf(“\n");printf(“%-14s%-4c%-4d%-10s%-20s\n”,\,wang.sex,wang.old,\wang.tel,wang.adr);printf("%-14s%-4c%-4d%-10s%-20s\n",\,gao.sex,gao.old,\gao.tel,gao.adr);}例8.1

結(jié)構(gòu)的使用形式結(jié)構(gòu)的初始化在結(jié)構(gòu)說明的時給這個結(jié)構(gòu)的每個成員賦初值初始數(shù)據(jù)之間用逗號分隔,初始數(shù)據(jù)的個數(shù)與結(jié)構(gòu)成員項(xiàng)的個數(shù)應(yīng)該相同。每個初始數(shù)據(jù)必須符合與其對應(yīng)的成員項(xiàng)的數(shù)據(jù)類型。8.1.3結(jié)構(gòu)變量的使用形式和初始化struct結(jié)構(gòu)名結(jié)構(gòu)變量={初始數(shù)據(jù)};其功能等價于="wanghai";wang.sex=’M’;wang.old=34;wang.tel=;wang.adr="beijing";structEmployeewang={"wanghai",’M’,34,"123-1111","beijing"};結(jié)構(gòu)數(shù)組具有相同結(jié)構(gòu)的結(jié)構(gòu)也可以組成數(shù)組,稱它們?yōu)榻Y(jié)構(gòu)數(shù)組。說明形式:例如:說明了結(jié)構(gòu)數(shù)組man[],它有三個元素man[0]、man[1]和man[2],它們都是具有Employee結(jié)構(gòu)的結(jié)構(gòu)變量在定義結(jié)構(gòu)數(shù)組的同時可以用初始化列表給它的每個元素賦初值在對結(jié)構(gòu)數(shù)組進(jìn)行初始化時,方括號[]中的元素個數(shù)可以缺省結(jié)構(gòu)數(shù)組也具有數(shù)組的屬性,結(jié)構(gòu)數(shù)組名是結(jié)構(gòu)數(shù)組存儲首地址8.2結(jié)構(gòu)數(shù)組與結(jié)構(gòu)指針<存儲類型>struct結(jié)構(gòu)名結(jié)構(gòu)數(shù)組名[元素個數(shù)][={初值表}];structEmployeeman[3];8.2.1

運(yùn)行結(jié)果:編號姓名年齡地址電話1王偉20東八舍416室 875436412李玲21南三舍219室 875439453張利19東八舍419室 87543645結(jié)構(gòu)類型Data的數(shù)據(jù)長度:56字節(jié)結(jié)構(gòu)數(shù)組例8.2

結(jié)構(gòu)數(shù)組的使用#include<stdio.h>#defineSTUDENT3//用符號常量STUDENT表示學(xué)生人數(shù)structData{//定義一個結(jié)構(gòu)

charname[20];//姓名

shortage;//年齡

charadr[30];//地址

longtel;//電話號碼};voidmain(){structDataman[STUDENT]={//定義一個結(jié)構(gòu)數(shù)組并初始化

{"王偉",20,"東八舍416室",87543641},{"李玲",21,"南三舍219室",87543945},{"張利",19,"東八舍419室",87543645}};inti;//輸出顯示表頭提示信息printf(“編號\t姓名\t年齡\t地址\t電話\n\n");//輸出結(jié)構(gòu)數(shù)組的數(shù)據(jù)for(i=0;i<STUDENT;i++)printf(“%-d\t%-s\t%-d\t%-s\t%Ld\n”,\i+1,man[i].name,man[i].age,\man[i].adr,man[i].tel);//每個輸出項(xiàng)都左對齊,編號從1開始printf("\n結(jié)構(gòu)類型Data的數(shù)據(jù)長度:\%d字節(jié)。\n",sizeof(structData));}8.2.1結(jié)構(gòu)數(shù)組

運(yùn)行結(jié)果:

//輸入wangwangzhangzhangzhangzhangzhouzhougaogao//輸出wang:2zhang:4zhou:2gao:2例8.3

對候選人得票進(jìn)行統(tǒng)計(jì):設(shè)有4個候選人,N個人參加選舉,每次輸入一個得票的候選人的名字,要求最后輸出個人的得票結(jié)果。#include<stdio.h>#include<string.h>//宏定義,定義參加選舉人的個數(shù)#defineN10//結(jié)構(gòu)定義structperson{charname[20];intcount;};voidmain(){//結(jié)構(gòu)數(shù)組定義及初始化

structpersonleader[4]={\ {“wang”,0},{“zhang”,0},\ {“zhou”,0},{"gao",0}};charname[20],i,j;//模擬選舉過程,循環(huán)一次代表一次選舉

for(i=0;i<N;i++){gets(name);//在候選人中查找匹配的人

for(j=0;j<4;j++)if(strcmp(name,leader[j].name)==0)

{

leader[j].count++;break;}}printf("\n");

for(j=0;j<4;j++)printf(“%s:%d\n”,leader[j].name,\leader[j].count);}指向結(jié)構(gòu)的指針變量稱為結(jié)構(gòu)指針。結(jié)構(gòu)指針的運(yùn)算按地址計(jì)算規(guī)則進(jìn)行,定義格式為(結(jié)構(gòu)名必須是已經(jīng)定義過的結(jié)構(gòu)類型):例如:存儲類型是結(jié)構(gòu)指針變量本身的存儲類型由于結(jié)構(gòu)指針是指向整個結(jié)構(gòu)體而不是某個成員,因此結(jié)構(gòu)指針的增(減)量運(yùn)算,將跳過一個結(jié)構(gòu)變量的整體,指向內(nèi)存中下一個結(jié)構(gòu)變量或結(jié)構(gòu)數(shù)組中下一個元素,結(jié)構(gòu)指針本身的(物理)地址增量值取決于它所指的結(jié)構(gòu)變量的數(shù)據(jù)長度8.2.2<存儲類型>struct結(jié)構(gòu)名*結(jié)構(gòu)指針名[=初始地址值];結(jié)構(gòu)指針structEmployee*pman;structEmployee*pd;結(jié)構(gòu)體可以嵌套,即結(jié)構(gòu)體成員又是一個結(jié)構(gòu)變量或結(jié)構(gòu)指針例如在結(jié)構(gòu)嵌套中,當(dāng)結(jié)構(gòu)體的成員項(xiàng)具有由該結(jié)構(gòu)類型定義的結(jié)構(gòu)指針時,這種結(jié)構(gòu)體稱為遞歸結(jié)構(gòu)體8.2.2結(jié)構(gòu)指針structstudent{charname[20];shortage;charadr[30];structDateBirthDay;structDateStudyDate;}studt[300];structNode{//數(shù)據(jù)場,節(jié)點(diǎn)序號

intnum;//指針場,指向下一個節(jié)點(diǎn)的結(jié)構(gòu)指針

structNode*next;};使用結(jié)構(gòu)指針對結(jié)構(gòu)成員進(jìn)行引用時,有兩種形式:使用結(jié)構(gòu)成員訪問運(yùn)算符“.”

運(yùn)算符"."的優(yōu)先級比取內(nèi)容運(yùn)算符"*"高,所以需要使用圓括號結(jié)構(gòu)指針運(yùn)算符“->”(橫線加大于號)。它與前一種表示方法在意義上是完全等價的。8.2.2結(jié)構(gòu)指針

(*結(jié)構(gòu)指針名).成員名結(jié)構(gòu)指針名->成員名8.2.2例8.4

結(jié)構(gòu)指針的使用運(yùn)行結(jié)果:Todayis4/15/1990結(jié)構(gòu)指針#include<stdio.h>structDate//定義一個結(jié)構(gòu){intmonth;intday;intyear;};voidmain(){//定義一個結(jié)構(gòu)變量和結(jié)構(gòu)指針變量

structDatetoday,*date_p;//將結(jié)構(gòu)指針指向一個結(jié)構(gòu)變量

date_p=&today;//采用結(jié)構(gòu)指針給目標(biāo)變量賦值

date_p->month=4;date_p->day=15;date_p->year=1990;//采用結(jié)構(gòu)指針輸出目標(biāo)變量的數(shù)據(jù)

printf(“Todayis%d/%d/%d\n”,\date_p->month,date_p->day,\date_p->year);}8.2.2結(jié)構(gòu)指針例8.5

結(jié)構(gòu)指針運(yùn)算#include<stdio.h>structKey{char*keyword;intkeyno;};voidmain(){structKeykd[]={{“are”,123},\{“my”,456},{"you",789}};structKey*p;inta;charchr;p=kd;a=p->keyno;printf("p=%d,a=%d\n",p,a);a=++p->keyno;printf("p=%d,a=%d\n",p,a);a=(++p)->keyno;printf("p=%d,a=%d\n",p,a);a=(p++)->keyno;printf("p=%d,a=%d\n",p,a);p=kd;chr=*p->keyword;printf("p=%d,chr=%c(adr=%d)\n",\p,chr,p->keyword);chr=*p->keyword++;printf("p=%d,chr=%c(adr=%d)\n",\p,chr,p->keyword);chr=(*p->keyword)++;printf("p=%d,chr=%c(adr=%d)\n",\p,chr,p->keyword);chr=*p++->keyword;printf("p=%d,chr=%c(adr=%d)\n",\p,chr,p->keyword);chr=*++p->keyword;printf("p=%d,chr=%c(adr=%d)\n",\p,chr,p->keyword);}定義結(jié)構(gòu)chr=*(++(p->keyword))變化前指向目標(biāo)的成員chr=(*(p->keyword))++chr=*((p->keyword)++)chr=*(p->keyword)變化前指向目標(biāo)的成員結(jié)構(gòu)指針變量訪問成員a=++(p->keyno)變化后指向目標(biāo)的成員運(yùn)行結(jié)果:p=158,a=123p=158,a=124p=162,a=456p=166,a=456p=158,chr=a(adr=170)p=158,chr=a(adr=171)p=158,chr=r(adr=171)p=162,chr=s(adr=174)p=162,chr=y(adr=175)8.2.2例8.6

指向結(jié)構(gòu)數(shù)組的指針結(jié)構(gòu)指針運(yùn)行結(jié)果:No.NameSexAge10101LiLinM1810102ZhangfanM1910104WangMinF20#include<stdio.h>structstudent//定義一個結(jié)構(gòu){intNo;charname[20];charsex;intage;};voidmain(){//定義一個結(jié)構(gòu)數(shù)組并初始化

structstudentstu[3]={{10101,"LiLin",’M’,18},{10102,"Zhangfan",’M’,19},{10104,"WangMin",’F’,20}};//定義一個結(jié)構(gòu)指針變量

structstudent*p;printf("No.NameSexAge\n");for(p=stu;p<stu+3;p++)printf("%8d%-12s%6c%4d\n",\p->No,p->name,p->sex,p->age);}將一個結(jié)構(gòu)體變量的值傳遞給另一個函數(shù),有3種方法:用結(jié)構(gòu)體變量的成員作參數(shù)。用法和用普通變量作實(shí)參是一樣的,屬于“值傳遞”方式用結(jié)構(gòu)體變量作實(shí)參。在調(diào)用函數(shù)時,把結(jié)構(gòu)作為參數(shù)傳遞給函數(shù),采取的是“值傳遞”的方式,將結(jié)構(gòu)體變量所占的內(nèi)存單元的內(nèi)容全部順序傳遞給形參用結(jié)構(gòu)變量的地址或結(jié)構(gòu)數(shù)組的首地址作為實(shí)參。用指向相同結(jié)構(gòu)類型的結(jié)構(gòu)指針作為函數(shù)的形參來接受該地址值8.3結(jié)構(gòu)在函數(shù)間的傳遞8.3結(jié)構(gòu)在函數(shù)間的傳遞運(yùn)行結(jié)果:請輸入每天的工資:38.5(CR)請輸入年份:2000(CR)請輸入月份:10(CR)請輸入日:1(CR)從2000年元月1日到2000年10月1日的雇傭期限:275天應(yīng)付給你的工錢:10587.50元。例8.7

采用值傳遞在函數(shù)間傳遞結(jié)構(gòu)變量,計(jì)算雇傭天數(shù)和工資。#include<stdio.h>structDate{intday;intmonth;intyear;intyearday;charmon_name[4];};intday_of_year(structDatepd);voidmain(){structDateHireDate;floatlaborage;//存放每天的雇傭工資

printf("請輸入每天的工資:");scanf("%f",&laborage);printf("請輸入年份:");scanf("%d",&HireDate.year);printf("請輸入月份:");scanf("%d",&HireDate.month);printf("請輸入日:");scanf("%d",&HireDate.day);HireDate.yearday=day_of_year(HireDate);printf(“從%d年元月1日到%d年%d月%d\

日的雇傭期限:%d天,\n應(yīng)付給你的\

工錢:%-.2f元。\n",\HireDate.year,HireDate.year,HireDate.month,\HireDate.day,HireDate.yearday,\laborage*HireDate.yearday);}//計(jì)算某年某月某日是這一年的第幾天intday_of_year(structDatepd){intday_tab[2][13]={{0,31,28,31,30,31,30,31,31,30,31,30,31},//非閏年的每月天數(shù)

{0,31,29,31,30,31,30,31,31,30,31,30,31}};//閏年的每月天數(shù)

/*為了與月份一致,列號不使用為零的下標(biāo)號。行號為0是非閏年的每月天數(shù),為1是閏年的每月天數(shù)*/inti,day,leap;//leap為0是非閏年,為1是閏年

day=pd.day;//將當(dāng)月的天數(shù)加入

leap=pd.year%4==0&&//能被4整除的年份基本上

//是閏年

pd.year%100!=0||//能被100整除的年份不是閏年

pd.year%400==0;//能被400整除的年份又是閏年

//求從元月1日算起到這一天的累加天數(shù)

for(i=1;i<pd.month;i++)day+=day_tab[leap][i];returnday;}8.3結(jié)構(gòu)在函數(shù)間的傳遞例8.8

通信錄的建立和顯示程序(采用地址方式傳遞結(jié)構(gòu)變量)intinput(structAddress*pt){printf("Name?");gets(pt->name);if(pt->name[0]==‘0’)return0;printf("Address?");gets(pt->addr);printf("Telephone?");gets(pt->tel);return1;//正常返回1}voiddisplay(structAddress*pt,intn){inti;printf("nameaddresstel\n");printf("----------------------------------------------\n");for(i=0;i<n;i++,pt++)printf("%-15s%-30s%s\n",pt->name,\pt->addr,pt->tel);}#include<stdio.h>#defineMAX3structAddress//定義一個通信錄的結(jié)構(gòu){charname[20];charaddr[50];chartel[15];};intinput(structAddress*pt);//通信錄錄入函數(shù)voiddisplay(structAddress*pt,intn);//通信錄顯示函數(shù)voidmain(){structAddressman[MAX];//定義結(jié)構(gòu)數(shù)組

inti;for(i=0;i<MAX;i++)//建立通信錄

if(input(&man[i])==0)break;display(man,i);//顯示通信錄}input()函數(shù)用于以人機(jī)對話方式輸入數(shù)據(jù),它的形式參數(shù)pt是結(jié)構(gòu)指針,用來接收結(jié)構(gòu)地址display()函數(shù)顯示輸入結(jié)果。調(diào)用時,實(shí)參是結(jié)構(gòu)數(shù)組man[]的首地址8.3例8.8

通信錄的建立和顯示程序(采用地址方式傳遞結(jié)構(gòu)變量)結(jié)構(gòu)在函數(shù)間的傳遞//輸入該程序運(yùn)行結(jié)果為:Name?王偉Address?東八舍416室Telephone?87543641Name?李玲Address?南三舍219室Telephone?87543945Name?張利Address?東八舍419室Telephone?87543645//輸出nameaddresstel--------------------------------------------王偉東八舍416室87543641李玲南三舍219室87543945張利東八舍419室875436458.3例8.9

返回結(jié)構(gòu)變量的函數(shù)結(jié)構(gòu)在函數(shù)間的傳遞運(yùn)行結(jié)果:31.452051.4520#include<stdio.h>#include<stdlib.h>#include<math.h>structRecord//定義一個結(jié)構(gòu){charstr[20];intnum;};//函數(shù)原型聲明structRecordstr_add_int(structRecordx);voidmain(){structRecordp,s={“31.45”,20};p=str_add_int(s);printf("%s%d\n",s.str,s.num);printf("%s%d\n",p.str,p.num);}//形參x和實(shí)參s的類型一致structRecordstr_add_int(structRecordx){floate;e=atof(x.str);//將字符串x.str轉(zhuǎn)換為浮

//點(diǎn)數(shù)并賦給ee=e+x.num;//浮點(diǎn)數(shù)與整數(shù)相加

gcvt(e,5,x.str);//將浮點(diǎn)數(shù)e再轉(zhuǎn)換為字

//符串,并賦給x.strreturnx;//將處理后的結(jié)果(結(jié)構(gòu)

//變量)返回給調(diào)用函數(shù)}值傳遞,將結(jié)構(gòu)變量s傳遞給函數(shù),處理后再將結(jié)果通過return語句返回8.3例8.10

結(jié)構(gòu)指針型函數(shù)結(jié)構(gòu)在函數(shù)間的傳遞運(yùn)行結(jié)果:Enterthenumber:101//輸入number:101//輸出color:Gtype:c#include<stdio.h>#defineNULL0structSample//定義一個結(jié)構(gòu){intnum;charcolor;chartype;};structSample*find(structSample*pd,intn);voidmain(){intnum;structSample*result;//結(jié)構(gòu)指針變量定義

structSamplecar[]={{101,'G','c'},{210,'Y','m'},\

{105,'R','l'},{222,'B','s'},{308,'P','b'},{0,0,0}};printf("Enterthenumber:");scanf("%d",&num);//輸入查找樣品代號result=find(car,num);if(result->num!=NULL){printf("number:%d\n",result->num);printf("color:%c\n",result->color);printf("type:%c\n",result->type);

}elseprintf("notfound");//未找到,給出提示信息}structSample*find(structSample*pd,intn){inti;for(i=0;pd[i].num!=0;i++)if(pd[i].num==n)break;//找到,退出循環(huán)

if(pd[i].num!=NULL)returnpd+i;//返回查找結(jié)果

elsereturnNULL;}結(jié)構(gòu)指針型函數(shù)是以地址傳遞方式向調(diào)用它的函數(shù)返回結(jié)構(gòu)的數(shù)據(jù)。不僅可以返回某個結(jié)構(gòu)的地址,也可以返回結(jié)構(gòu)數(shù)組的地址,從而把函數(shù)中處理的若干結(jié)構(gòu)的數(shù)據(jù)返回給調(diào)用它的函數(shù)中8.4位字段結(jié)構(gòu)計(jì)算機(jī)應(yīng)用與過程控制、參數(shù)檢測和數(shù)據(jù)通信領(lǐng)域時,要求其應(yīng)用程序具有對外部設(shè)備借口硬件進(jìn)行控制和管理的功能。經(jīng)常使用的控制方式是向接口發(fā)送方式字或命令字,以及從接口讀取狀態(tài)自等與接口有關(guān)的命令字、方式和狀態(tài)字是以二進(jìn)制位為單位的字段組成的數(shù)據(jù),他們稱為位字段數(shù)據(jù)位字段數(shù)據(jù)是一種壓縮形式,數(shù)據(jù)整體沒有具體意義??偸且越M成它的位字段為處理對象。在C語言程序中,可以使用位操作(位邏輯與、或操作)對位字段進(jìn)行處理C語言還提供了處理位字段的另一種構(gòu)造類型——位字段結(jié)構(gòu)8.4位字段結(jié)構(gòu)位字段結(jié)構(gòu)是一種特殊形式的結(jié)構(gòu),其成員項(xiàng)是二進(jìn)制位字符。例如8251A使用RS-232接口進(jìn)行數(shù)據(jù)通信時,方式字具的結(jié)構(gòu):可以定義一下位字段結(jié)構(gòu):D7D6D5D4D3D2D1D0stopevenparicharbundstructbit{unsignedbund_bit:2;unsignedchar_bit:2;unsignedpari_bit:1;unsignedeven_bit:1;unsignedstop_bit:2;}8.4位字段結(jié)構(gòu)位字段結(jié)構(gòu)定義中的每個成員項(xiàng)一般書寫格式為:位字段以單個unsigned型數(shù)據(jù)為單位,其內(nèi)存放著一連串相鄰的二進(jìn)制位若某一段要從另一個字開始存放,可以使用以下形式:在位字段結(jié)構(gòu)體內(nèi)若有不帶名字的位字段時,冒號后面的位數(shù)應(yīng)寫0,表示位字段間的填充物,使得下一個成員項(xiàng)c分配在相鄰的下一個unsigned型內(nèi)unsigned成員名:位數(shù);structtest{unsigneda:1;unsignedb:2;//成員a和b占用一個存儲單元

unsigned:0;unsignedc:3;//成員c占用另一個存儲單元}8.4位字段結(jié)構(gòu)位字段結(jié)構(gòu)在程序中的處理方式和表示方法等于與普通結(jié)構(gòu)相同。例如,上述8251A方式字結(jié)構(gòu)在定義后可以有下列說明:其結(jié)構(gòu)變量mod的成員為:一個位段必須存儲在同一個存儲單元中。如果一個單元空間不能容納下一位段,則不用該空間,從另一個單元其存放該位段。位段的長度不能大于存儲單元的長度,也不能定義為段數(shù)據(jù)structbitmod;

mod.bund_bit

mod.stop_bit等8.4位字段結(jié)構(gòu)位字段結(jié)構(gòu)的成員項(xiàng)可以和一個變量一樣參加各種運(yùn)算,但一般不能對位字段結(jié)構(gòu)的成員項(xiàng)作取地址&運(yùn)算。例如:也可以使用%u,%o,%x等格式輸出。位段可以在數(shù)值表達(dá)式中引用,它會被系統(tǒng)自動的轉(zhuǎn)換成整數(shù)型。例如:mod.bund_bit+5/mod.char_bitstructbitmod;mod.bund_bit=3;//如果賦值4就有錯mod.char_bit=2;mod.pari_bit=0;printf(“%d,%d,%d”,mod.bund_bit,mod.char_bit,mod.pari_bit);8.5聯(lián)合在C語言中,不同數(shù)據(jù)類型的數(shù)據(jù)可以使用共同的存儲區(qū)域,這種數(shù)據(jù)結(jié)構(gòu)類型稱為聯(lián)合體,簡稱聯(lián)合聯(lián)合體在定義、說明和使用形式上與結(jié)構(gòu)相似。二者本質(zhì)上的不同僅在于使用內(nèi)存的方式上聯(lián)合的定義制定了聯(lián)合的組成形式,同時指出了組成聯(lián)合的成員具體數(shù)據(jù)類型。與結(jié)構(gòu)的定義相同,聯(lián)合的定義并不為聯(lián)合體分配具體的內(nèi)存空間,它僅僅說明聯(lián)合體使用內(nèi)存的模式union聯(lián)合名{

數(shù)據(jù)類型成員名1;數(shù)據(jù)類型成員名2;

……

數(shù)據(jù)類型成員名n;}8.5聯(lián)合聯(lián)合uarea由3個成員項(xiàng)組成,這3個成員項(xiàng)在內(nèi)存中使用共同的存儲空間由于聯(lián)合中各成員項(xiàng)的數(shù)據(jù)長度往往不同,聯(lián)合體在存儲時總是按照其成員中數(shù)據(jù)長度最大的成員項(xiàng)占用內(nèi)存空間uareac_datai_datal_dataunionuarea{charc_data;inti_data;longl_data;}8.5聯(lián)合聯(lián)合一經(jīng)定義,就可以定義使用這種數(shù)據(jù)構(gòu)造類型的具體對象,即聯(lián)合變量的定義,其形式與結(jié)構(gòu)變量的定義類似。例如:定義了使用uarea聯(lián)合類型的聯(lián)合變量udata、聯(lián)合指針*pud和聯(lián)合數(shù)組data[]。由于聯(lián)合體的各個成員項(xiàng)使用共同的內(nèi)存區(qū)域,所以聯(lián)合體的內(nèi)存空間中在某個時刻只能保持某個成員項(xiàng)的數(shù)據(jù)在程序中參加運(yùn)算的必然是聯(lián)合體的某個成員項(xiàng)unionuareaudata,*pud,data[10];8.5聯(lián)合聯(lián)合體成員項(xiàng)的表現(xiàn)形式與結(jié)構(gòu)相同,用訪問成員運(yùn)算符.和->表示聯(lián)合變量可以向另一個相同聯(lián)合類型的聯(lián)合體賦值。聯(lián)合變量可以作為參數(shù)傳遞給函數(shù),也可以作為返值從函數(shù)中返回在程序中經(jīng)常使用結(jié)構(gòu)與聯(lián)合體相互嵌套的形式Udata.c_data,udata.i_data,

udata.l_datapud->c_data,pud->i_data,pud->l_dataunionuarea{charc_data;inti_data;longl_data;}structdata{char*p;inttype;unionuareaudata;}8.5例8.11

設(shè)有若干人員的數(shù)據(jù),其中有學(xué)生和教師。學(xué)生的數(shù)據(jù)中包括:姓名、號碼、性別、職業(yè)、班級。教師的數(shù)據(jù)包括有:姓名、號碼、性別、職業(yè)、職務(wù)。現(xiàn)要求把它們放在同一表格中。要求先輸入人員的數(shù)據(jù),然后再輸出。聯(lián)合分析:從上面可以看出,學(xué)生和老師包含的數(shù)據(jù)是不同的。如果job項(xiàng)為s(學(xué)生),則第五項(xiàng)為class,即li是501班的。如果job項(xiàng)是t(教師),則第五項(xiàng)為position,wang是professor。顯然對第五項(xiàng)可以采取聯(lián)合方式來處理。namenumsexjobClass/positionli1011fs501wang2058mtprofessor8.5聯(lián)合例8.11

輸入輸出學(xué)生、教師信息#include<stdio.h>#include<stdlib.h>#include<string.h>unionCareer//定義一個聯(lián)合{intmyclass;charposition[10];};structData//定義一個結(jié)構(gòu){intnum;charname[10];charsex;charjob;unionCarrercategory;}voidmain(){intn;charstr[20];structDataperson[N];//定義結(jié)構(gòu)數(shù)組

for(n=0;n<N;n++){gets(str);person[n].num=atoi(str);

gets(person[n].name);gets(str);person[n].sex=str[0];//取字符串的第一個字符

gets(str);person[n].job=str[0];//取字符串的第一個字符if(person[n].job=='s')//為學(xué)生

{gets(str);person[n].category.myclass=atoi(str);}elseif(person[n].job=='t')//為老師

gets(person[n].category.positon);else//輸入數(shù)據(jù)錯誤

printf("inputerror");}printf("\n");printf("No.NameSexJobclass/position\n");for(n=0;n<N;n++)//顯示錄入數(shù)據(jù)

{if(person[b].job=='s')//為學(xué)生

printf(“%-6d%-10s%-3c%-3c%-10d\n”,\person[n].num,person[n].name,person[n].\sex,person[n].job,person[n].category.myclass);elseif(person[n].job==‘t’)//為老師

printf("%-6d%-10s%-3c%-3c%-10d\n",\person[n].num,person[n].name,person[n].\sex,person[n].job,person[n].category.position);}}8.6類型定義語句typedeftypedef:用新的類型名來代替已有的基本數(shù)據(jù)類型名和已經(jīng)定義了的類型的功能。格式為:其中類型說明是對新類型名的描述,類型說明可以是各種基本

數(shù)據(jù)類型和已定義了的結(jié)構(gòu)體、聯(lián)合體、指針、枚舉等類型typedef<類型說明><新類型名>;typedefintINTEGER;typedeffloatREAL;inti,j;floata,b;INTEGERi,j;REALa,b;等價于8.6類型定義語句typedef例如,在stdio.h頭文件中有如下定義:由于經(jīng)常要用無符號整形變量記錄一個內(nèi)存空間的大小或者是某種數(shù)據(jù)類型的數(shù)據(jù)塊大小,用新類型名”size_t”,不僅書寫方便,且見名知意,在標(biāo)準(zhǔn)函數(shù)庫中經(jīng)常使用新類型名“size_t”移植方便typedefunsignedintsize_t;inta,b,c;longa,b,c;修改typedefintINT;typedeflongINT修改8.6類型定義語句typedeftypedef與#define的區(qū)別作用都是用COUNT代替int,但#define語句是在預(yù)處理操作時進(jìn)行字符串的替換,而typedef則是在編譯時進(jìn)行處理的,它并不是進(jìn)行簡單的字符串替換。定義了一個STRING類型,它是具有81個字符的數(shù)組,以后就可用STRING類型定義類型的字符型數(shù)組typedefintCOUNT;#defineCOUNTinttypedefcharSTRING[81];STRINGtext,line;chartext[81],line[81];等價于8.6類型定義語句typedef使用typedef語句給已定義的結(jié)構(gòu)類型賦予新的類型名,大大簡化了對結(jié)構(gòu)變量的說明,例如:其中COMPLEX就是struct{}的新類型名,即struct{}與COMPLEX對其結(jié)構(gòu)變量的說明作用一樣,COMPLEX也是結(jié)構(gòu)名COMPLEX是結(jié)構(gòu)類型而不是結(jié)構(gòu)變量,因此不能用COMPLEX進(jìn)行訪問成員的運(yùn)算?!盋OMPLEX.real”是非法的typedefstruct{doublereal;doubleimag;}COMPLEX;COMPLEXc1,c2;COMPLEX*r,*op1,*op2;8.6例8.12

復(fù)數(shù)的加法運(yùn)算類型定義語句typedef運(yùn)行結(jié)果:(1)a(6.00,8.00)(2)COMPLEXb(2.00,8.00)(3)COMPLEXc(8.00,16.00)#include<stdio.h>typedefstruct{doublereal;doubleimag;}COMPLEX;COMPLEXcadd(COMPLEX*op1,COMPLEX*op2);COMPLEXcadd(COMPLEX*op1,COMPLEX*op2){COMPLEXresult;result.real=op1->real+op2->real;//實(shí)數(shù)部分相加

result.imag=op1->imag+op2->imag;//虛數(shù)部分相加

returnresult;}voidmain(){COMPLEXa={6.0,8.0},b={2.0,8.0},c;printf("(1)COMPLEXa(%.21f,%.21f)\n"),a.real,a.imag);printf("(2)COMPLEXb(%.21f,%.21f)\n"),b.real,b.imag);c=caad(&a,&b);//調(diào)用cadd()求復(fù)數(shù)a和b之和

printf("(3)COMPLEXc(%.21f,%.21f)\n"),c.real,c.imag);}8.7枚舉類型枚舉類型:把一組整型符號常量按順序集合成一種數(shù)據(jù)類型其中整型符號常量叫做該枚舉類型的元素,簡稱枚舉元素,每個枚舉元素都有確定的整數(shù)值。用符號常量名來一次列舉他的每一個可能值枚舉定義:enumWEEKDAY{sun,mon,tue,wed,thu,fri,sat};enumCOLOR{BLACK,BLUE,GREEN,RED=4,YELLOW=14,WHITE};enum枚舉類型名{枚舉元素1,枚舉元素2,…,枚舉元素n};<存儲類>enum枚舉類型名枚舉變量名;staticenumCOLORbackdrop,frame;8.7枚舉類型枚舉變量具有變量的屬性,可以讀取它的值和對它賦值。其存儲類也有auto型、static型和extern型等枚舉變量只能取枚舉元素表內(nèi)所列的可能值。賦值時一般使用使用枚舉元素名,避免把非枚舉值賦給了枚舉變量。與結(jié)構(gòu)類型一樣,枚舉類型的定義和枚舉變量的說明即可以加上所述那樣分開進(jìn)行,又可以同時進(jìn)行frame=RED;backdrop=BLUE;enumMONTH{January=1,February,March,\April,May,June,July,August,\September,October,November,\December}month;8.7枚舉類型枚舉元素均為常量,不能用賦值語句對他們賦值

枚舉元素一經(jīng)初始化后,就只能使用它而不能改變枚舉元素作為常量,編譯系統(tǒng)按定義式的排列順序使它們的數(shù)值為0,1,2,…如枚舉類型WEEKDAY的元素sun的值為0,mon的值為1,…sat的值為6,這稱為隱式初始化操作枚舉元素的值也可以在定義的同時由編程者自行指定sun=1;//出錯RED=2;//出錯printf(“BLACK=%d,BLUE=%d,GREEN=%d,RED=%d,YELLOW=%d,\WHITE=%d\n”,BLACK,BLUE,GREEN,RED,YELLOW,WHITE);運(yùn)行結(jié)果:BLACK=0,BLUE=1,GREEN=2,RED=4,YELLOW=14,WHITE=158.7例8.13

枚舉變量用于switch結(jié)構(gòu)枚舉類型運(yùn)行結(jié)果:請輸入年份:2000(CR)請輸入月份:11(CR)請輸入日:11(CR)從2000年元月1日到2000年11月11日共有316天!//定義一個結(jié)構(gòu)指針變量#include<stdio.h>voidmain(){enumMONTH{January=1,February,March,April,\May,June,July,August,September,October,November,\December}month;intyear,day,days;printf("請輸入年份:");scaf("%d",&year);printf("請輸入月份:");scanf("%d",&month);printf("請輸入日:");scanf("%d",&day);days=day;//加入本月的天數(shù)

//計(jì)算(month-1)月的累加天數(shù),

//該switch語句為鏈形結(jié)構(gòu)

switch(month-1){caseDecember:days+=31;caseNovember:days+=30;caseOctober:days+=31;caseSepetember:days+=30;caseAugust:days+=31;caseJuly:days+=31;caseJune:days+=30;caseMay:days+=31;caseApril:days+=30;caseMarch:days+=31;caseFebruary:if(year%4==0&&year%100!=0||\year%400==0)days+=29;//閏年

elsedays+=28;//非閏年

caseJanuary:days+=31;}printf(“從%d年元月1日到%d年%d月%d\

日共有%d天!\n\n”,\year,year,month,day,days);}8.8綜合舉例——鏈表數(shù)組雖然結(jié)構(gòu)簡單、訪問元素方便、執(zhí)行速度快但是數(shù)組是靜態(tài)數(shù)據(jù)結(jié)構(gòu),即必須要預(yù)先確定它的大小只能用順序存儲的存儲結(jié)構(gòu),且要求其存儲單元是連續(xù)的鏈表是一種動態(tài)地進(jìn)行存儲分配的數(shù)據(jù)結(jié)構(gòu)。非常適合處理數(shù)據(jù)個數(shù)預(yù)先無法確定且數(shù)據(jù)記錄頻繁變化的場合,使用動態(tài)存儲技術(shù)和遞歸結(jié)構(gòu)體建立鏈表,可通過指針增加或刪除結(jié)點(diǎn)(Node)8.8綜合舉例——鏈表鏈表結(jié)構(gòu)常用的鏈表有單向鏈表和雙向鏈表,單向鏈表中又包含循環(huán)單向鏈表,雙向鏈表也包含循環(huán)雙向鏈表一般雙向鏈表循環(huán)雙向鏈表一般單向鏈表循環(huán)單向鏈表8.8綜合舉例——鏈表單向鏈表的結(jié)構(gòu)頭指針:存放一個地址,該地址指向一個元素結(jié)點(diǎn):用戶需要的實(shí)際數(shù)據(jù)和鏈接下一個結(jié)點(diǎn)的指針

可以不連續(xù)存放不提供“頭指針”(head),則整個鏈表都無法訪問8.8綜合舉例——鏈表單向鏈表的結(jié)構(gòu)成員num和score用來存放結(jié)點(diǎn)中的有用數(shù)據(jù)(用戶需要用到的數(shù)據(jù))next是指針類型成員,指向structstudent類型數(shù)據(jù)(next所在的結(jié)構(gòu)體類型)structstudent{intnum;floatscore:structstudent*next;};8.8綜合舉例——鏈表簡單舉例運(yùn)行結(jié)果:1010189.51010390.01010785.0#include<stdio.h>

#defineNULL0

structstudent{ longnum; floatscore; structstudent*next;};main(){ structstudenta,b,c,*head,*p; a.num=99101;a.score=89.5; b.num=99103;b.score=90; c.num=99107;c.score=85; head=&a; a.next=&b; b.next=&c; c.next=NULL; p=head;

do{ printf("%ld%5.1f\n",p->num,p->score); p=p->next; }while(p!=NULL);}8.8綜合舉例——鏈表動態(tài)鏈表——動態(tài)地開辟和釋放存儲單元(1)malloc函數(shù)在內(nèi)存的動態(tài)存儲區(qū)中分配一個長度為size的連續(xù)空間。(2)calloc函數(shù)

在內(nèi)存的動態(tài)區(qū)存儲中分配n個長度為size的連續(xù)空間(3)free函數(shù)釋放由p指向的內(nèi)存區(qū)void*malloc(unsignedintsize);void*calloc(unsignedn,unsignedsize);voidfree(void*p);8.8綜合舉例——鏈表單向鏈表操作——查找結(jié)點(diǎn)1typedefintDataType;typedefstructlinknode{ DataTypedata; structlinknode*next;}Node;int node_find(Node*head,Datatypex){ Node*p; p=head;

while(p!=NULL) { if(p->data==x)break; p=p->next;

}

if(p==NULL) return0; elsereturn1;}Node*node_find(Node*head,Datatypex){ Node*p; p=head;

while(p!=NULL) {if(p->data==x)break;

p=p->next;}returnp;}單向鏈表操作——查找結(jié)點(diǎn)28.8綜合舉例——鏈表單向鏈表操作——插入結(jié)點(diǎn)voidinsert(Node*p,Datatypex){ Node*q,*t; q=(Node*)malloc(sizeof(Node)); if(q==NULL) { printf("noenoughmemory"); exit(1); } q->data=x; t=p->next; p->next=q; q->next=t;}8.8綜合舉例——應(yīng)用舉例例8.14

編程處理某班N個學(xué)生4門課的成績,它們是數(shù)學(xué)、物理、英語和計(jì)算機(jī),

按編號從小到大的順序依次輸入學(xué)生的姓名、性別和四門課的成績。計(jì)算每個學(xué)生的平均分,并以清晰的打印格式從高分到低分的順序打印平

均分高于全班總平均成績的男生的成績單。問題分析與設(shè)計(jì):模塊劃分:四個功能塊:輸入數(shù)據(jù)、排序,求總平均成績和輸出數(shù)據(jù)結(jié)構(gòu):由于學(xué)生的姓名、性別、各門功課的成績及平均成績具有一定的關(guān)聯(lián)性,作為集合數(shù)據(jù),將其規(guī)劃為一個結(jié)構(gòu)體:structstudent{charname[20];//姓名

charsex;//性別,'m'代表男,'f'代表女

floatscore[4];//學(xué)生的各科成績

floataver;//平均成績};8.8綜合舉例——應(yīng)用舉例(1)voidinput(structstudent*p,intn);

功能:輸入學(xué)生信息

形參:第一個參數(shù)用來接收存儲學(xué)生數(shù)據(jù)的結(jié)構(gòu)數(shù)組首地址,第二個參數(shù)接收學(xué)生的個數(shù)(4)floataverage(structstudent*p,intn);

功能:計(jì)算平均成績(函數(shù)返回總平均成績)

形參:第一個參數(shù)用來接收存儲學(xué)生數(shù)據(jù)的結(jié)構(gòu)數(shù)組首地址,第二個參數(shù)接收學(xué)生的個數(shù)

(2)voidsort(structstudent*p,intn);

功能:按照學(xué)生成績排序

形參:第一個參數(shù)用來接收存儲學(xué)生數(shù)據(jù)的結(jié)構(gòu)數(shù)組首地址,第二個參數(shù)接收

溫馨提示

  • 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論