C语言程序设计 课件 第9章 结构体类型及其他构造类型_第1页
C语言程序设计 课件 第9章 结构体类型及其他构造类型_第2页
C语言程序设计 课件 第9章 结构体类型及其他构造类型_第3页
C语言程序设计 课件 第9章 结构体类型及其他构造类型_第4页
C语言程序设计 课件 第9章 结构体类型及其他构造类型_第5页
已阅读5页,还剩31页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C语言程序设计结构体类型及其他构造类型第9章学习目标掌握结构体数组与结构体指针的简单应用2掌握结构体类型及结构体变量定义1掌握共同体类型及共用体变量的应用4掌握用typedef声明新类型名5了解指针处理链表的方法3了解枚举型数据的处理69.1结构体类型C语言中给出了另一种新的构造数据类型:由一系列具有相同类型或不同类型的数据构成的数据集合,称为结构体类型(struct)。结构体是这些元素的集合,这些元素称为结构体的成员(member)。访问结构体的成员是通过成员的名字。结构体类型的定义可以说明该结构体类型的组成及每个成员的数据类型,其定义的一般形式如下:struct结构体类型名{数据类型

成员名1;数据类型

成员名2;…数据类型

成员名n;}structstaff_info//结构体类型名{charname[20];//姓名为字符数组intnum;//员工编号intage;//年龄charsex;//性别floatsale//销售额};//此处的分号不能省略9.1结构体类型(1)结构体类型的定义以struct关键字开头,后面的结构体类型名是用户自定义的标识符,其命名需要符合标识符命名规则。(2)花括号{}中称为结构体类型的“成员”,成员的定义与变量相同。成员的数据类型可以是基本数据类型、数组、指针或已定义过的结构体类型等。(3)结构体类型中的成员名,可以与程序中的变量同名,但它们代表的是不同的对象,互不影响。(4)结构体类型的定义可以在一个函数的内部,也可以在所有函数的外部。在函数内部定义的结构体类型,仅在该函数内部有效;而在所有函数的外部定义的结构体类型,在所有函数中都可以使用。(5)如果结构体类型名省略,则此时定义的结构体类型称为无名结构体类型。(6)整个结构体定义以分号结束。structdate//声明结构体类型date{intyear,month,day;};structstaff_info//声明结构体类型staff_info{charname[20];intnum;intage;charsex;floatsale;structdatebirthday;}staff1,staff2;9.1结构体类型1.结构体变量的定义结构体类型的定义只是描述结构体类型数据的组织形式,它规定了这个结构体类型使用内存的模式,并没有分配一段内存单元来存放各数据项成员。只有定义了基于此类型的结构体变量,系统才会为变量分配内存空间。定义结构体变量的方法有以下几种形式:(2)在定义结构体类型的同时,可以定义结构体变量。这些结构体变量可以直接在结构体类型定义的大括号后、分号前给出。其定义的一般形式为struct结构体类型名{成员表列;}变量1,…,变量n;例如:structdate{intyear,month,day;}today;(3)不定义结构体类型名,直接定义结构体变量,其定义的一般形式为struct{成员表列;}变量1,…,变量n;这种方式是直接定义若干结构体变量,由于省略了结构体类型名,因此不能用它再定义其他的变量。结构体变量被定义之后,系统为其分配存储单元,结构体变量的成员在内存中占用连续的存储区域,所占内存大小为结构体中每个成员的长度之和。一个结构体变量占用内存的实际大小,可以使用sizeof运算求出。(1)先定义结构体类型,再定义结构体变量。我们先定义了结构体类型staff_info,然后用它定义结构体变量,其一般形式为:struct结构体类型名

变量1,…,变量n例如:structstaff_infostaff1,staff2;9.1结构体类型2.结构体变量的初始化和其他类型变量一样,结构体变量也可以在定义时进行初始化赋值。其初始化的格式与一维数组的初始化相似,附在变量后面的一组数据须用花括号括起来,其顺序应与结构体中的成员顺序保持一致。不同的是,如果结构体变量的某个成员本身又是结构体类型,则该成员的初值为一个初值表。结构体变量初始化的一般形式如下:struct结构体类型名

结构体变量={初始化数据};(1)例如,前面给出的date类型的today变量,可初始化为structdatetoday={2024,5,5};(2)例如,前面给出的staff_info类型的staff1变量,可初始化为structstaff_infostaff1={"wanggang",10234,23,'M',754.5,{1997,4,8}};9.1结构体类型3.结构体变量的引用在程序中使用结构体变量时,可以对其整体操作,但是更频繁的是对结构体变量的各个成员进行各种运算和操作,例如,赋值、输入、输出、运算等。在程序中引用结构体变量成员的一般形式如下:结构体变量名.成员名其中,“.”为成员运算符,它的优先级在C语言中是最高的,其结合性为自左至右。例如:staff1.num//即结构体变量staff1的员工编号num。9.1结构体类型(1)对结构体变量进行输入/输出时,只能以成员引用的方式进行,不能对结构体变量进行整体的输入/输出。C语言不允许用赋值语句将一组常量直接赋值给一个结构体变量。下面的赋值语句是不合法的:staff2={"小明",100,'F',{1989,1,1}};而通过结构体变量的初始化赋值是合法的:structstaff_infostaff2={"小明",100,'F',{1989,1,1}};(2)如果结构体变量的成员本身又是一个结构体类型的数据,那么必须逐级找到最低级的成员才能使用。如:staff1.birthday.year=1997;(3)结构体变量的成员,可以进行何种运算是由定义的类型决定的。关于结构体变量的几点说明。(4)可以将一个结构体变量作为一个整体赋给另一个具有相同类型的结构体变量。例如:staff2=staff1;(5)可以把一个结构体变量中的内嵌结构体类型成员赋给另一个结构体变量的相应部分。9.1结构体类型【例9-1】

编写程序完成以下目标:(1)输入今天的日期、然后输出该日期。(2)自定义结构体类型,完成员工staff1的信息并从键盘输入,staff2的信息直接赋值,并输出结果。(3)对员工的销售业绩求和并输出。#include<stdio.h>structdate{ intyear,month,day;}today;structstaff_info{ charname[20]; intsale; charsex; structdatebirthday;}staff1,staff2={"小明",100,'F',{1989,1,1}};voidmain(){ scanf("%d%d%d",&today.year,&today.month,&today.day); scanf("%s%d%c%d%d%d",,&staff1.sale,&staff1.sex, &staff1.birthday.year,&staff1.birthday.month,&staff1.birthday.day); printf("Today:%d-%d-%d\n",today.year,today.month,today.day); printf("%s,%d,%c,%d-%d-%d\n",,staff1.sale,staff1.sex, staff1.birthday.year,staff1.birthday.month,staff1.birthday.day); printf("%s,%d,%c,%d-%d-%d\n",,staff2.sale,staff2.sex, staff2.birthday.year,staff2.birthday.month,staff2.birthday.day); printf("总销售业绩:%d\n",staff1.sale+staff2.sale);}

成员

结构体变量namesalesexbirthdaystaff1小王200M1999-5-5staff2小明100F1989-1-19.2结构体数组直接定义一个结构体数组structstudent{ charname[10]; longnum; intage; floatscore;}structstudentstu[5];或struct//省略结构体类型名{ charname[10]; longnum; intage; floatscore;}structstudentstu[5];先定义结构体类型,再定义结构体数组structstudent{charname[10];longnum;intage;floatscore;};structstudentstu[5];//定义了一个有五个元素的数组stu,类型为structstudent结构体数组定义的一般形式为:struct

结构体类型名

结构体数组名[整型常量表达式];9.2结构体数组在定义结构体类型和定义结构体数组的同时,进行初始化structstudent{ charname[10]; longnum; intage; floatscore;}stu[]={{“小王”,123001,19,95.5},{“小李”,123002,20,61}};在完全初始化的时候,数组长度可以省略。定义完结构体类型后,定义结构体数组时初始化structstudent{ charname[10]; longnum; intage; floatscore;};structstudentstu[2]={“小王”,123001,19,95.5};//只给stu[0]赋值对结构体数组可以作初始化赋值。结构体数组的一个元素相当于一个结构体变量,结构体数组初始化即顺序对数组元素初始化。9.2结构体数组【例9-2】编写程序:建立一个通讯录,包含姓名和电话号码。#include<stdio.h>structphonebook{ charname[20],phone[20];}people[2];voidmain(){ inti; for(i=0;i<2;i++) { gets(people[i].name); gets(people[i].phone); } for(i=0;i<2;i++) printf("姓名:%s,电话:%s\n",people[i].name,people[i].phone);}结构体数组元素的引用结构体类型数组也是通过数组名和下标来引用数组元素,结构体类型数组元素的引用与结构体类型变量的引用一样,也使用成员运算符“.”,逐级找到最低一级成员,对最低一级的成员进行赋值或运算。引用形式如下:数组名[下标].成员名可用如下形式来引用上面定义的数组stu的元素:stu[0].name=”小王”;stu[1].num=stu[2].num-1;stu[1].age=stu[0]+1;stu[0].score=95.5;scanf(“%f”,&stu[1].score);printf(“%f”,stu[1].score);9.3结构体指针指向结构体变量的指针使用结构体指针变量引用结构体的成员步骤如下:(1)定义结构体类型。(2)定义结构体类型变量,并完成结构体变量的初始化。例如:structstaff_infostaff2={“小明”,100,’F’,{1989,1,1}};(3)定义指向结构体的指针变量,通过使用“&”把结构体变量的地址赋给指针变量,使指针指向结构体变量。例如:structstaff_info*p;p=&staff1;或:structstaff_info*p=&staff1;(4)通过指针变量,引用结构体变量或者数组中的值。当指针变量指向结构体变量时,引用该结构体变量的成员有以下几种方式:①使用普通变量名引用,格式为:结构体变量名.成员名,例如:②使用指针变量名引用,格式有如下两种。方法1:(指针变量名).成员名,例如:(*p).name方法2:指针变量名->成员名,例如:p->name【例9-3】用结构体指针引用结构体成员。程序代码:#include<stdio.h>structperson{ charname[20]; doublehigh; floatweight;};voidmain(){ structpersonman={"lucy",1.6,65.5}; structperson*p=&man;//变量的首地址赋给指针p printf("%s\t%5.2f\t%5.2f\n",,man.high,man.weight); printf("%s\t%5.2f\t%5.2f\n",(*p).name,(*p).high,(*p).weight); printf("%s\t%5.2f\t%5.2f\n",p->name,p->high,p->weight);}(1)结构体成员运算符“.”的优先级比指针运算符“*”高,所以使用指针引用结构体变量时“(*指针变量名).成员名”中的圆括号不能省略。(2)“->”是成员选择运算符,指向结构体成员,等价于(*)形式。9.3结构体指针指向结构体数组的指针指针可以指向元素为结构体类型的数组,实际是用指针变量指向结构体数组的首个元素,即:将结构体数组的首元素的地址赋值给指针变量。【例9-4】用指针变量输出结构体数组#include<stdio.h>structperson{ charname[20]; doublehigh; floatweight;}man[2]={{"lucy",1.6,65.5},{"tom",1.8,81.5}};voidmain(){ structperson*p=man;//数组的首地址赋给指针p for(;p<man+2;p++) printf("%s\t%.2f\t%.2f\n",p->name,p->high,p->weight);}9.4在函数之间传递结构体向函数传递结构体变量的成员在函数之间传递结构体变量的成员实际上与在函数之间传递一个简单变量是相同的。在函数之间既可以传递结构体变量成员的值,也可以传递结构体变量中成员的地址。【例9-5】

输入个人信息,打印输入结果。#include<stdio.h>structperson{ charname[20]; intnum;}man;voidmain(){ gets();//传递成员字符串数组首地址 scanf("%d",&man.num);//传递成员num的地址 printf("%s\t",);//传递字符串name的地址 printf("%d\n",man.num);//传递成员num的值 printf("%c\n",[2]);//传递字符串数组下标2的值}9.4在函数之间传递结构体向函数传递整个结构体变量将结构体变量作为形参,通过函数间形参与实参结合的方式将整个结构体变量传递给函数,这种传递方式就是值传递。在被调用函数中,对结构体形参变量的值的任何修改,都不会

影响到调用函数中的结构体变量。将结构体作为函数参数时,结构体的类型必须完全匹配。【例9-6】结构体变量整体作为函数的参数。#include<stdio.h>structstu_score{ charname[20]; intmath; intchinese;};intstu_aver_score(structstu_scorem)//结构体变量作为形参{ intaver; aver=(m.chinese+m.math)/2; returnaver;}voidmain(){ structstu_scoreman; intaver; printf("请输入名字和两门课分数:\n"); scanf("%s%d%d",,&man.math,&man.chinese); aver=stu_aver_score(man);//结构体变量作为实参传递 printf("%s,%d,%d,平均分:%d\n",,man.math,man.chinese,aver);}9.4在函数之间传递结构体向函数传递结构体变量的地址结构体变量具有C语言中变量的全部特性,在函数调用方面也不例外。结构体变量、结构体指针变量以及结构体数组等均可作为函数的参数(形参或实参)。与其他数据类型的运用一样,结构体类型的形参和实参也需相互匹配。向函数传递结构体变量的地址要将函数的形参定义为指向结构体的指针,在调用时要用结构体变量的地址作为实参。【例9-7】结构体指针作为函数的形参及实参。程序代码:#include<stdio.h>structstu_score{ charname[20]; intmath; intchinese;};intstu_aver_score(structstu_score*p2){ intaver; aver=(p2->chinese+p2->math)/2; returnaver;}voidmain(){ structstu_scoreman,*p1; intaver; printf("请输入名字和两门课分数:\n"); scanf("%s%d%d",,&man.math,&man.chinese); p1=&man; aver=stu_aver_score(p1); printf("%s,%d,%d,平均分:%d\n",,man.math,man.chinese,aver);}9.5用指针处理链表链表是一种常见的重要的数据结构,它是动态地进行存储分配的一种结构。C语言规定不允许对数组的长度作动态定义,然而,在实际的编程中,往往会出现所需的内存空间无法预先确定的情况,内存空间取决于实际输入的数据。如用数组来存放班级学生数据时,班级的人数没有固定值,若用同一个数组先后存放不同班级的学生数据,则必须以人数最多班级来设定数组长度,以便能存放任何班级的学生数据,显然这将会浪费内存空间。链表没有这种缺点,它是动态进行存储分配的一种结构,可以根据需要开辟内存单元。链表有一个“头指针”,以head表示,它存放一个地址,该地址指向一个元素。链表中每一个元素称为“结点”,每个结点包括两个部分:(1)存放用户需要的实际数据,称为数据域。(2)存放下一个结点的地址,称为指针域。可以看出,head指向第1个结点,第1个结点又指向第2个结点……直到最后一个结点,该结点不再指向其他结点称为“表尾”,它的地址部分放一个“NULL”(表示“空地址”),链表到此结束。链表中各结点在内存中的地址可以是不连续的,要找到某一结点,必须先找到

上一个结点,根据它提供的下一结点地址才能找到下一个结点,如果不提供“头指针”(head),则整个链表都无法访问。链表如同一条铁链一样,一环扣一环,中间是不能断开的。链表这种数据结构,必须利用指针变量才能实现,即一个结点中应包含一个指针变量,用它存放下一结点的地址。

链表的结点可以用结构体类型描述,一个结构体变量包含若干成员,这些成员可以是数值类型、字符类型、数组类型,也可以是指针类型。用指针类型成员来存放下一个结点的地址。9.5用指针处理链表1、malloc函数malloc函数的功能是申请内存空间。其调用格式如下:malloc(size)可以使用malloc函数申请size字节大小的一块连续内存空间。如果函数调用成功,则返回该连续内存空间的首地址;如果申请空间失败,就说明没有足够的空间可供分配,则返回空指针NULL。malloc函数的返回值为void类型指针,在使用该函数时,需要将该返回值强制转换为所需的类型。申请一个动态的int型所需的连续内存空间,使用以下语句:int*p;p=(int*)malloc(sizeof(int));申请一个动态的链表节点所需的连续内存空间,可用以下语句:structstu{ longnum; charname[20]; structstu*next;};structstu*p;p=(structstu*)malloc(sizeof(structstu));2、free函数对于用函数malloc或calloc申请的空间,在使用结束后必须用free函数释放,所以free与malloc或calloc经常配对使用。函数free的调用格式如下:free(指针变量名)free函数的功能是释放“指针变量名”所指向的连续内存空间。释放之后,该连续内存空间才可以被其他变量所使用。例如:int*p;p=(int*)malloc(sizeof(int));free(p);操作链表时,需要动态地分配和释放节点。C语言提供了相应的函数,用于对内存空间的申请和释放。在使用这些函数时,需要使用#include命令将“malloc.h”或“stdlib.h”包含进来。9.5用指针处理链表【例9-8】建立一个单向静态链表,它由3个学生数据的结点组成,要求输出各结点中的数据。#include<stdio.h>structstu{ intnum; floatscore; structstu*next;};voidmain(){ structstux,y,z,*head,*p; x.num=123001;x.score=85.5; y.num=123002;y.score=95.5; z.num=123003;z.score=70; head=&x; x.next=&y; y.next=&z; z.next=NULL; p=head; do { printf("%d:%.2f\n",p->num,p->score); p=p->next;}while(p!=NULL);}【分析】声明一个结构体类型,其成员包括num(学号)、score(成绩)和next(指针变量)。将第1个结点x的起始地址赋给头指针head,将第2个结点y的起始地址赋给第1个结点x的next成员,将第3个结点z的起始地址赋给第2个结点y的next成员。第3个结点z的next成员赋予NULL,这样就形成了链表。输出链表的时候,使p指向x结点,然后输出x结点中的数据,“p=p->next”是为输出下一个结点作准备

。p->next的值是y结点中的地址,因此执行“p=p->nex”后p就指向y结点,所以在下一次循环的时候输出的是y结点中的数据。本例中所有的结点都在程序中定义的,不是临

时开辟的,也不能用完后释放,这种链表称为“静态链表”。建立简单的静态链表9.5用指针处理链表【例9-9】建立一个单向动态链表,它由3个学生数据的结点组成,学号为0表示输入结束,要求输出各结点中的数据。#include<stdio.h>#include<malloc.h>//动态内存分配声明,或用#include<stdlib.h>#defineLENsizeof(structstu)structstu{ longnum; floatscore; structstu*next;};intn;//全局变量n建立动态链表structstu*creat(){structstu*head;structstu*p,*q;n=0;p=q=(structstu*)malloc(LEN); scanf("%ld,%f",&p->num,&p->score); head=NULL;while(p->num!=0){n=n+1;if(n==1)head=p;elseq->next=p;q=p;p=(structstu*)malloc(LEN); scanf("%ld,%f",&p->num,&p->score);}q->next=NULL;return(head);}voidmain(){structstu*p1;p1=creat();if(creat!=NULL){do{printf("num:%ld\tscore:%.2f\n",p1->num,p1->score);p1=p1->next;}while(p1!=NULL);}}9.5用指针处理链表【例9-10】编写一个函数,在一个已有的单链表中插入一个结点。structstu*insert(structstu*head,structstu*s){ structstu*p,*q; if((head==NULL)||(s->num<head->num)) { s->next=head; head=s; } else { p=head; while(p!=NULL&&p->num<s-num) { q=p; p=p->next; } s->next=p; q->next=s; } returnhead;//函数返回插入后单链表第1结点地址}在单链表中插入结点9.6共用体结构体和共用体都属于构造类型,这两种类型的定义十分相似。共用体类型定义的一般形式为:union共用体类型名{

数据类型

成员名1;

数据类型

成员名2;……

数据类型

成员名n;};例如,可以定义如下的共用体:unionstu{ charname[20]; longnum;};表示定义了一个名为stu的共用体类型。说明:(1)共用体类型定义使用关键字union开头,不能省略。(2)花括号{}中是共用体类型的成员,与结构体不同的是,共用体的各个成员,是以同一个地址开始存放的,每一个时刻只可以存储一个成员,也就是说共用体类型实际占用存储空间为其最长的成员所占的存储空间。共用体类型定义9.6共用体共用体变量和结构体变量在定义上也很相似,也可分为三种方式。(1)先定义共用体类型,再定义共用体变量。例如:前面我们已经定义了名为stu的共用体类型,使用共用体定义变量s1,s2。unionstus1,s2;(2)定义共用体类型的同时定义共用体变量。例如:unionstu{ charname[20]; longnum;}s1,s2;(3)直接定义共用体类型变量。例如:union//省略类型名{ charname[20]; longnum;}s1,s2;【例9-11】测试共用体类型的长度。程序代码:#include<stdio.h>unionstu{ charname[20]; longnum;}s1,s2;voidmain(){ printf("%d\n",sizeof(unionstu));}共用体类型变量的定义9.6共用体(1)在定义共用体变量的同时,进行赋值。但不能对共用体变量初始化。#include<stdio.h>unionstu{ charname[20]; longnum;}s1,s2={"xiaoming"};//此处只能第1个成员赋值voidmain(){ printf("%s\n",);} 运行结果:xiaoming(2)定义完共用体类型变量后,对某个成员初始化。例如:#include<stdio.h>unionstu{ charname[20]; longnum;}s1,s2,*p;voidmain(){ unionstus2={"xiaoming"}; printf("%s\n",);}共用体变量初始化有两种形式9.6共用体对共用体中成员的引用同结构体完全一样。(1)如果要访问共用体变量中的成员,可使用“.”运算符,引用的一般形式为:共用体类型

变量名.成员名例如,对于已定义的共用体类型变量m,各成员引用方式为m.flag、m.num、m.score。各成员所占空间:flag占1字节;num占2字节;score占4字节。定义m之后,系统为m分配4字节的内存(即占内存空间最大的成员score所占的内存空间)。虽然这4字节的内存单元由成员flag、num、score共同使用,但是在某一时刻,只能由flag、num、score中的某一个成员占用。例如,顺序执行下面的语句之后:m.flag=’a’;m.num=12;m.score=90;这4字节中存储的是成员score的值。(2)如果使用指针访问共用体中的成员,可以使用“->”。例如: s1.num或(*p).num或p->num【例9-12】

共用体变量成员的引用方法示例。程序代码:#include<stdio.h>unionstu{ charname[20]; longnum;}s1,s2,*p;voidmain(){ unionstus2={"xiaoming"}; p=&s2; printf("%s\n",); printf("%s\n",(*p).name); printf("%s\n",p->name);}共用体成员的引用9.6共用体使用共用体类型数据时的几点说明:(1)同一内存段可以用来存放几种不同类型的成员,但在每一瞬时只能存放其中一种,而不是同时存放几种。也就是说,每一瞬时只有一个成员起作用,其他的成员不起作用,即不是同时都存在或起作用。(2)共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员就失去作用。(3)共用体变量的地址和它的各成员的地址都是同一地址。(4)不能对共用体变量名赋值,也不能企图引用变量名来得到成员的值,而且不能在定义共用体变量时对它初始化。(5)不能把共用体变量作为函数参数,也不能把一个函数的类型定义成共用体类型,但可以使用指向共用体变量的指针。(6)共用体与结构体可以互相嵌套。在共用体中可以定义结构体成员,也可以在结构体中定义共用体成员。【例9-13】

分析以下程序的运行结果。voidmain(){union{longx;shorty;charz;chars[4];}mix;mix.x=0x12345678;printf("mix.x=%lx\n",mix.x);printf("mix.y=%x\n",mix.y);printf("mix.z=%x\n",mix.z);printf("mix.s[0]=%x\t,mix.s[1]=%x\n",mix.s[0],mix.s[1]);printf("mix.s[2]=%x\t,mix.s[3]=%x\n",mix.s[2],mix.s[3]);printf("%d,%d,%d,%d,%d\n",sizeof(mix),sizeof(mix.x), sizeof(mix.y),sizeof(mix.z),sizeof(mix.s));//mix和其成员所占内存字节}9.7typedef声明类型C语言不仅提供了丰富的数据类型,而且还允许由用户自己定义类型说明符,也就是说允许由用户为数据类型取“别名”。类型定义符typedef即可用来完成此功。typedef定义的

一般形式为:typedef原类型名

新类型名其中,原类型名中含有定义部分,新类型名一般用大写表示,以便于区别。(1)有整型量m,n,其说明为:intm,n;可以以将整型说明符用typedef定义为:typedefintINTEGERINTEGER来代替int作整型变量的类型说明。例如:“NTEGERa,b;”它等效于:“inta,b;”(2)用typedef定义数组,不仅使程序书写简单,而且使意义更为明确,因而增强了可读性。例如:typedefcharNAME[20];表示NAME是字符数组类型,数组长度为20。然后可用NME说明变量,如:“NAMEal,a2,sl,s2;”完全等效于“charal[20],a2[20],s1[20],s2[20];”。(3)用typedef定义结构体等类型。例如:typedefstructstu{ charname[20]; intage; charsex;}STU;定义STU表示stu的结构体类型,然后可用STU来说明结构体变量,例如:STUbody1,body2;(4)有时也可用宏定义来代替typedef的功能,但是宏定义是由预处理完成的,而typedef则是在编译时完成的,后者更为灵活方便。9.8枚举类型如果一个变量只有几种可能的值,则可以定义为枚举(enumeration)类型。所谓“枚举”就是指把可能的值一一列举出来,变量的值只限于列举出来的值的范围内。

比如,描述星期几的数据就只能在星期一到星期日之间选择。声明枚举类型的一般形式为:enum[枚举名]{枚举元素列表};例如:enumweekday{mon,tue,wed,thu,fri,sat,sun};以上声明了一个枚举类型enumweekday,花括号中的mon,…,sun,称为枚举元素或枚举常量。我们可以用枚举类型来定义枚举变量。例如:enumweekdayweek1,week2;week1和week2被定义为枚举变量,它们的取值范围是花括号中的值之一。例如:weekl=mon;week2=sun;也可以没有类型名,而直接定义枚举变量,例如:enum{mon,tue,wed,thu,fri,sat,sun}work1,work2;9.8枚举类型(1)enum是关键字,标识枚举类型、定义枚举类型时必须用enum开头。(2)在定义枚举类型时,花括号中的枚举元素是常量,这些元素的名字是程序设计者自己指

定的,命名规则与标识符相同。这些名字只是作为一个符号,以利于提高程序的可读性,并无

其他固定的含义。枚举元素是常量,在C编译器中,按定义时的排列顺序取值0、1、2、……例如:weekl=mon;printf("%d",week1);输出整数0。(3)可以将枚举常量赋给一个枚举变量,但不能对枚举元素赋

值,例如:week2=sat;//正确

sun=0;//错误,不能对枚举常量赋值(4)在定义枚举类型时,可以指定枚举常量的值,例如:enumweekday{sun=7,mon=1,tue,wed,thu,fri,sat};此时,tue、wed、……的值从mon的值顺序加1,例如:tue=2(5)枚举值可以作判断比较,例如:if(week1==mon)if(week1>sun)枚举值的比较规则是以其在定义时的顺序号大小为依据。如果定义时未指定,则第

一个枚举元素的值默认为0。故有mon<tue<wed等关系。(6)整型与枚举类型是不同的数据类型,不能直接赋值。例如:work1=0;//错误,work1是枚举类型,只能在指定范围内获取枚举元素但可以通过强制类型转换赋值。例如:work1=(enumweekday)0;(7)枚举常量不是字符串,不能用下面的方法输出字符串“mon”:printf("%s",mon);而应用检查的方法去处理:if(weekl==mon)printf("mon");9.8枚举类型【例9-14】运行程序,观察枚举常量的输出值。程序代码:#include<stdio.h>voidmain(){ enumweekday{mon,tue,wed,thu,fri,sat,sun}; enumweekdayweek1; for(week1=mon;week1<=sun;week1++) switch(week1) { casemon:printf("mon,%d\t",mon);break; casetue:printf("tue,%d\t",tue);break; casewed:printf("wed,%d\t",wed);break; casethu:printf("thu,%d\t",thu);break; casefri:printf("fri,%d\t",fri);break; casesat:printf("sat,%d\t",sat);break; casesun:printf("sun,%d\n",sun);break; }}运行结果:mon,0

tue,1

wed,2

thu,3

fri,4

sat,5

sun,6【分析】未人为指定时,枚举常量按顺序对应的值是从0开始依次递增的,分别0,1,2,3,4,5,6。请读者思考,如何将其对应的顺序值变为1,2,3,4,5,6,7。实际上,只要将程序中的枚举定义语句中初始值指定从1开始即可,改为:enumweekday{mon=1,tue,wed,thu,fri,sat,sun};运行结果:mon,1

tue,2

wed,3

thu,4

fri,5

sat,6

sun,79.8枚举类型【例9-15】写一个函数,计算明天是星期几。程序代码:#include<stdio.h>enumday{sun,mon,tue,wed,thu,fri,sat};enumdayday_tomorrow(enumdayd){ enumdaynd; switch(d) { casesun:nd=mon;break; casemon:nd=tue;break; case

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论