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),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

結(jié)構(gòu)體和共用體7.1結(jié)構(gòu)體7.2結(jié)構(gòu)體數(shù)組7.3共用體單元小結(jié) 7.1結(jié)

構(gòu)

7.1.1結(jié)構(gòu)體類型

1.認(rèn)識(shí)結(jié)構(gòu)體類型

與數(shù)組相同,結(jié)構(gòu)體也是一種構(gòu)造類型,同樣允許用戶將多個(gè)數(shù)據(jù)成員作為一個(gè)整體來保存和使用。它們的區(qū)別在于數(shù)組所有元素的數(shù)據(jù)類型必須一致,而結(jié)構(gòu)體的各個(gè)成員可以定義成不同的數(shù)據(jù)類型。因此,結(jié)構(gòu)體是一種用戶自定義的構(gòu)造數(shù)據(jù)類型,是由若干數(shù)據(jù)成員組成的,這些成員不要求類型必須一致,成員既可以是基本數(shù)據(jù)類型的數(shù)據(jù),也可以是其他構(gòu)造類型的數(shù)據(jù)。

例如,表7-1是某校學(xué)生信息表,現(xiàn)在希望通過C程序管理這些數(shù)據(jù)。

我們要把每個(gè)學(xué)生的學(xué)號(hào)、姓名、性別、年齡和成績幾個(gè)數(shù)據(jù)項(xiàng)當(dāng)成一個(gè)整體來看待,可以通過構(gòu)造結(jié)構(gòu)體類型來實(shí)現(xiàn)。分析表7-1中的數(shù)據(jù),學(xué)號(hào)和姓名可以定義成字符數(shù)組,性別定義成字符型('m'代表男性,'f'代表女性),年齡定義成整型,成績定義成實(shí)型,如圖7-1所示。圖7-1“學(xué)生”類型設(shè)計(jì)2.聲明結(jié)構(gòu)體類型

聲明結(jié)構(gòu)體類型的一般形式如下:

struct結(jié)構(gòu)體名

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

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

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

};

這里需要注意的是:

(1)“

struct”是關(guān)鍵字,表示聲明的類型是一種結(jié)構(gòu)體類型,不能省略。

(2)“結(jié)構(gòu)體名”是由用戶自己定義的,用來標(biāo)識(shí)這個(gè)新構(gòu)造的結(jié)構(gòu)體類型,以便于同其他結(jié)構(gòu)體類型相區(qū)分。

(3)大括號(hào)內(nèi)是該結(jié)構(gòu)體類型的所有數(shù)據(jù)成員,可以直接采用定義變量的方式來定義數(shù)據(jù)成員。

(4)結(jié)構(gòu)體類型定義必須以分號(hào)結(jié)束。

例如,根據(jù)圖7-1的分析可以設(shè)計(jì)結(jié)構(gòu)體類型如下:

structstudent

{ charid[9];

/*學(xué)號(hào)*/

charname[10]; /*姓名*/

charsex; /*性別*/

intage;

/*年齡*/

floatscore;

/*成績*/

};

7.1.2結(jié)構(gòu)體變量

1.結(jié)構(gòu)體變量的定義

前面只是構(gòu)造了一個(gè)結(jié)構(gòu)體類型,其地位等同于系統(tǒng)已經(jīng)定義好的基本數(shù)據(jù)類型,但至此還沒有定義具體的變量,系統(tǒng)也沒有分配具體的內(nèi)存空間。因此,若想真正存取結(jié)構(gòu)體類型的數(shù)據(jù),還需要定義具有該類型結(jié)構(gòu)的變量。定義結(jié)構(gòu)體變量可以使用下面三種方法。

(1)使用已聲明的結(jié)構(gòu)體類型定義變量。其一般形式如下:

結(jié)構(gòu)體類型名

變量名列表;

例如,可以使用7.1.1節(jié)中聲明的“structstudent”類型定義變量如下:

structstudentst1,st2;

變量st1、st2將具有“structstudent”類型聲明的數(shù)據(jù)成員結(jié)構(gòu),可以存取表7-1中的學(xué)生信息,具體的內(nèi)存空間分配如圖7-2所示(圖中已預(yù)先為各成員進(jìn)行了賦值,便于幫助理解)。圖7-2結(jié)構(gòu)體變量st1的存儲(chǔ)結(jié)構(gòu)示意圖

(2)聲明結(jié)構(gòu)體類型的同時(shí)定義變量。

可以將結(jié)構(gòu)體類型的聲明和結(jié)構(gòu)體變量的定義合二為一,同時(shí)進(jìn)行。使用這種方法定義變量的一般形式如下:

struct結(jié)構(gòu)體名

{

成員列表;

}變量名列表;

例如,前面“structstudent”類型的聲明和st1、st2兩個(gè)變量的定義可以同時(shí)進(jìn)行:

structstudent

{ charid[9]; /*學(xué)號(hào)*/

charname[10]; /*姓名*/

charsex; /*性別*/

intage;

/*年齡*/

floatscore; /*成績*/

}st1,st2;

(3)缺省類型名直接定義結(jié)構(gòu)體變量。

如果某個(gè)結(jié)構(gòu)體類型只使用一次,以后不再使用它來定義新的變量,那么可以省略結(jié)構(gòu)體名,直接定義結(jié)構(gòu)體變量。其一般形式如下:

struct

{ 成員列表;

}變量名列表;

例如,可以直接定義結(jié)構(gòu)體變量st1、st2:

struct

{ charid[9]; /*學(xué)號(hào)*/

charname[10]; /*姓名*/

charsex;

/*性別*/

intage;

/*年齡*/

floatscore; /*成績*/

}st1,st2;

2.結(jié)構(gòu)體成員的引用

結(jié)構(gòu)體變量是若干數(shù)據(jù)成員的集合,故一般不直接使用結(jié)構(gòu)體變量,而是通過對(duì)其成員的引用來進(jìn)行輸入、輸出等操作。引用結(jié)構(gòu)體變量中成員的一般形式如下:

結(jié)構(gòu)體變量名.成員名

例如,若想為st1賦值以獲得圖7-2中所示的效果,可使用如下程序段來實(shí)現(xiàn):

strcpy(st1.id,“20142154”); /*字符串不能直接用“=”賦值*/

strcpy(,“王宇”);

st1.sex=‘m’;

st1.age=17;

st1.score=89.5;

結(jié)構(gòu)體變量的操作類似于數(shù)組,它的各個(gè)成員可以和普通變量一樣進(jìn)行各種運(yùn)算,但是其本身不能作為一個(gè)整體輸入、輸出或賦常量值。例如,不能像下面這樣訪問結(jié)構(gòu)體

變量:

st1={“20142154”,“王宇”,‘m’,17,89.5};

/*錯(cuò)誤用法*/

printf(“%s,%s,%c,%d,%f”,st1);

/*錯(cuò)誤用法*/

相同類型的結(jié)構(gòu)體變量之間可以直接賦值,這也是結(jié)構(gòu)體變量唯一可以整體操作的方式。例如,已有“structstudentst1,st2”,可以直接將st1整體賦值給st2:

st2=st1;

/*同類型的結(jié)構(gòu)體變量間可整體賦值*/

【例7-1】

構(gòu)造用于保存日期(年、月、日)的結(jié)構(gòu)體類型date,輸入今天的日期,計(jì)算并輸出明天的日期。

#include<stdio.h>

structdate /*結(jié)構(gòu)體類型-日期*/

{ intyear; /*成員-年*/

intmonth; /*成員-月*/

intday;

/*成員-日*/

};

main()

{ structdatetoday,tomor;

today.year=2014;

today.month=9;

today.day=1;

tomor=today;

tomor.day++;

printf("今天:%d年%d月%d日\n",today.year,today.month,today.day);

printf("明天:%d年%d月%d日\n",tomor.year,tomor.month,tomor.day);

}

圖7-3例7-1程序運(yùn)行結(jié)果

3.結(jié)構(gòu)體變量的初始化

在結(jié)構(gòu)體變量定義的同時(shí)可以為其整體賦初值,方法與數(shù)組的初始化相似,將各個(gè)數(shù)據(jù)成員的值按聲明類型時(shí)的順序依次排列,使用逗號(hào)間隔,全部放在大括號(hào)中,整體賦值給變量。例如:

structstudentst1={“20142154”,“王宇”,‘m’,17,89.5};

初始化結(jié)構(gòu)體變量時(shí),應(yīng)注意每一個(gè)數(shù)據(jù)都要與結(jié)構(gòu)體類型中對(duì)應(yīng)成員的數(shù)據(jù)類型相同。

7.1.3應(yīng)用舉例

【例7-2】

輸入一個(gè)點(diǎn)的二維坐標(biāo),計(jì)算并輸出這個(gè)點(diǎn)距離原點(diǎn)的長度。

定義結(jié)構(gòu)體類型structpoint來表示點(diǎn),其中分別定義實(shí)型變量x和y表示點(diǎn)的x坐標(biāo)和y坐標(biāo)。

#include<stdio.h>

#include<math.h>

structpoint /*點(diǎn)*/

{ floatx; /*x坐標(biāo)*/

floaty; /*y坐標(biāo)*/

};

main(){ structpointp1;

floatl;

printf("x坐標(biāo):");

scanf("%f",&p1.x);

printf("y坐標(biāo):");

scanf("%f",&p1.y);

l=sqrt(p1.x*p1.x+p1.y*p1.y);

printf("點(diǎn)(%.1f,%.1f)距離原點(diǎn)長%.1f\n",p1.x,p1.y,l);

}

圖7-4例7-2程序運(yùn)行結(jié)果

【例7-3】

某研究小組希望建立氣象信息檔案,要求記錄各地每日的最高、最低溫度及空氣質(zhì)量指數(shù)。請(qǐng)為它們構(gòu)造合適的結(jié)構(gòu)體類型,并提供1組樣例作為測(cè)試數(shù)據(jù)。

定義結(jié)構(gòu)體類型structwether來表示氣象記錄,其中的日期繼續(xù)定義結(jié)構(gòu)體類型structdate來表示,構(gòu)造出來的結(jié)構(gòu)如圖7-5所示。圖7-5structwether的結(jié)構(gòu)#include<stdio.h>

structdate

{ intyear;

intmonth;

intday;

};

structweather

{ charcity[20];

structdatemydate;

inttemp_max;

inttemp_min;

intpm;

};

main()

{ structweatherw={"上海",{2014,3,18},24,13,85};

printf("%s\n",w.city);

printf("%d年%d月%d日\n",

w.mydate.year,w.mydate.month,w.mydate.day);

printf("最高溫度:%d\t最低溫度:%d\n",w.temp_max,w.temp_min);

printf("空氣質(zhì)量指數(shù):%d\n",w.pm);

}

說明:

(1)結(jié)構(gòu)體中的數(shù)據(jù)成員可以定義為另一種結(jié)構(gòu)體類型,這時(shí)將構(gòu)成結(jié)構(gòu)體的嵌套。

(2)對(duì)嵌套結(jié)構(gòu)體成員的引用要引用到最末一級(jí)。例如,本例中顯示日期需分別顯示年、月、日,而且是采用逐級(jí)訪問的方式完成的。

程序運(yùn)行結(jié)果如圖7-6所示。圖7-6例7-3程序運(yùn)行結(jié)果 7.2結(jié)?構(gòu)?體?數(shù)?組

在7.1.1小節(jié)中,我們?yōu)榱斯芾肀?-1中的學(xué)生數(shù)據(jù)聲明了結(jié)構(gòu)體類型“structstudent”,并定義了兩個(gè)變量st1,st2。定義結(jié)構(gòu)體變量可以滿足存放一兩個(gè)學(xué)生數(shù)據(jù)的要求,若想管理表中的所有數(shù)據(jù),就需要將結(jié)構(gòu)體類型定義成數(shù)組才行。結(jié)構(gòu)體數(shù)組中的每個(gè)元素都是一個(gè)結(jié)構(gòu)體類型的數(shù)據(jù),和定義結(jié)構(gòu)體變量的方法相仿,只需將結(jié)構(gòu)體變量換成數(shù)組即可。根據(jù)已經(jīng)聲明的類型定義結(jié)構(gòu)體數(shù)組的一般格式如下:

struct結(jié)構(gòu)體名

數(shù)組名[長度];

為結(jié)構(gòu)體數(shù)組進(jìn)行初始化的方法與二維數(shù)組的相似,每個(gè)數(shù)組元素作為結(jié)構(gòu)體類型的數(shù)據(jù)要使用大括號(hào)括起來,所有元素的外層采用數(shù)組初始化的規(guī)則繼續(xù)使用大括號(hào)括起來。例如:

structstudentstu[3]={{“20142145”,“王宇”,‘m’,17,89.5},

{“20143018”,“柳青”,‘m’,18,76.0},

{"20148429","李萱萱",'f',17,92.5}};圖7-7結(jié)構(gòu)體數(shù)組stu圖7-8結(jié)構(gòu)體數(shù)組stu的存儲(chǔ)方式訪問結(jié)構(gòu)體數(shù)組中元素的各數(shù)據(jù)成員的方法如下:

數(shù)組名[下標(biāo)].成員名;

例如:

printf("%s",stu[1].name); /*輸出“柳青”*/

【例7-4】

某學(xué)生干事希望編寫程序幫助其管理學(xué)生成績,他希望錄入學(xué)生的學(xué)號(hào)、姓名及各門課程的成績后,程序可以計(jì)算每個(gè)學(xué)生的總成績和平均成績,并將結(jié)果顯示

出來。

本例以錄入3名學(xué)生4門課程的成績?yōu)槔幊?,使用符?hào)常量保存學(xué)生人數(shù)和課程門數(shù),使用時(shí)可根據(jù)實(shí)際情況方便地修改參數(shù)。

#include<stdio.h>

#defineM3 /*M為學(xué)生人數(shù)*/

#defineN4 /*N為課程門數(shù)*/

structstudent

{ intid; /*學(xué)號(hào)*/

charname[20]; /*姓名*/

floatscore[N]; /*各門課程的成績*/

floatsum; /*總分*/

floatavg; /*平均分*/

};

main()

{ structstudents[M];

inti,j;

for(i=0;i<M;i++) /*輸入姓名、學(xué)號(hào)、各科成績*/

{ printf("學(xué)號(hào):");

scanf("%d",&s[i].id);

printf("姓名:");

scanf("%s",s[i].name);

for(j=0;j<N;j++)

{ printf("\t科目%d:",j+1);

scanf("%f",&s[i].score[j]);

}

}

for(i=0;i<M;i++)

{ s[i].sum=0;

for(j=0;j<N;j++) /*計(jì)算總分*/

s[i].sum+=s[i].score[j];

s[i].avg=s[i].sum/N; /*計(jì)算平均分*/

}

for(i=0;i<M;i++) /*輸出結(jié)果*/

{ printf("學(xué)號(hào):%d\t姓名:%s\t",s[i].id,s[i].name);

printf("總分:%.1f\t平均分:%.1f\n",s[i].sum,s[i].avg);

}

}

說明:

(1)程序定義了一個(gè)結(jié)構(gòu)體數(shù)組s表示學(xué)生,數(shù)組具有M個(gè)元素,M為3時(shí)可以統(tǒng)計(jì)3個(gè)學(xué)生的成績。程序中的“s[i]”表示第(i+1)名學(xué)生。

(2)每個(gè)數(shù)組元素包含id(學(xué)號(hào))、name(姓名)、score(各單科成績)、sum(總分)和avg(平均分)5個(gè)數(shù)據(jù)成員。

(3)結(jié)構(gòu)體成員score也是一個(gè)數(shù)組,用來存放學(xué)生的各門課程的成績。本數(shù)組具有N個(gè)元素,N為4時(shí)可以為每名學(xué)生錄入4門課程的成績。程序中的“s[i].score[j]”表示第(i+1)名學(xué)生的第(j+1)門課程的成績。

(4)注意數(shù)據(jù)成員間的對(duì)應(yīng)關(guān)系,計(jì)算時(shí)一個(gè)學(xué)生的各項(xiàng)數(shù)據(jù)成員應(yīng)通過相同的數(shù)組元素來引用。例如,學(xué)生的總分由該名學(xué)生的各門課程成績累加得出,即“for(j=0;j<N;j++)s[i].sum+=s[i].score[j];”;平均分由該名學(xué)生的總分除以科目數(shù)得出,即“s[i].avg?=s[i].sum/N;”。

圖7-9例7-4程序運(yùn)行結(jié)果

7.3共

共用體是C語言中另一種允許用戶自定義數(shù)據(jù)結(jié)構(gòu)的構(gòu)造類型。它和結(jié)構(gòu)體類似,也是由若干不同類型的數(shù)據(jù)成員組合而成的,類型聲明、變量定義等使用方式也與結(jié)構(gòu)體類型大同小異。不同的是,共用體變量的所有成員均從同一地址開始存放,即在同樣的內(nèi)存空間中可以根據(jù)需要存放不同類型的數(shù)據(jù)。也就是說,共用體為所有成員定義了一塊共享的內(nèi)存空間。靈活運(yùn)用共用體可以有效地節(jié)省內(nèi)存空間。聲明共用體類型的一般形式如下:

union共用體名

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

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

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

};

表中“成績”一欄因?yàn)椴捎玫目己朔绞讲煌a(chǎn)生了兩種成績記錄方式。其中考試課的成績可以直接使用整型數(shù)保存;考查課的成績包含“優(yōu)”、“良”、“中”、“及格”和“不及格”5個(gè)等級(jí),即使映射成“A”、“B”、“C”、“D”、“E”也需使用字符型保存。這時(shí),我們可以將成績一欄設(shè)計(jì)成共用體類型,以使其既可以存儲(chǔ)字符型數(shù)據(jù),又可以存儲(chǔ)整型數(shù)據(jù)。當(dāng)然,每門課程只能選擇一種考核方式,產(chǎn)生一個(gè)成績,要么是整型,要么是字符型。

為“成績”一欄聲明共用體類型如下:

unionscore

{ intnum; /*用來記錄百分制成績*/

chargrade; /*用來記錄等級(jí)制成績*/

};

這里聲明了共用體類型“unionscore”,數(shù)據(jù)成員包含一個(gè)整型和一個(gè)字符型,它們共用同一段內(nèi)存單元,如圖7-10所示。

圖7-10共用體類型的存儲(chǔ)方式

因?yàn)閿?shù)據(jù)成員共享內(nèi)存空間,所以共用體的大小以各數(shù)據(jù)成員中所占內(nèi)存空間最大的成員為準(zhǔn)。例如,上面聲明的共用體類型“unionscore”占有的內(nèi)存空間大小等于其成員num的大小,為4字節(jié)。

共用體的變量定義和成員引用方式與結(jié)構(gòu)體的相同。例如:

unionscoresc1; /*定義共用體變量sc1*/

sc1.num=92; /*使用百分制方式記錄考核成績*/

【例7-5】

某高校準(zhǔn)備編寫成績管理系統(tǒng),現(xiàn)提供某名學(xué)生的成績單如表7-2所示,要求編寫程序管理學(xué)生成績并輸出成績單。

為表7-2中的各行記錄設(shè)計(jì)結(jié)構(gòu)體類型“structsubject”,包含成員課程名、考核方式、成績。其中課程名使用字符數(shù)組表示,考核方式使用字符型表示(t為考試,f為考核),成績使用前面分析的共用體類型“unionscore”表示。#include<stdio.h>

#defineN3 /*課程數(shù)*/

unionscore /*成績*/

{ intnum;

chargrade;

};

structsubject

{ charname[20]; /*課程名*/

chartype; /*考核方式*/

unionscoresc; /*成績*/

};

main()

{ structsubjectsub[N]={{"C語言程序設(shè)計(jì)",'t',{92}},

{“藝術(shù)欣賞”,‘f’,{‘B’}},{“大學(xué)英語”,‘t’,{87}}};

inti;

for(i=0;i<N;i++)

{ printf(“%s\t”,sub[i].name);/*輸出課程名*/

if(sub[i].type==‘t’) /*若課程為考試課*/

{ printf(“考試\t”);

printf(“%d”,sub[i].sc.num);

/*考試課成績采用百分制記錄*/

}

else

/*若課程為考查課*/

{ printf("考核\t");

switch(sub[i].sc.grade) /*考查課成績采用等級(jí)制記錄*/

{ case'A':printf("優(yōu)");break; case'B':printf("良");break;

case'C':printf("中");break;

case'D':printf("及格");break;

case'E':printf("不及格");break;

default:printf("缺考");

}

}

printf("\n");

}

}

說明:

(1)結(jié)構(gòu)體類型可以包含共用體變量,反之,共用體類型也可以包含結(jié)構(gòu)體變量。本例中結(jié)構(gòu)體類型“structsubject”中表示成績的成員就是共用體變量“unionscoresc;”。

(2)共用體變量初始化的值放在一對(duì)大括號(hào)中。

因?yàn)樵诠灿皿w中同一時(shí)刻只有一個(gè)成員起作用,所以初始化時(shí)只需要賦一個(gè)值就可以了。本例中針對(duì)共用體部分的初始化實(shí)際上相當(dāng)于如下賦值語句:

sub[0].score.num=92;

sub[1].score.grade=’B’;

sub[2].score.num=’87’;

(3)通常會(huì)定義一個(gè)狀態(tài)變量與共用體配合使用,根據(jù)狀態(tài)變量取值的不同來確定共用體變量當(dāng)前生效的成員。本例將結(jié)構(gòu)體成員考核方式“chartype”與成績“unionscoresc”搭配使用。當(dāng)課程為考試課(sub[i].type==‘t’)時(shí),成績中生效的成員是num;當(dāng)課程為考查課(sub[i].type==‘f’)時(shí),成績中生效的成員是grade。

程序運(yùn)行結(jié)果如圖7-11所示。圖7-11例7-5程序運(yùn)行結(jié)果

【例7-6】

某學(xué)生管理系統(tǒng)錄入學(xué)生的個(gè)人信息時(shí),每個(gè)學(xué)生首先需輸入姓名、學(xué)號(hào)和性別。如果是男生,則繼續(xù)登記視力是否正常(正常記Y,異常記N);如果是女生,則繼續(xù)登記身高和體重。#include<stdio.h>#defineN2structstudent{ charname[10];

/*姓名*/

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論