第9章結(jié)構(gòu)體與共用_第1頁
第9章結(jié)構(gòu)體與共用_第2頁
第9章結(jié)構(gòu)體與共用_第3頁
第9章結(jié)構(gòu)體與共用_第4頁
第9章結(jié)構(gòu)體與共用_第5頁
已閱讀5頁,還剩87頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第9章結(jié)構(gòu)體與共用體結(jié)構(gòu)體共用體用typedef定義類型枚舉類型9.1概述有時需要將不同類型的數(shù)據(jù)組合成一個有機的整體以便于引用,如:

一個學(xué)生的學(xué)號,姓名,性別,年齡,成績,住址等.分別定義簡單變量難以反映它們之間的聯(lián)系.應(yīng)當將它們組成一個組合項,其中可以包含若干個類型不同的數(shù)據(jù)項.C提供的結(jié)構(gòu)體相當于記錄引例:編寫一程序,實現(xiàn)電話號碼查詢。假設(shè)有一電話號碼表,信息包括戶主的姓名、戶主地址、電話號碼,輸入一個電話號碼,找出該號碼對應(yīng)的戶主的姓名、地址。#include"stdio.h"#include"string.h"voidmain(){charname[3][8],address[3][10],tel[3][8],temp[8];inti,flag=1;for(i=0;i<3;i++){printf("姓名:");gets(name[i]);printf("地址:");gets(address[i]);printf("電話號碼:");gets(tel[i]);}printf("請輸入號碼:");gets(temp);for(i=0;i<3;i++){if(strcmp(tel[i],temp)==0){puts(name[i]);puts(address[i]);flag=0;break;}}if(flag==1)puts("無此人");}9.1.1結(jié)構(gòu)體類型定義struct結(jié)構(gòu)體名{成員表列};類型說明符成員名;聲明一個結(jié)構(gòu)體類型的一般形式structstudent

{intnum;

charname[20];

charsex;

intage;

floatscore;

charaddr[30];

};關(guān)鍵字

不能省略結(jié)構(gòu)體類型名,和標準類型

名一樣可以定義變量成員列表,每個成員又稱

分量或域.

成員名定名規(guī)則與變量同作為語句,必須以分號結(jié)束說明:(1)struct是關(guān)鍵字,必須原樣寫出,表示定義一個結(jié)構(gòu)體類型;(2)結(jié)構(gòu)體名、成員名的命名規(guī)則與標識符的定義規(guī)則相同;(3)結(jié)構(gòu)體類型定義是一個語句,應(yīng)以分號結(jié)束;(4)結(jié)構(gòu)體的嵌套定義。如:

structdate{intmonth;intday;intyear;} structstudent{intnum;charname[20];charsex;intage;structdatebirthday;charaddr[30];}student1,student2;(5)結(jié)構(gòu)體類型的定義只說明了該類型的構(gòu)成形式,系統(tǒng)并不為其分配內(nèi)存空間.(6)不同結(jié)構(gòu)體類型的成員名可以相同;(7)struct結(jié)構(gòu)體類型名“為結(jié)構(gòu)體的類型說明符,可用于定義或說明變量。9.1.2定義結(jié)構(gòu)體類型變量的方法1.先定義結(jié)構(gòu)體類型再定義變量名3.直接定義結(jié)構(gòu)體類型變量2.在定義類型的同時定義變量9.1.3結(jié)構(gòu)體類型變量的引用不能將一個結(jié)構(gòu)體變量為一個整體進行輸入輸出只能對最低級的成員進行賦值、存取以及運算對成員變量可以象普通變量一樣進行各種運算可以引用成員的地址,也可以引用結(jié)構(gòu)體變量的地址引用形式:結(jié)構(gòu)體變量名.成員名9.1.4結(jié)構(gòu)體變量的賦值1.定義結(jié)構(gòu)體變量時初始化【例9.1】在定義時對結(jié)構(gòu)體變量賦初值。參考程序如下:#include<stdio.h>voidmain(){structstu{intnum;charname[20];charsex;floatscore;}a={1001,"Zhang",'M',78.5}; /*定義結(jié)構(gòu)體變量并初始化*/structstub={1002,"Wang",'F',67.5};printf("NO.=%d\tName=%s\tsex=%c\tscore=%5.2f\n",a.

num,,a.sex,a.score);/*輸出結(jié)構(gòu)體a的值*/printf("NO.=%d\tName=%s\tsex=%c\tscore=%5.2f\n",b.

num,,b.sex,b.score);/*輸出結(jié)構(gòu)體b的值*/}2.結(jié)構(gòu)體變量定義后【例9.2】在定義后對結(jié)構(gòu)體變量賦初值。參考程序如下:#include<stdio.h>#include<string.h>structstu/*定義結(jié)構(gòu)體類型*/{intnum;charname[20];charsex;floatscore;}a;/*定義結(jié)構(gòu)體變量a*/voidmain(){structstub;/*定義結(jié)構(gòu)體變量b*/a.num=1001;printf("輸入姓名:");gets();a.sex='M';a.score=76.5;b=a;/*將結(jié)構(gòu)體a賦值給結(jié)構(gòu)體變量b*/printf("No.=%d\tName=%s\tsex=%c\tscore=%5.2f\n",a.

num,,a.sex,a.score);printf("No.=%d\tName=%s\tsex=%c\tscore=%5.2f\n",b.

num,,b.sex,b.score);}【例9.3】有兩條記錄,記錄包括數(shù)量(num)和價錢(price),編寫一程序完成總價錢的計算。參考程序如下:#include<stdio.h>structp{intnum;floatprice;};voidmain(){structpa,b;floatsum;printf("輸入第一個數(shù)量和價格:\n");scanf("%d%f",&a.num,&a.price);printf("輸入第二個數(shù)量和價格:\n");scanf("%d%f",&b.num,&b.price);sum=a.num*a.price+b.num*b.price;printf("sum=%5.2f",sum);}9.2結(jié)構(gòu)體數(shù)組和結(jié)構(gòu)體指針9.2.1結(jié)構(gòu)體數(shù)組結(jié)構(gòu)體數(shù)組與以前介紹的數(shù)值型數(shù)組不同之處在于每個數(shù)組元素都是一個結(jié)構(gòu)體類型的數(shù)據(jù)一、結(jié)構(gòu)體數(shù)組的定義二、結(jié)構(gòu)體數(shù)組的初始化三、舉例:對候選人得票的統(tǒng)計程序.例如9.2.2指向結(jié)構(gòu)體類型數(shù)據(jù)的指針一個結(jié)構(gòu)體變量的指針就是該變量所占據(jù)的內(nèi)存段的起始地址,可以設(shè)一個指向一個結(jié)構(gòu)體變量的指針變量指向結(jié)構(gòu)體變量的指針指向結(jié)構(gòu)體數(shù)組的指針如上面已定義的結(jié)構(gòu)類型structstudent,可以用它來定義變量:structstudentstudent1,student2變量名注意:定義標準類型變量和定義結(jié)構(gòu)體類型變量不同,

前者類型是已知的(如int,float),而后者要先定義類型后

定義變量人們通常用一個符號常量代表一個結(jié)構(gòu)體類型

#defineSTUDENTstructstudent先聲明結(jié)構(gòu)體類型再定義變量名structstudent

{intnum;

charname[20];

charsex;

intage;

floatscore;

charaddr[30];

}student1,student2;變量名列表在聲明類型的同時定義變量定義的一般形式為:struct結(jié)構(gòu)體名{

成員表列}變量名表列struct

{intnum;

charname[20];

charsex;

intage;

floatscore;

charaddr[30];

}student1,student2;直接定義結(jié)構(gòu)體類型變量printf(“%d,%s,%c,%d,%f,%s\n”,student1);引用方式:結(jié)構(gòu)體變量名.成員名。如:student1.num結(jié)構(gòu)體變量名成員名成

符(1)不能將結(jié)構(gòu)體變量作為整體進行輸入輸出。如果成員本身又是一個結(jié)構(gòu)體類型,則要用成員運算符一級一級地找到最低一級的成員structstudent

{intnum;

charname[20];

charsex;

intage;

structdatebirthday;

charaddr[30];

}student1,student2;

structdate

{intmonth;intday;

intyear;

};正確引用:

student1.num

student1.birthday.daystudent2.score=student1.score;

sum=student1.score+student2.score;

student1.age++;

++student2.birthday.year;“.”的優(yōu)先級最高可以:

scanf(“%d”,&student1.num);

printf(“%o”,&student2);不可以:

scanf(“%d%s%c%d%f%s”,&student1);structstudent

{longintnum;

charname[20];

charsex;

charaddr[30];

}a={89031,"LiLin",'M',"123BeijingRoad"};

main()

{printf(“No.:%ld\nname:%s\nsex:%c\naddress:%s\n”,a.num,,a.sex,a.addr);}No.:89031name:LiLinsex:Maddress:123BeijingRoad返回方法1:structstudent

{intnum;

charname[20];

charsex;

intage;

floatscore;

charaddr[30];

};

structstudentstu[3];方法2:structstudent

{intnum;

charname[20];

charsex;

intage;

floatscore;

charaddr[30];

}stu[3];方法3:struct

{intnum;

charname[20];

charsex;

intage;

floatscore;

charaddr[30];

}stu[3];

numnamesexagescoreddr

10101LiLinM1887.5103BeijingRoad

10102ZhangyiM1999130ShanghaiRoad

10103WangerF2078.51010JinanRoad

stu[0]

stu[1]

stu[2]數(shù)組各元素在內(nèi)存中連續(xù)存放10101

“LiLin”

‘M’

18

87.5

“103BeijingRoad”

10102

“zhangyi”

‘M’

19

...stu[0]stu[1]structstudent

{longintnum;

charname[20];

charsex;

charaddr[30];

}stu[3]={{89031,”LiLin”,’M’,”123BeijingRoad”},{10102,”Zhangyi”,…},

{10103,…}};例9.3指向結(jié)構(gòu)體變量的指針#include<string.h>voidmain(){structstudent{longnum;charname[20];charsex;floatscore;};structstudentstu_1;structstudent*p;p=&stu_1;stu_1.num=89101;strcpy(stu_1.name,"LiLin");stu_1.sex='M';stu_1.score=89.5;printf("No.:%ld\nname:%ssex:%c\nscore:%f\n",stu_1.num,stu_1.name,stu_1.sex,stu_1.score);printf("No.:%ld\nname:%ssex:%c\nscore:%f\n",(*p).num,(*p).name,(*p).sex,(*p).score);}三種等價形式:1結(jié)構(gòu)體變量.成員名2(*p).成員名3p->成員名structstudentstu;

structstudent*p;

p=&stu;89101

“LiLin”

‘M’

89.5pstu.num

stu.sex

stu.score(*p).num

(*p).name

(*p).sex

(*p).scorep->num

p->name

p->sex

p->score分析以下幾種運算:指向運算符p->n++p->np->n++使用值后加1先加1后使用值9.2.2指向結(jié)構(gòu)體數(shù)組的指針例9.2指向結(jié)構(gòu)體數(shù)組的指針structstudent{intnum;charname[20];charsex;intage;};structstudentstu[3]={{10101,"LiLin",'M',18},(10102,"ZhangFun",'M',19},{10104,"WangMin",'F',20}};voidmain(){structstudent*p;printf("No.Namesexage\n");for(p=stu;p<stu+3;p++)printf("%5d%-20s%2c%4d\n",p->num,p->name,p->sex;p->age);}p已有一個結(jié)構(gòu)體數(shù)組:

structstudentstu[4]={...};再定義一個指針變量:

structstudent*p;

p=stu;如:for(p=stu;p<stu+3;p++)

printf(“%5d,%-20s,%2c,%4d”,p->num,

p->name,p->sex,p->age);注:

先使p指向數(shù)組stu的起始地址,并于第一個循環(huán)輸

出stu[0]的各個成員.

然后p+1意味著增加的地址值為結(jié)構(gòu)體類型數(shù)組stu

的一個元素所占的字節(jié)數(shù)注意區(qū)別:(++p)->num

(p++)->nump已定義為指向structstudent類型的數(shù)據(jù):p=stu;正確(數(shù)組名)

p=&;錯誤(不能指向結(jié)構(gòu)體成員)

p=(structstudent*)&例9.6有4名學(xué)生,每個學(xué)生的信息包括學(xué)號、姓名、成績,要求通過指針方法找出成績最高者的姓名和成績#include<stdio.h>voidmain(){structstudent{longnum;charname[20];floatscore;};structstudentstu[4];structstudent*p;inti,temp=0;for(p=stu;p<stu+4;p++)scanf(“%ld%s%f”,&p->num,p->name,&p->score);for(max=stu[0].score,i=1;i<4;i++)if(stu[i].score>max){max=stu[i].score;temp=i;}p=stu+temp;printf(“%ld%s%f”,p->num,p->name,p->score);9.2.3結(jié)構(gòu)體作函數(shù)參數(shù)有3種方法:

1.用結(jié)構(gòu)體變量成員作參數(shù),如:主函數(shù)中:

...

print();

...被調(diào)函數(shù)中:

voidprint(chara[])

{…}2.用結(jié)構(gòu)體變量作實參,如:主函數(shù)中:

...

print(stu);

...被調(diào)函數(shù)中:

voidprint(structstudenta)

{…}3.用指向結(jié)構(gòu)體變量(或數(shù)組)的指針作實參,將結(jié)構(gòu)體(或數(shù)組)的地址傳給形參.主函數(shù)中:

...

print(&stu);

...被調(diào)函數(shù)中:

voidprint(structstudent*a)

{…}1、結(jié)構(gòu)體變量作函數(shù)的參數(shù)【例9.7】編寫一個函數(shù),輸出結(jié)構(gòu)體變量各成員的值。參考程序如下:#include<stdio.h>structs{intchinese;intmaths;};voidprint(structsy){printf("chinese=%d\tmaths=%d\n",y.chinese,y.maths);}voidmain(){structsx;scanf("%d%d",&x.chinese,&x.maths);print(x);}2、結(jié)構(gòu)體數(shù)組作函數(shù)參數(shù)【例9.8】一個班有5名學(xué)生,學(xué)生信息包括學(xué)號(num)和三門成績(score[3]),編寫一個函數(shù),統(tǒng)計不及格學(xué)生的人數(shù)及輸出不及格學(xué)生的學(xué)號。參考程序如下:#include<stdio.h>structstu/*全局的結(jié)構(gòu)體類型*/{intnum;intscore[3];};intcount(structstus[],intn)/*形參數(shù)組和長度*/{inti,j,c=0,flag;/*flag變量是標志位*/printf("numberis:\n");for(i=0;i<n;i++){flag=0;/*flag==0假設(shè)沒有不及格的*/for(j=0;j<3;j++)if(s[i].score[j]<60){flag=1;/*flag==1找到一個不及格的*/break;/*不用再繼續(xù)查找了,可以退出循環(huán)*/}if(flag==1)/*如果flag為1,說明有不及格的*/{c++;/*將統(tǒng)計變量c加1*/printf("%d\n",s[i].num);/*輸出有不及格成績的人的學(xué)號*/}}return(c);/*將C值返回到主函數(shù)中*/}voidmain(){intc;structstua[5]={{1001,67,56,78},{1002,78,78,90},{1003,67,85,45},{1004,89,67,89},{1005,83,92,99}};c=count(a,5);/*實參是數(shù)組名和長度*/printf("nopassis:%d",c);}【例9.9】一個班有5名學(xué)生,學(xué)生信息包括學(xué)號(num)、語文成績(chinese)、英語成績(english)、數(shù)學(xué)成績(maths),編寫一個函數(shù),計算各學(xué)生的總成績及平均成績。參考程序如下:#include<stdio.h>structstu{intnum;intchinese,english,maths;intsum;floataver;};voidsum(structstustudent[],intn){inti;for(i=0;i<n;i++){student[i].sum=student[i].chinese+student[i].

english+student[i].maths;student[i].aver=student[i].sum/3.0;}}voidmain(){inti;structstua[5]={{1001,67,56,78}, {1002,78,78,90}, {1003,67,85,45}, {1004,89,67,89}, {1005,83,92,99}};sum(a,5);printf("num\tchinese\tenglish\tmaths\tsum\taverage");printf("\n");for(i=0;i<5;i++)printf("%d\t%d\t%d\t%d\t%d\t%.2f\n",a[i].num,a[i].chinese,a[i].english,a[i].maths,a[i].sum,a[i].aver);}3、指向結(jié)構(gòu)體的指針作函數(shù)參數(shù)【例9.10】將例9.7改用指向結(jié)構(gòu)體變量的指針作形參。參考程序如下:#include<stdio.h>structs{intchinese;intmaths;};voidprint(structs*p){printf("chinese=%d\tmaths=%d",p->chinese,p->maths);printf("\n");}voidmain(){structsx;scanf("%d%d",&x.chinese,&x.maths);print(&x);}9.2.4結(jié)構(gòu)體舉例【例9.11】一個班有5名學(xué)生,學(xué)生信息包括姓名、年齡、家庭住址等,按照姓名升序進行輸出。參考程序如下:#include<stdio.h>#include<string.h>structuser_info{charname[20];intage;charphone[20];charaddress[80];};voidmain(){inti,j,k;structuser_infotmp;structuser_infouser[5]={{"Li",31,"1258746","Beijing"},{"Zhao",39,"5897412","Shanghai"},{"Qian",28,"3654879","Chongqing"},{"Zhou",30,"5632146","Hangzhou"},{"Sun",34,"8632541","Shenyang"}};for(i=1;i<5;i++)/*按姓名從小到大排序*/{k=5-i;for(j=0;j<5-i;j++)if(strcmp(user[j].name,user[k].name)>0)k=j;if(k!=5-i){tmp=user[k];user[k]=user[5-i];user[5-i]=tmp;}}printf("%20s%5s%15s%20s","name","age","phone","address");printf("\n");for(i=0;i<5;i++)printf("%20s%5d%15s%20s\n",user[i].name,user[i].age,

user[i].phone,user[i].address);}9.3用指針處理鏈表-結(jié)構(gòu)體指針的應(yīng)用9.3.1概述1.鏈表結(jié)構(gòu)鏈表作為一種常用的、能夠?qū)崿F(xiàn)動態(tài)存儲分配的數(shù)據(jù)結(jié)構(gòu),在《數(shù)據(jù)結(jié)構(gòu)》課程中有詳細介紹。下圖所示為單鏈表。(1)頭指針變量head──指向鏈表的首結(jié)點。(2)每個結(jié)點由2個域組成:

1)數(shù)據(jù)域──存儲結(jié)點本身的信息。

2)指針域──指向后繼結(jié)點的指針。(3)尾結(jié)點的指針域置為“NULL(空)”,作為鏈表結(jié)束的標志。注意:鏈表和數(shù)組具有相同的邏輯結(jié)構(gòu),它們之間的區(qū)別是,數(shù)組各元素的存儲空間是連續(xù)的、固定的,數(shù)組元素個數(shù)一經(jīng)定義是不可改變的;而鏈表中的元素個數(shù)是可變化的,元素的存儲空間是動態(tài)分配的,邏輯上相鄰的結(jié)點其存儲空間不一定相鄰。2.C語言對鏈表結(jié)點的結(jié)構(gòu)描述

在C語言中,用結(jié)構(gòu)類型來描述結(jié)點結(jié)構(gòu)。例如:

structgrade{charno[7]; /*學(xué)號*/intscore; /*成績*/structgrade*next; /*指針域*/};#include<stdio.h>#include<stdlib.h>#include<stdio.h>#defineNULL0structstudent{longnum;floatscore;structstudent*next;};voidmain(){structstudenta,b,c,*head,*p;a.num=10101;a.score=89.5;b.num=10103;b.score=90;c.num=10107;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);}9.3.2處理動態(tài)鏈表所需的函數(shù)常用的內(nèi)存管理函數(shù)有以下三個,注意在使用時請加頭文件:

#include<stdlib.h>1.分配內(nèi)存空間函數(shù)malloc函數(shù)原型:void*malloc(unsignedsize);函數(shù)調(diào)用的一般形式:(類型說明符*)malloc(size)說明:

(1)malloc函數(shù)要求系統(tǒng)在內(nèi)存中分配一塊存儲空間,這個存儲空間是一塊長度為“size”字節(jié)的連續(xù)區(qū)域,函數(shù)的返回值為該區(qū)域的首地址。(2)函數(shù)返回的指針是無類型的,用戶要根據(jù)存儲空間的用途把它強制轉(zhuǎn)換成相應(yīng)的類型。所以,“類型說明符”表示把該區(qū)域用于何種數(shù)據(jù)類型:(類型說明符*)表示把返回值強制轉(zhuǎn)換為該類型指針。(3)“size”是一個無符號數(shù),單位為字節(jié)。如下語句:p=(char*)malloc(100);【例9.13】應(yīng)用malloc()動態(tài)分配存儲空間。參考程序如下:#include<stdio.h>#include<stdlib.h>voidmain(){int*p;p=(int*)malloc(2);*p=20;printf("%d",*p);}2.分配內(nèi)存空間函數(shù)calloc函數(shù)原型:void*calloc(unsignedintn,unsignedintsize);函數(shù)調(diào)用的一般形式:(類型說明符*)calloc(n,size)說明:(1)函數(shù)實現(xiàn)的功能是在內(nèi)存動態(tài)存儲區(qū)中分配n塊長度為“size”字節(jié)的連續(xù)區(qū)域,函數(shù)的返回值為該區(qū)域的首地址。(2)(類型說明符*)用于強制類型轉(zhuǎn)換。(3)calloc函數(shù)與malloc函數(shù)的區(qū)別僅在于一次可以分配n塊區(qū)域。如下語句:ps=(structstu*)calloc(2,sizeof(structstu));3.釋放內(nèi)存空間函數(shù)free函數(shù)原型:voidfree(void*p);函數(shù)調(diào)用的一般形式:free(p);說明:釋放p所指向的一塊內(nèi)存空間,p是一個任意類型的指針變量,它指向被釋放區(qū)域的首地址,被釋放區(qū)域應(yīng)該是由mal1oc或calloc函數(shù)所分配的區(qū)域?!纠?-14】動態(tài)分配存儲空間函數(shù)應(yīng)用。參考程序如下:#include<stdio.h>#include<stdlib.h>voidmain(){structstu{intnum;char*name;charsex;floatscore;}*ps;ps=(structstu*)malloc(sizeof(structstu));ps->num=1001;ps->name="Zhang";ps->sex='M';ps->score=95.5;printf("No.=%d\nName=%s\n",ps->num,ps->name);printf("Sex=%c\nScore=%f\n",ps->sex,ps->score);free(ps);}9.3.3鏈表的基本操作對鏈表的主要操作有以下幾種:建立鏈表、查找鏈表、輸出鏈表、插入結(jié)點、刪除結(jié)點等。1.建立鏈表所謂建立鏈表是指從無到有地建立起一個鏈表,即一個一個地輸入各結(jié)點數(shù)據(jù),并建立起前后相連的關(guān)系。單鏈表的建立過程應(yīng)反復(fù)執(zhí)行下面的3個步驟。(1)調(diào)用malloc()函數(shù)向系統(tǒng)申請一個結(jié)點的存儲空間。(2)輸入該結(jié)點的值,并把該結(jié)點的指針成員設(shè)置為0。(3)把該結(jié)點加入到鏈表中,如果鏈表為空,則該結(jié)點為鏈表的頭結(jié)點,否則把該結(jié)點加入到表尾。【例9.15】建立包含5個結(jié)點的單鏈表,5個結(jié)點的值分別為1001、78,1002、87,1003、54,1004、89,1005、90。參考程序如下:#include<stdio.h>#include<stdlib.h>structnode{intnum,score;structnode*next;};voidmain(){structnode*creat(structnode*head,intn);voidprint(structnode*head);structnode*head=NULL;/*定義表頭指針*/head=creat(head,5);print(head);}structnode*creat(structnode*head,intn){structnode*p,*q;inti;for(i=1;i<=n;i++){/*申請結(jié)點空間*/q=(structnode*)malloc(sizeof(structnode));printf("Input%dnum,score:\n",i);scanf("%d,%d",&q->num,&q->score);q->next=NULL;if(head==NULL)head=q;/*新結(jié)點作為表頭結(jié)點插入鏈表*/elsep->next=q;/*新結(jié)點作為表尾結(jié)點插入鏈表*/p=q;}returnhead;}voidprint(structnode*head){structnode*p=head;printf("num\tscore\n");do{printf("%d\t%d\n",p->num,p->score);p=p->next;/*p指向下一個結(jié)點*/}while(p!=NULL);}2.單鏈表的查找查找是最經(jīng)常使用的操作,查找操作也是更新、刪除等操作的基礎(chǔ)。在鏈表中查找滿足條件的結(jié)點,操作過程和鏈表的輸出過程相似,也要依次掃描鏈表中的各結(jié)點?!纠?.16】編寫一函數(shù),在鏈表中查找指定學(xué)號的學(xué)生成績,找到則輸出成績,否則輸出查找失敗。程序設(shè)計分析:循環(huán)比較輸入的學(xué)號與鏈表中的學(xué)號,循環(huán)初始值是輸入x的值:循環(huán)條件是當鏈表到結(jié)尾也沒有找到該學(xué)號,或者找到該學(xué)號退出循環(huán),循環(huán)結(jié)束的標志是p==NULL,那么循環(huán)條件是p!=NULL&&p->num!=x;循環(huán)體是p向下移動;退出循環(huán)后如果找到該學(xué)號,就輸出相應(yīng)內(nèi)容,如果沒有找到該學(xué)號,p的值應(yīng)該是NULL。參考程序如下:#include<stdio.h>#include<stdlib.h>structnode{intnum,score;structnode*next;};voidfind(structnode*head){structnode*p;intx;printf("輸入要查找的數(shù):\n");scanf("%d",&x);p=head;while(p!=NULL&&p->num!=x)p=p->next;if(p)printf("num=%d\tscore=%d\n",p->num,p->score);elseprintf("%dnotbefound!\n");}3.刪除指定的結(jié)點鏈表中已經(jīng)不需要的結(jié)點應(yīng)該刪除,但刪除結(jié)點不能破壞鏈表的結(jié)構(gòu)。在單鏈表中刪除指定值的結(jié)點,并由系統(tǒng)回收該結(jié)點所占用的存儲空間。具體操作過程如下。(1)從表頭結(jié)點開始,確定要刪除結(jié)點的地址p,以及p的前一個結(jié)點地址q。(2)如果p為頭結(jié)點,刪除后應(yīng)修改表頭指針head,否則修改q結(jié)點的指針域。(3)回收p結(jié)點的空間。刪除結(jié)點的過程如圖9-4所示。pqheadNULL【例9.17】編寫一函數(shù),在鏈表中刪除指定學(xué)號的結(jié)點,函數(shù)返回刪除后的表頭指針。參考程序如下:#include<stdio.h>#include<stdlib.h>structnode{intnum,score;structnode*next;};structnode*dele(structnode*head){intx;structnode*p,*q;p=head;printf("輸入要刪除的學(xué)號:\n");scanf("%d",&x);while(p!=NULL&&p->num!=x)/*查找被刪除結(jié)點*/{q=p;p=p->next;}if(p==NULL)printf("%disnotfound!\n");elseif(p==head)/*刪除表頭結(jié)點*/head=p->next;elseq->next=p->next;/*刪除中間結(jié)點*/free(p);return(head);}4.在鏈表中插入結(jié)點根據(jù)應(yīng)用的需要,可以在鏈表中加入新結(jié)點。加入的結(jié)點可以放在表頭、表尾或鏈表的任意位置。例如,要在學(xué)生成績表中加入一個學(xué)生的考試成績,為了保持鏈表中學(xué)號的連續(xù)性(按從小到大的順序排列),需要根據(jù)加入結(jié)點的學(xué)號值把該結(jié)點插入到鏈表的適當位置。在鏈表中插入新結(jié)點的一般過程如下:(1)調(diào)用malloc()函數(shù)分配一個結(jié)點空間,并輸入新結(jié)點的值。(2)查找合適的插入位置。(3)修改相關(guān)結(jié)點的指針域?!纠?.18】編寫一函數(shù),把某學(xué)生的考試成績添加到學(xué)生信息鏈表中,添加結(jié)點后,鏈表中的各結(jié)點還應(yīng)按學(xué)號從小到大順序排列。參考程序如下:#include<stdio.h>#include<stdlib.h>structnode{intnum,score;structnode*next;};structnode*insert(structnode*head){structnode*q,*p,*p1;q=(structnode*)malloc(sizeof(structnode));printf("輸入學(xué)號、成績:\n");scanf("%d,%d",&q->num,&q->score);if(head==NULL)/*在空表中插入*/{q->next=NULL;head=q;return(head);}if(head->num>q->num)/*新結(jié)點插入在表頭之前*/{q->next=head;head=q;returnhead;}p=head;p1=head->next;/*在鏈表中查找插入位置*/while(p1!=NULL&&p1->num<q->num){p=p1;p1=p1->next;}q->next=p1;p->next=q;return(head);}【例9.19】一個班有5名學(xué)生,學(xué)生信息包括學(xué)號、姓名和成績,統(tǒng)計并輸出最高分的學(xué)生信息。參考程序如下:#include<stdio.h>#include<stdlib.h>structnode{intnum,score;charname[10];structnode*next;};voidmain(){structnode*creat(structnode*head,intn);voidprint(structnode*head);voidfind(structnode*head);structnode*head=NULL;/*定義表頭指針*/head=creat(head,3);print(head);find(head);}voidfind(structnode*head){structnode*p,*q;intx;p=q=head;x=p->score;while(p!=NULL){if(p->score>x){x=p->score;q=p;}p=p->next;}printf("最高分學(xué)生學(xué)號:姓名:成績:\n");printf("num=%d\t%s\tscore=%d\n",q->num,q->name,q->score);}structnode*creat(structnode*head,intn){structnode*p,*q;inti;for(i=1;i<=n;i++){/*申請結(jié)點空間*/q=(structnode*)malloc(sizeof(structnode));printf("Input%d學(xué)號,成績和姓名:\n",i);scanf("%d%d%s",&q->num,&q->score,q->name);q->next=NULL;if(head==NULL)head=q;/*新結(jié)點作為表頭結(jié)點插入鏈表*/elsep->next=q;/*新結(jié)點作為表尾結(jié)點插入鏈表*/p=q;}returnhead;}voidprint(structnode*head){structnode*p=head;printf("num\tname\tscore\n");while(p!=NULL){printf("%d\t%s\t%d\n",p->num,p->name,p->score);p=p->next;}/*p指向下一個結(jié)點*/}9.4共用體

9.4.1共用體的概念有時需要將幾種不同類型的變量存放到同一段內(nèi)存單元中,如:將一個整型變量,一個字符型變量,一個實型變量放在同一個地址開始的內(nèi)存單元中.由于三個變量在內(nèi)存中占的字節(jié)數(shù)不同,故使用覆蓋技術(shù),使三個變量互相覆蓋.9.4.2定義共用體類型變量的方法先定義共用體類型再定義變量名在定義類型的同時定義變量直接定義共用體類型變量9.4.3共用體變量的引用方式先定義后使用,不能引用共用體變量,只能引用共用體變量中的成員.

如正確引用:a.i

a.ch

a.f

錯誤引用:printf(“%d”,a);繼續(xù)

uniondata

{inti;

charch;

floatf;

}a,b,c;關(guān)鍵字共用體名成員表列變量表列union共用體{成員表列}變量表列在定義類型的同時定義變量

uniondata

{inti;

charch;

floatf;

};

uniondataa,b,c;先定義共用體類型再定義變量名union{inti;

charch;

floatf;

}a,b,c;共用體與結(jié)構(gòu)體形式相似,而含義不同:

結(jié)構(gòu)體變量所占內(nèi)存長度是各成員占的內(nèi)存

長度之和.共用體變量所占內(nèi)存長度等于各成

員中占的內(nèi)存長度最長的.共用體類型數(shù)據(jù)的特點:(1)同一內(nèi)存段可以用來存放幾種不同類型的成員,但每一瞬時只能存放其中一種(2)共用體變量中起作用的成員是最后一次存放的成員a.i=1;a.c='a';a.f=1.5;(3)共用體變量的地址和它的成員地址都是同一地址例如:&a,&a.i,&a.c,&a.f表示的是同一地址#include<stdio.h>voidmain(){union{inti;charch;floatf;}a;a.i=1;a.ch='a';a.f='1.5';printf("%d,%c,%f\n",a.i,a.ch,a.f);printf("%x,%x,%x",&a.i,&a.ch,&a.f);}(4)不能對共用體變量名賦值,如a=1不能引用變量名來得到成員值,如m=a不能初始化.如:union{inti;charch;floatf;}a={1,'a',1.5};(5)不能把共用體變量作為函數(shù)參數(shù),也不能使函數(shù)帶回共用體變量,但可以用指向共用體變量的指針(6)共用體類型可以出現(xiàn)在結(jié)構(gòu)體類型定義中,也可以定義共用體數(shù)組.反之依然.例如如果一個變量只有幾種可能的值,可以定義為枚舉類型.變量的值只限于列舉出來的值的范圍內(nèi).enumweekday{sun,mon,tue,wed,thu,fri,sat};關(guān)鍵字枚舉類型名枚舉元素或

枚舉常量9.5枚舉類型也可以直接定義枚舉變量enum{sun,mon,tue,wed,thu,fri,sat}workday,week_end;然后,可以定義變量:

enumweekdayworkday,week_end;說明:在C編譯中,對枚舉元素按常量處理,不能賦值.枚舉元素作為常量,標識符并不代表什么含義.但它們是有值的,C語言編譯按順序為:0,1,2,3……。

由上面定義,則sun值為0,mon的值為1,...sat值為6。

也可以改變枚舉元素的值,如:

enumweekday{sun=7,mon=1,tue,wed,thu,fri,sat}day;枚舉值可以用來作判斷比較一個整數(shù)不能直接賦給一個枚舉變量.如:

day=2;錯誤,因它們不屬于同一類型.應(yīng)先進行強制類型轉(zhuǎn)換,如:

workday=(enumweekday)2;此相當于將序號為2的枚舉元素賦給workday.表達式也可以.例如9.6用typedef定義類型除了可以使用C提供的標準類型名和自定義的結(jié)構(gòu)體、共用體、

枚舉類型外,還可以typedef定義新的類型名來代替已有的類型名。typedefintINTEGER;

typedeffloatREAL;

inti,j;floata;b;等價于

INTEGERi,j;REALa,b;聲明結(jié)構(gòu)體類型:typedefstruct

{intmonth;

intday;

intyear;}DATE;

可以定義變量:

DATEbirthday;

DATE*p;不要寫成structDATEbirthday定義一個新的類型名的方法:

①先按定義變量的方法寫出定義體(inti;)

②將變量名換成新類型名(將i換成COUNT)

③在最前面加typedef(typedefintCOUNT)

④然后用新類型名去定義變量如:typedefintNUM[100];

NUMn;如:typedefchar*STRING;STRINGp,s[10];如:typedefint(*POINTER)();POINTERp1,p2;定義NUM為整型數(shù)組類型定義n為整型數(shù)組變量定義STRING為字符指針類型P為字符指針變量,s為指針數(shù)組定義POINTER為指向返回整型值的函數(shù)的指針類型P1,p2為POINTER型指針變量typedefintCOUNT;COUNTi;說明:用typedef可以定義各種類型名,但不能用來定義變量用typedef只是對已經(jīng)存在的類型增加一個類型名,而沒有創(chuàng)造出新類型typedef與#define有相似之處.但事實上二者不同,預(yù)編譯只作簡單的字符替換,typedef是在編譯時處理的,它如同定義變量那樣來定義一個類型typedef有利于程序的移植.比如,我們要使用一類4字節(jié)的變量。typedeflonginteger對4字節(jié)的機器作業(yè):1、編程實現(xiàn)某班學(xué)生信息管理:學(xué)生信息包括姓名、學(xué)號、性別、出生日期,三門課成績,家庭住址,創(chuàng)建一個學(xué)生信息的單向鏈表并輸出該信息,按學(xué)號對學(xué)生信息排序。從鍵盤輸入一學(xué)生學(xué)號,輸出該學(xué)生的信息。如果班級有學(xué)生退學(xué),根據(jù)學(xué)號刪除該生信息。如果班級新進學(xué)生,根據(jù)學(xué)號將其添加到系統(tǒng)里。(用到鏈表的創(chuàng)建、輸出、查找、刪除、添加和排序)2、認真完成課后習題本章結(jié)束C語言程序設(shè)計例9-23個候選人,輸入得票人的名字,要求最后輸出個人得票結(jié)果#include"string.h"structperson{charname[20];intcount;}leader[3]={"li",0,"zhang",0,"fun",0};main(){inti,

溫馨提示

  • 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)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論