版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C语言程序设计技术基础太原理工大学计算机学院计算机基础部第9章结构体、联合体和枚举类型§9.1结构体类型§9.2结构体数组§9.3结构体指针§9.4结构体变量与函数
§9.5联合体§9.6枚举类型第9章结构体、联合体和枚举类型§9.7用户自定义类型——typedef§9.8程序举例§9.1结构体类型9.1.1结构体类型的定义和说明9.1.2结构体变量的定义9.1.3结构体变量的初始化9.1.4结构体变量成员的引用9.1.1结构体类型的定义和说明C语言提供了一种称为结构体的构造数据类型,它可以将同一个对象的不同类型的属性数据组成一个有联系的整体。也就是说,可以定义一种结构体类型,将属于同一个对象的不同类型的属性数据组合在一起,形成整体的结构体类型,然后定义该结构体类型的变量来存储、处理每个对象的信息。结构体类型的定义形式为:struct结构体名{
成员说明表列};结构体类型的成员表列说明:{
类型说明符1成员标识符1;
类型说明符2成员标识符2;……
类型说明符n
成员标识符n;}9.1.1结构体类型的定义和说明【例9
-1】有一个学生成绩表,如表9-1所示,定义一个结构体类型表示此结构。表9-1学生成绩表structstudent{ longnumber; charname[20]; charclass[20]; floatMath; floatEnglish;};学号姓名班级数学成绩英语成绩1009LilinTongxin120187891010ZhangxiaoCehui12028590其中struct是关键字,声明结构体类型时必须使用,不能省略;student是结构体名;“structstudent”作为一个整体表示类型名,它和系统提供的标准类型(如int、char、float等)一样具有相同的作用,都可以用来定义变量的类型;number、name、class、Math、English称为成员;请注意不要忽略了{}外面最后的分号。9.1.1结构体类型的定义和说明说明:(1)结构体名和结构体的成员名遵循C语言标识符的命名规则,建议用具有一定意义的单词或组合来命名。(2)结构体成员的类型定义形式同简单变量的定义形式。(3)定义结构体类型后,系统并不分配存储空间来存放各个成员。它的作用在于告诉系统该结构是由哪些类型的成员构成的,并把它们当成一个整体来处理。只有定义了该结构体类型的变量,系统才会为变量分配存储空间。9.1.2结构体变量的定义为了在程序中能够使用结构体类型的数据,应当定义结构体类型的变量,并在其中存放具体的值。共有3种方法定义结构体类型的变量。1.先定义结构体类型,再定义结构体变量struct结构体名{
成员说明表列};struct结构体名结构体变量列表;例如用【例9-1】中定义的structstudent类型定义结构体变量stu1、stu2,可表示为:structstudentstu1,stu2;而stu1和stu2就是具有structstudent结构的结构体变量。注意不能错写为:structstu1,stu2;(没有声明是哪一种结构体类型)或:studentstu1,stu2;(没有关键字struct,不认为是结构体类型)9.1.2结构体变量的定义2.在定义结构体类型的同时定义结构体变量
struct结构体名{
成员说明表列}结构体变量列表;例如,在定义structteacher的同时,定义与它具有相同结构的结构体变量tea1、tea2。structteacher{ longnumber; charname[20]; chardepartment[20]; floatsalary; chartelephone[20];}tea1,tea2;定义了两个structteacher类型的变量tea1、tea2。它的作用与第一种方法相同,如果有必要,还可以采用第一种方法再定义另外的结构体类型变量,如structteacherdean。9.1.2结构体变量的定义3.不出现结构体名,直接定义结构体变量
struct{
成员说明表列}结构体变量列表;例如:struct{ longindentityNo; charname[20]; intage; charsex; charaddr[40];}student,teacher,worker;这里只定义了student、teacher和worker3个变量为结构体类型,但没有定义该结构体类型的名字,因此,不能再用它来定义其他变量。例如:structpolice;是不正确的。9.1.2结构体变量的定义【例9
-2】在【例9-1】的结构体类型structstudent中增加birthday成员。birthday的数据类型是date结构体类型,代表出生日期,包括month、day、year3个成员。分析:可以先定义一个结构体类型structdate,然后在定义structstudent类型时,将成员birthday指定为structdate类型。structdate /*定义一个结构体类型*/{ intmonth; intday; intyear;};structstudent{ longnumber; charname[20]; structdatebirthday; /*birthday是structdate类型*/ charclass[20]; floatMath; floatEnglish;};
9.1.2结构体变量的定义说明:(1)类型与变量是不同的概念。只能对变量赋值、存取或运算,而不能对一个类型赋值、存取或运算。编译时,对类型不分配存储空间,只对变量分配存储空间。结构体变量占用存储空间的大小为结构体内各成员占用存储单元的总和。(2)成员也可以是一个结构体变量,如【例9-2】中的birthday。9.1.3结构体变量的初始化像其他简单变量和数组一样,结构体类型的变量也可以在变量定义时进行初始化,也就是在定义变量的同时给变量的成员赋值。1.对于结构体类型已经定义的结构体变量的初始化例如,在【例9-1】中已经定义了structstudent结构体类型,再定义其结构体变量stu1,并对它进行初始化。structstudent{ longnumber; charname[20]; charclass[20]; floatMath; floatEnglish;};structstudentstu1={1009,"Lilin","Tongxin1201",87,89};9.1.3结构体变量的初始化2.结构体类型定义、结构体变量定义和初始化同时完成structstudent{ longnumber; charname[20]; charclass[20]; floatMath; floatEnglish;}stu1={1009,"Lilin","Tongxin1201",87,89};说明:(1)所有的初始化数据都需要用{}括起来,初始化数据之间用逗号分隔,字符串数据用双引号括起来,初始化时需要按照成员的顺序、类型依次赋予初值。
9.1.3结构体变量的初始化(2)以下初始化过程是错误的:structstudent{ longnumber=1009; charname[20]="Lilin"; charclass[20]="Tongxin1201"; floatMath=87; floatEnglish=89;}stu1;也不允许直接对结构体变量赋一组常量:stu1={1009,"Lilin","Tongxin1201",87,89};(3)若结构体的成员中另有一个结构体类型的变量,则初始化时仍然要对各个基本成员赋初值。如【例9-2】中定义的结构体变量赋初值可写为:structstudentstu1={1009,"Lilin",9,25,1992,"Tongxin1201",87,89};9.1.4结构体变量成员的引用定义了结构体变量后,在程序中就可以引用该变量了。除了具有相同类型的结构体变量可以作为一个整体相互赋值以外,赋值、运算、输入、输出等都是通过结构体变量的成员来实现的。1.引用结构体变量中的成员引用结构体变量成员的一般形式为:结构体变量名.成员名其中的圆点为成员运算符,它的运算级别是最高的。例如:stu1.number、tea1.department[0]等。如果成员本身又是一个结构体类型的变量,则在访问该结构体变量的成员时,应采取逐级访问的方法。如要得到学生的出生日期,则可以这样引用:stu1.birthday.month、stu1.birthday.day、stu1.birthday.year9.1.4结构体变量成员的引用2.将结构体变量作为整体引用只有在两个结构体变量具有相同的结构体类型时,才可以将一个结构体变量作为一个整体赋值给另一个结构体变量。例如:structteachertea1={2135,"Wangqi","computer",3125.9,85664179};structteacherdean;dean=tea1;这样dean中各成员的值均与tea1成员的值相同。说明:对结构体变量成员的运算与该成员所对应的相同数据类型的变量的操作是一样的。例如,对的操作与对字符数组的操作是一样的,可以通过“strcpy(,“Lilin”);”将“Lilin”赋值给。9.1.4结构体变量成员的引用(2)不能将一个结构体变量作为一个整体进行输入/输出,只能对变量的成员进行输入/输出。例如,对于一个结构体变量:struct{ charname[20]; charadd[30]; longzip;}stu={"Zhangming","79JiefangRoad",300026};以下输出是错误的:printf("%s\n",stu);printf("%s,%s,%ld\n",stu);只能对变量的成员进行输入/输出,如:scanf(%s%s%ld",,stu.add,&stu.zip);printf(%s,%s,%ld\n",,stu.add,stu.zip);或者也可以用gets函数和puts函数输入和输出一个结构体变量中的字符数组成员。例如:gets();puts();【例9
-3】下面的程序定义了工资信息和人员基本信息两个结构体,阅读程序,了解结构体成员的使用方法。#include<stdio.h>#include<conio.h>structsalary /*定义工资信息结构体类型描述工资信息*/{ floatbase; /*基础工资*/ floatallowances; /*津贴*/ floattaxes; /*税金*/};structworker /*定义人员基本信息结构体类型描述人员基本信息*/{ longnum; /*编号*/ charname[12]; /*姓名*/ structsalarysal; /*工资*/};voidmain(){ structworkerwk1={120101,"Liyue",2780.5,1356.5,124.11}; structworkerwk2; wk2=wk1; [0]='M'; [1]='a'; wk2.num=120102; wk2.sal.allowances=2168.5; wk2.sal.taxes=(wk2.sal.base+wk2.sal.allowances)*0.03; printf("编号\t\t姓名\t基础工资\t津贴\t\t税金\n"); printf("%ld\t\t%s\t%.2f\t\t%.2f\t\t%.2f\n",wk1.num,, wk1.sal.base,wk1.sal.allowances,wk1.sal.taxes); printf("%ld\t\t%s\t%.2f\t\t%.2f\t\t%.2f\n",wk2.num,, wk2.sal.base,wk2.sal.allowances,wk2.sal.taxes);}§9.2结构体数组9.2.1结构体数组的定义9.2.2结构体数组成员的初始化和引用9.2.1结构体数组的定义定义结构体数组与定义结构体变量的方法相同,可以采用以下3种定义中的任意一种。1.先定义结构体类型,再定义结构体数组struct结构体名{
成员说明表列};struct结构体名
数组名[数组大小];例如,定义一个数组psn,数组有5个元素,均为structperson类型变量,可以写为:structperson{ charname[20]; charadd[30]; longzip;};structpersonpsn[5];
9.2.1结构体数组的定义2.在定义结构体类型的同时定义结构体数组
struct结构体名{
成员说明表列}数组名[数组大小];例如,上面的例子也可以写为:structperson{ charname[20]; charadd[30]; longzip;}psn[5];
9.2.1结构体数组的定义3.不出现结构体名,直接定义结构体数组struct{
成员说明表列}数组名[数组大小];例如,上面的例子也可以写为:struct{ charname[20]; charadd[30]; longzip;}psn[5];9.2.2结构体数组成员的初始化和引用1.结构体数组成员的初始化结构体数组成员初始化的形式与多维数组的初始化形式类似,例如:structpersonpsn[10]={{“Yangxiao”,“101RenminRoad”,046001},{“Zhaojun”,“25JiansheRoad”,036002},{"Qianyu","56NanjingRoad",046004}};
这里只对结构体数组元素psn[0]、psn[1]、psn[2]的成员赋予了初值,psn[3]~psn[9]的各成员的值仍是不确定的。对结构体数组初始化的其他规则与一般数组相同。9.2.2结构体数组成员的初始化和引用2.结构体数组成员的引用结构体数组成员的引用完全类似于结构体变量的引用,只是用结构体数组元素来代替结构体变量,其他规则不变,一般的引用形式为:数组名[下标].成员名对于上面定义的数组psn,下列的引用均是正确的:psn[0].name;表示第一个人的姓名(字符串的首地址)。psn[0].zip;表示第一个人的邮政编码。psn[3]=psn[1];将结构体数组元素作为一个整体来使用。说明:同结构体变量一样,结构体数组元素不能作为一个整体进行输入/输出,只能以单个成员为对象进行输入/输出,因为每一个结构体数组元素都是一个结构体变量。【例9-4】计算每门课程期末考试的平均成绩。假设共有5名学生,学生的信息包括姓名、数学成绩、英语成绩和计算机成绩。分析:由于5名学生包括相同类型的多项信息,需要定义结构体类型的数组。计算数学成绩的总和,只需要对数组的math成员求累加和,然后求出均值;英语和计算机课程的均分计算方法同数学。#include<stdio.h>#defineN5structstudent /*定义结构体类型描述学生信息*/{ charname[12]; floatmath; floatenglish; floatcomputer;};voidmain(){ inti=0; floatsum1=0,sum2=0,sum3=0; floatave1=0,ave2=0,ave3=0; /*定义并初始化结构体数组*/ structstudentstu[N]={{“Sunli”,78,80,82},{“Weijuan”,82,84,89},{“Liuzhe”,69,90,93},{“Zhaoxing”,87,76,87},{"Dengjun",88,79,84}}; printf("Outputinformationofstudent:\n"); for(i=0;i<N;i++) /*结构体数组成员的输出*/ printf(“%-15s%7.2f%7.2f%7.2f\n”,stu[i].name,stu[i].math,stu[i].english,stu[i].computer); /*引用结构体数组成员计算总成绩和平均成绩*/ for(i=0;i<N;i++) { sum1=sum1+stu[i].math; sum2=sum2+stu[i].english; sum3=sum3+stu[i].computer; } ave1=sum1/N; ave2=sum2/N; ave3=sum3/N; printf(“AverageofMath:%7.2f,AverageofEnglish:%7.2f,AverageofComputer:%7.2f\n",ave1,ave2,ave3);}§9.3结构体指针9.3.1结构体指针变量的定义9.3.2用结构体指针访问结构体变量及结构体数组9.3.1结构体指针变量的定义结构体指针变量定义的一般形式为:struct结构体名*结构体指针变量名;例如:structstudent{ longnumber; charname[20]; charsex;};structstudentstu;structstudent*p=&stu;可以通过结构体指针变量访问结构体变量的成员,访问方式为:(1)(*结构体指针变量名).成员名其中“*结构体指针变量名”为所指向的结构体变量,“.”的运算符优先级比“*”高,所以圆括号不能少。例如,(*p).number表示指针变量p指向结构体变量stu的number成员。(2)结构体指针变量名->成员名(“->”是指向成员运算符)例如,p->number表示指针变量p指向结构体变量stu的number成员。9.3.2用结构体指针访问结构体变量及结构体数组指向结构体对象的指针变量既可以指向结构体变量,也可以指向结构体数组中的元素。指针变量的基类型必须与结构体变量的类型相同。指向数组元素和指向变量的结构体指针变量在使用上完全相同。【例9-5】分析程序,熟悉用结构体指针访问结构体变量和结构体数组元素的方法。include<stdio.h>voidmain(){ structstudent/*定义结构体类型*/ { longnum; charname[20]; charsex; floatscore; }; inti; /*定义结构体变量和结构体数组,并初始化*/ structstudentstu1={120010,"Malin",'M',90.5}; structstudentstu[3]={{120011,"Zhaofei",'M',87.0}, {120012,"Lixia",'F',79.0}, {120013,"Songyu",'F',83.5}}; structstudent*p,*q; /*定义指向结构体类型的指针变量*/ p=&stu1; /*p指向结构体变量*/ printf("No.:%ld\nname:%s\nsex:%c\nscore:%5.1f\n", stu1.num,(*p).name,stu1.sex,p->score);/*访问结构体变量*/ q=stu; /*q指向结构体数组的元素*/ for(i=0;i<3;i++) /*循环访问结构体数组的元素*/ { printf("\nNo.:%ld\nname:%s\nsex:%c\nscore:%5.1f\n", (*q).num,q->name,(*q).sex,q->score); q++; }}§9.4结构体变量与函数9.4.1结构体变量作为函数的参数9.4.2函数的返回值类型为结构体9.4.1结构体变量作为函数的参数结构体变量、结构体指针变量都可以像其他数据类型一样作为函数的参数,也可以将函数定义为结构体类型或结构体指针类型(返回值为结构体、结构体指针类型)。【例9-6】某单位清点库存商品,假设目前存有4种,从键盘输入商品名、库存数量、商品单价,请编写程序计算每种商品的总价,以及所有商品的总金额,并输出库存清单(包括商品名、数量、单价、合计)。分析:(1)商品信息可用结构体来表示。structStoreLib{ charname[12]; intnum; floatprice; floatSumMoney;};(2)使用函数voidlist(structStoreLibGoods)输出库存信息。#include<stdio.h>#include<conio.h>#include<stdlib.h>structStoreLib/*定义结构体类型描述商品信息*/{ charname[12]; intnum; floatprice; floatSumMoney;};/*函数声明,用来计算库存商品的总价并输出所有信息,参数为结构体变量*/voidlist(structStoreLibGoods);voidmain(){ structStoreLibiGoods[4]; inti; floatTotal=0; printf("请输入4种库存商品信息:商品名
数量
单价\n"); for(i=0;i<4;i++) { scanf("%s",iGoods[i].name); /*输入商品名*/ scanf("%d%f",&iGoods[i].num,&iGoods[i].price);/*输入数量和单价*/ Total=Total+iGoods[i].num*iGoods[i].price; } printf("\n----------------------------------------------\n"); printf("库存清单:\n"); printf("商品名\t\t\t数量\t单价\t合计\n"); for(i=0;i<4;i++) list(iGoods[i]); /*函数调用,输出库存清单*/ printf("库存商品金额总计:%.2f\n",Total);}/*函数定义,用来计算库存商品的总价并输出所有信息,参数为结构体变量*/voidlist(structStoreLibGoods){ Goods.SumMoney=Goods.num*Goods.price; printf(“%-24s%d\t%.2f\t%.2f\n”,G,Goods.num,Goods.price,Goods.SumMoney);}9.4.2函数的返回值类型为结构体函数的返回值除了可以是整型、实型、字符型和指向这些数据类型的指针等,还可以返回结构体类型的值。【例9-7】修改【例9-6】所示的程序,将“输入库存商品信息”功能改写为一个函数,其返回值为结构体类型。分析:因为每次输入的数据都是结构体变量的各成员值,因此可以设计函数:structStoreLibInputInfo();用于将商品信息输入到结构体数组Goods中。#include<stdio.h>#include<conio.h>#include<stdlib.h>structStoreLib /*定义结构体类型描述商品信息*/{ charname[12]; intnum; floatprice; floatSumMoney;};structStoreLibInputInfo();/*函数声明,用来输入库存商品信息,函数的返回值为结构体变量*/voidlist(structStoreLibGoods);/*函数声明,用来计算库存商品的总价并输出所有信息,参数为结构体变量*/floatTotal=0;voidmain(){ structStoreLibiGoods[4];
inti; printf("请输入4种库存商品信息:商品名
数量
单价\n"); for(i=0;i<4;i++) iGoods[i]=InputInfo(); /*函数调用,输入商品信息*/ printf("\n----------------------------------------------\n"); printf("库存清单:\n"); printf("商品名\t\t\t数量\t单价\t合计\n"); for(i=0;i<4;i++) list(iGoods[i]); /*函数调用,输出库存清单*/ printf("库存商品金额总计:%.2f\n",Total);}/*函数定义,将输入的商品信息保存到结构体数组Goods中*/structStoreLibInputInfo(){ structStoreLibGoods; scanf("%s",G); /*输入商品名*/ scanf("%d%f",&Goods.num,&Goods.price);/*输入数量和单价*/ Total=Total+Goods.num*Goods.price; returnGoods;}/*函数定义,输出Goods中的商品信息清单*/voidlist(structStoreLibGoods){ Goods.SumMoney=Goods.num*Goods.price; printf(“%-24s%d\t%.2f\t%.2f\n”,G,Goods.num,Goods.price,Goods.SumMoney);}§9.5联合体联合体又称为共用体,是将不同类型的数据项存放于同一段内存单元的一种构造数据类型。与结构体类似,在联合体内可以定义多种不同数据类型的成员。但是联合体变量与结构体变量不同,结构体变量所占用的内存是各成员所占用内存的长度之和,每个成员分别占有自己的内存单元;而在一个联合体变量中,所有的成员共用同一块内存单元,因此虽然每一个联合体变量成员均可以被赋值,但只有最后一次赋的值能够保存下来,而先前成员的赋值都被最后的赋值覆盖了。§9.5联合体9.5.1联合体类型的定义和说明9.5.2联合体变量的定义9.5.3联合体变量成员的引用9.5.1联合体类型的定义和说明联合体类型定义的一般形式为:
union联合体名{
成员说明表列};union是关键字,是定义联合体类型必不可少的标识符;联合体名是用户定义的标识符。{}中的内容为联合体成员的类型说明,与结构体类型的成员说明相同。例如:uniondata{ doublev; intn; charc;};
说明:(1)联合体的成员可以是任何类型,包括联合体类型和结构体类型。(2)定义联合体类型后,系统并不分配存储空间。9.5.2联合体变量的定义与结构体变量的定义相似,联合体变量的定义也有3种方式。1.先定义联合体类型,再定义联合体变量union联合体名{成员说明表列};union联合体名联合体变量列表;
例如:uniondata{ doublev; intn; charc;};uniondatanum1,*p,array[5];9.5.2联合体变量的定义2.在定义联合体类型的同时定义联合体变量union联合体名{
成员说明表列}联合体变量列表;例如:uniondata{ doublev; intn; charc;}num1,*p,array[5];9.5.2联合体变量的定义3.不出现联合体名,直接定义联合体变量union{成员说明表列}联合体变量列表;例如:union{ doublev; intn; charc;}num1,*p,array[5];
说明:(1)第3种方法定义的联合体类型不能再用来定义另外的联合体变量。(2)联合体变量所占存储空间等于占据内存最长的成员的长度。9.5.3联合体变量成员的引用联合体变量成员的引用方法与结构体变量成员的引用方法类似:
联合体变量名.成员名
由于联合体变量不同时具有每个成员的值,因此,最后一个赋予它的值就是联合体变量的值。另外,C语言允许同类型的联合体变量之间相互赋值。【例9-8】阅读程序,了解联合体变量成员的引用方法。#include<stdio.h>uniondata{ doublev; intn; charc;};voidmain(){ uniondatanum,fig; num.n=21; num.c='u'; num.v=25.4; printf("联合体变量num成员的值为:\n"); printf("num.v=%6.2lf\nnum.n=%4d\nnum.c=%c\n",num.v,num.n,num.c); num.n=68; fig=num; printf("联合体变量fig的值为:\n"); printf("figis%d\n",fig.n);
}9.5.3联合体变量成员的引用说明:(1)联合体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员就失去作用了。所以【例9-8】中,在num.v赋值之后,num.n、num.c所在的内存单元被覆盖,因而num.n、num.c的值不能确定。(2)相同类型的联合体变量之间可以作为一个整体来赋值,但应注意由于联合体变量共用一段内存的关系,赋值的操作其实仅发生于具有相同类型的联合体变量的成员之间。同时应注意不能对联合体变量名赋值,也不能直接输入/输出联合体变量。如下面的语句是错误的:fig=1;scanf("%f",&fig);printf("%f",fig);9.5.3联合体变量成员的引用(3)因为在每一瞬时联合体变量的存储单元中只能存放一个成员的值,所以可以对联合体变量初始化,但初始化列表中只能有一个常量。例如:uniondata{ doublev; intn; charc;}a={17.8,90,'w'};
是错误的。uniondataa={17.8};uniondataa={.c='w'};是正确的。(4)联合体变量的地址和它的各成员的地址都是同一地址。例如,&num.v、&num.n、&num.c都是同一个值。§9.6枚举类型9.6.1枚举类型的定义9.6.2枚举变量的定义9.6.3枚举变量的使用9.6.1枚举类型的定义在实际问题中,有些变量只有几种可能的取值。例如,一个星期只有7天,取值只可能是星期一至星期日;一年只有12个月,取值只可能是一月至十二月;人的性别只有两种,取值只可能是男或女。在C语言中,这样的变量可以定义为枚举类型。所谓“枚举”就是指把所有可能的值一
一列举出来,变量的值不能超出列举的范围。枚举类型定义的一般形式为:enum枚举名{取值列表};
例如,enumweekday{sun,mon,tue,wed,thu,fri,sat};其中enum是必不可少的关键词;weekday是枚举名,是用户定义的枚举类型标识符;取值列表为所有可能的取值,是常量;sun、mon、tue、wed、thu、fri、sat即一周中的7天;各常量之间用逗号分隔,使用时不要在常量的两端加单引号或双引号。9.6.2枚举变量的定义只有在定义了枚举类型后,才可以定义枚举变量。如同结构体和联合体一样,枚举变量也可以用3种不同的方式说明。1.先定义枚举类型再定义枚举变量enum枚举名{取值列表};enum枚举名变量名列表;例如:enumweekday{sun,mon,tue,wed,thu,fri,sat};enumweekdaya,b,c;2.在定义枚举类型的同时定义枚举变量enum枚举名{取值列表}变量名列表;例如:enumweekday{sun,mon,tue,wed,thu,fri,sat}a,b,c;3.不出现枚举名直接定义枚举变量enum{取值列表}变量名列表;例如:enum{sun,mon,tue,wed,thu,fri,sat}a,b,c;9.6.3枚举变量的使用枚举常量实际上就是一些整型数的名字,使用枚举常量比直接使用整型数容易理解,同时可以迫使编译时对定义的类型加以检查,以提高程序的可靠性。使用枚举变量时需要注意以下一些问题:(1)枚举值是常量,不是变量,不能在程序中用赋值语句再对它赋值。例如,对枚举类型weekday的元素再做以下赋值:sun=7;mon=3;sun=mon;都是错误的。(2)只能把枚举常量赋予枚举变量,不能把枚举值的序号数值赋予枚举变量。例如:a=sun;b=mon;是正确的,而a=0;b=1;是错误的。(3)各枚举常量对应一个表示序号的整型数值,用户若不指定则由系统定义,数值从0开始,顺序定义为0,1,2,…。例如,在weekday中,默认sun值为0,mon值为1,……,sat值为6。9.6.3枚举变量的使用(4)枚举值的序号数值也可以在定义时由用户指定。例如:enumweekday{sun,mon,tue=4,wed,thu,fri,sat}a;对于没有指定数值的枚举值,其数值从已定义的数值开始依次加1。所以sun=0,mon=1,tru=4,wed=5,fri=6,sat=7。(5)用printf函数输出枚举变量时,只能输出其所对应的枚举常量的序号数值。例如:#include<stdio.h>voidmain(){ enumweekday{sun,mon,tue,wed,thu,fri,sat}workday,restday; workday=mon; restday=sun; printf("workday=%d,restday=%d\n",workday,restday);}程序运行的结果为:workday=1,restday=0如果要输出枚举变量的值可以将上述程序中的输出部分改为:if(workday==mon) printf("%s\n","mon");【例9-9】从键盘输入一个1~7的整数,在屏幕上显示与该整数对应的星期的英文名称。分析:在输出较多的枚举变量时,可以用switch结构语句。#include<stdio.h>voidmain(){ enumweekday{sun=7,mon=1,tue,wed,thu,fri,sat}day; intk; printf("Pleaseinputanumber(1~7):"); scanf("%d",&k); day=(enumweekday)k; switch(day) { casesun:printf("TodayisSunday.\n");break; casemon:printf("TodayisMonday.\n");break; casetue:printf("TodayisTuesday.\n");break; casewed:printf("TodayisWednesday.\n");break; casethu:printf("TodayisThursday.\n");break; casefri:printf("TodayisFriday.\n");break; casesat:printf("TodayisSaturday.\n");break; default:printf("Inputiserror!\n"); }}§9.7用户自定义类型——typedef9.7.1为基本数据类型定义新的类型名9.7.2为复杂的数据类型定义简单的类型名9.7.1为基本数据类型定义新的类型名C语言提供了许多标准的类型名(如int、char、float、double和long等)和程序设计者自己声明的结构体、联合体、枚举类型,用户可以直接使用这些类型来定义所需要的变量。同时C语言还允许使用typedef语句定义一种新的类型名来代替已有的类型名,定义新的类型名之后,可像标准数据类型那样用新的类型名定义变量。typedef定义的一般形式为:typedef原类型名新类型名;其中,原类型名中含有定义部分,新类型名的第一个字母一般用大写表示,以便与系统提供的标准类型的标识符相区别。例如:typedefintInteger;typedefunsignedintUINT;指定用Integer代表int类型,UNIT代表unsignedint。这样,就可以用Integer和UNIT来定义变量了,例如:Integeri,j;与inti,j;是等价的。unsignedinta,b;与UNITa,b;是等价的。9.7.2为复杂的数据类型定义简单的类型名1.为结构体类型定义一个新的类型名,例如:typedefstruct{ doublex; doubley; doublez;}Point;
声明了一个新类型名Point,代表上面一个结构体类型。然后就可以用新的类型名Point去定义变量了,如:Pointopoint1;定义了一个结构体类型的变量,不要写成structPointopoint1。Point*p;定义了结构体指针变量p,指向此结构体类型的变量。9.7.2为复杂的数据类型定义简单的类型名2.为数组类型定义一个新的类型名,例如:typedefintArray[10];Arraya;声明Array为整型数组类型名,用Array定义a为整型数组名,它有10个元素。声明的方法为:(1)先按定义数组变量的形式书写:inta[10];(2)将变量名a换成用户自定义的新类型名:intArray[10];(3)在前面加上typedef,得到typedefintArray[10];(4)用新类型名定义变量:Arraya;与inta[10];等价。9.7.2为复杂的数据类型定义简单的类型名3.为指针类型定义一个新的类型名,例如:typedefchar*String;Stringp,s[10];声明String为字符型指针类型,定义p为字符型指针变量,s为字符指针数组。声明的方法为:(1)定义指针变量p:char*p;(2)用新类型名String取代变量p:char*String;(3)在前面加上typedef,得到typedefchar*String;(4)用新类型名定义变量:Stringp;与char*p;等价。9.7.2为复杂的数据类型定义简单的类型名在使用typedef定义新类型时,应当注意以下几个问题:(1)typedef只是对已经存在的类型指定了一个新的名称,并没有引入新的数据类型。(2)typedef只适于类型名的定义,不适于变量的定义。(3)typedef与#define具有相似之处,但其实质不同。例如,#defineINTEGERint与typedefintINTEGER可以达到相同的效果,但是#define为预编译处理指令,主要用来定义常量,此常量可以为任何的字符或其组合,在编译之前此常量出现的所有位置,用其代表的字符或字符组合会被无条件替换;typedef是为已知数据类型增加一个新的名称,是在编译时处理的,它并不是进行简单的字符串替换,而是用新类型名去定义变量。另外,#define是预处理命令,不能在末尾加分号;而typedef是类型声明语句,以分号结束。§9.8程序举例【例9-10】输入5个同学的姓名、数学成绩、英语成绩和计算机成绩,确定总分最高的同学,并打印其姓名及其3门课程的成绩。分析:(1)使用长度为5的structstudent类型的结构体数组存储所有同学的相关信息。(2)定义structstudent类型指针pmax存储总分最高的同学的地址。(3)定义structstudent类型指针pstu引用结构体数组中的元素及其数组元素成员的值。(4)通过循环语句为每个数组元素成员赋值。(5)利用pmax输出成绩最高的同学的相关信息。#include<stdio.h>#include<string.h>structstudent /*定义结构体类型*/{ charname[20]; intmath; intenglish; intcomputer;};voidmain(){ structstudentstu[5];/*定义structstudent类型的结构体数组存储所有同学的相关信息*/ structstudent*pmaxstu;/*定义structstudent类型指针存储总分最高的同学的地址*/ structstudent*pstudent; /*定义structstudent类型指针来引用数组*/ intfmaxscore=0,ftotal; /*存储最高分和总分的中间变量*/ intfmath,fenglish,fcomputer; /*存储各科成绩的中间变量*/ charszname[20]; printf("\nPleaseinput5studentsandscore\n"); printf("Name\tMath\tEnglish\tComputer\n"); pmaxstu=stu; /*给pmaxstu指针变量赋初值*/ /*将数组stu的地址赋给pstudent指针变量,通过pstudent为数组stu各元素赋值*/ for(pstudent=stu;pstudent<stu+5;pstudent++) { /*键盘输入当前同学的相关信息*/ scanf("%s%d%d%d",szname,&fmath,&fenglish,&fcomputer); /*将中间变量的值通过结构体指针引用,赋值到对应数组元素的各个成员中*/ strcpy(pstudent->name,szname); pstudent->math=fmath; pstudent->english=fenglish; pstudent->computer=fcomputer; ftotal=pstudent->math+pstudent->english+pstudent->computer; /*获得当前最高分同学所对应数组元素的地址*/ if(fmaxscore<ftotal) { fmaxscore=ftotal; pmaxstu=pstudent;/*将最高分同学所对应的首地址赋值给最高分指针变量*/ } } printf("themaximumis:"); printf("%s,%d,%d,%d\n",pmaxstu->name,pmaxstu->math,pmaxstu->english,pmaxstu->computer);}§9.8程序举例【例9-11】商品进出库管理,入库商品的数据包括编号、商品名、数量、状态(入库)、货架号,出库商品的数据包括编号、商品名、数量、状态(出库)、部门。用同一个表格实现这个管理,如表9-2所示。编写程序输入和输出这些数据。分析:(1)可以为进出库商品定义一个结构体类型,结构体类型包括5个成员,分别是编号、商品名、数量、状态、货架号或部门;表格中只有“货架号或部门”这个栏目的数据类型不同,如果记录的是入库商品,这一栏填写货架号(长整型数据),否则填写领取部门的名称(字符串数据),其他类型均相同,可以将“货架号或部门”这一成员定义为联合体类型。(2)定义结构体数组,保存键盘输入的数据。(3)输出结构体数组保存的数据。#include<stdlib.h> /
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年3年级上册5单元语文试卷及答案
- 2026年18年北京安全员c证考试题及答案
- 2026年214周模拟考试题答案
- 2026年16g101试题及标准答案
- 2026年23年文职考试题答案
- 2026年1995年AMC8试题答案
- 2026年4399校招运营笔试题目及答案
- 2026年20规则三管题库答案
- 2026年1月学考语文试卷及答案
- 2026年ai意面面试题库及答案
- 2026年山东济南市高三二模高考化学试卷试题(含答案详解)
- 2025年新版烟草在线测试题及答案2
- 2026广东佛山市公安局三水分局警务辅助人员招聘49人(第一批)考试参考试题及答案解析
- 国家义务教育质量监测小学四年级科学核心素养国测模拟测试题(附答案)
- 2023休克患者的麻醉管理
- 有限空间作业事故安全施救指南解读培训
- 导气石笼井施工技术交底
- 2026年时事政治测试题库100道附答案【满分必刷】
- 中医护理质量管理工作手册
- 毕业设计说明书 邯郸市陵园路(光明大街滏河大街段)交通设计
- 虫害控制记录表
评论
0/150
提交评论