C语言ch093共用体和枚举.ppt
2023/11/7,1,上一节我们学到了,链表,2023/11/7,2,第9章 用户自己建立数据类型,9.1 定义和使用结构体变量9.2 使用结构体数组9.3 结构体指针9.4 结构体数组9.5 用指针处理链表9.6 共用体类型9.9 使用枚举类型9.10 用typedef定义新类型,2023/11/7,3,9.5 共用体(Union),所有成员共享同一内存的自定义类型,0 x0012ff40,int i,float f,char ch,2023/11/7,4,共用体类型声明和变量定义,定义共用体变量的一般形式:union 共用体名 成员表列 变量表列;例如:union data int i;char ch;float f;union data a,b,c;sizeof(union data)?取决于占空间最多的那个成员变量,2023/11/7,5,也可以将类型声明与变量定义分开:union data int i;char ch;float f;union data a,b,c;当然也可以直接定义共用体变量,如:union int i;char ch;float f;a,b,c;,2023/11/7,6,union vs struct,相同点声明、定义和成员引用形式都相似。不同点结构体变量所占内存长度是各成员占的内存长度之和。一次只能给一个成员赋值。共用体变量所占的内存长度等于最长成员的长度。,2023/11/7,7,9.5.3 共用体类型数据的特点,(1)共用体变量中起作用的成员是最后一次存放的成员。如有以下赋值语句:a.i=1;a.c=a;a.f=1.5f;在完成以上3个赋值运算以后,以浮点数的形式存储1.5。此时用printf(“%d”,a.i);结果不是1(2)共用体变量的地址和各成员的地址相同。printf(%pn%pn%pn%pn,2023/11/7,8,(3)一次只能给一个成员赋值。例如:union int i;char ch;float f;a=1;(4)共用体变量不能作为函数参数,但指向共用体变量的指针可以。,2023/11/7,9,9.6 枚举类型(enum),如果一个变量只有几种可能的常量值,可以定义为枚举类型。所谓枚举是指将变量的值一一列举出来,变量的值只限于列举出来的值的范围内。枚举的声明与结构和联合相似:enum 枚举名 标识符=整型常数,标识符=整型常数,.标识符=整型常数 枚举变量;例如:enum weekdaysun,mon,tue,wed,thu,fri,sat;其中sun、mon、sat等称为枚举元素或枚举常量。,2023/11/7,10,如果其中不包括带有=的枚举元素,则相应常量值从0开始,且从左到右顺次加1。如果其中包括带有=的枚举元素,则该枚举元素的值由该表达式决定,其后的值由该值开始依次加1。注意:同一作用域中的各枚举符的名字必须各不相同,也不能与普通变量名同名,但其值可以相同。枚举元素可赋负值,之以后的标识符仍依次加1。,2023/11/7,11,枚举类型变量的定义,枚举类型变量的定义与结构和联合也相似。如,可以用此类型来定义变量。enum weekday workday,week_end;注意:枚举变量只能取枚举说明结构中的某个枚举常量。如,workday和week_end被定义为枚举变量,它们的值只能是sun到sat之一。例如:workday=mon;week_end=sun;today=1;是正确的。,2023/11/7,12,(1)C编译器将枚举元素按常量处理,故称枚举常量。不能对它们赋值,例如:sun=0;mon=1;是错误的。赋值只能声明时进行。(2)枚举值可以用来做判断比较。如if(workday=mon)if(workdaysun),说明,#include enum weekday SUN,MON,TUE,WED,THU,FRI,SAT;int main()enum weekday today=FRI;if(today=SAT|today=SUN)printf(today is a weekend dayn);else printf(today is a work dayn);return 0;,2023/11/7,13,2023/11/7,14,例9.12 口袋中有红、黄、蓝、白、黑5种颜色的球若干个。每次从口袋中先后取出3个球,问得到3种不同色的球的可能取法,打印出每种排列的情况。分析:球只能是5种色之一,而且要判断各球是否同色,可以用枚举类型变量处理。设取出的球为i、j、k。根据题意,i、j、k分别是5种色球之一,并要求ijk。可以用穷举法,即一种可能一种可能地试,看哪一组符合条件。算法可用图9.20表示。,2023/11/7,15,2023/11/7,16,2023/11/7,17,下面的问题是如何实现图9.20中的输出一种取法。这里有一个问题:如何输出red、blue等单词。不能写成printf(%s,red)来输出red字符串。可以采用图9.21的方法。,2023/11/7,18,int main()enum color red,yellow,blue,white,black;enum color pri;int i,j,k;int n,loop;n=0;/取法次数,2023/11/7,19,for(i=red;i=black;i+)for(j=red;j=black;j+)if(i!=j)for(k=red;k=black;k+)if(k!=i),20,for(loop=1;loop=3;loop+)switch(loop)case 1:pri=(enum color)i;break;case 2:pri=(enum color)j;break;case 3:pri=(enum color)k;break;default:break;switch(pri)case red:printf(%-10s,red);break;case yellow:printf(%-10s,yellow);break;case blue:printf(%-10s,blue);break;case white:printf(%-10s,white);break;case black:printf(%-10s,black);break;default:break;,2023/11/7,21,printf(n);printf(ntotal:%5dn,n);,2023/11/7,22,修改输出后的程序,int main()enum color red,yellow,blue,white,black;int i,j,k,n=0;/组合个数char*sColor5=red,yellow,blue,white,black;,2023/11/7,23,for(i=red;i=black;i+)for(j=red;j=black;j+)if(i!=j)for(k=red;k=black;k+)if(k!=i),2023/11/7,24,那么,不用枚举变量而用常数0代表红,1代表黄不也可以吗?是的,完全可以。但显然用枚举变量更直观,因为枚举元素都选用了令人见名知意的标识符,而且枚举变量的值限制在定义时规定的几个枚举元素范围内,如果赋予它一个其他的值,就会出现出错信息,不易出错。,2023/11/7,25,9.7 用typedef定义类型,typedef:为已有的类型声明一个新的名字注意:并没有创建新类型。类型说明的格式为:typedef 已有类型名 新类型名;如:typedef int INTEGER;typedef float REAL;指定用INTEGER代表int类型,REAL代表float。这样,以下两行等价:int i,j;float a,b;INTEGER i,j;REAL a,b;这样可以使熟悉FORTRAN的人能用INTEGER和REAL定义变量,以适应他们的习惯。我们一般把新类型名的首字母用大字母表示,以示区别。,2023/11/7,26,如果在一个程序中,一个整型变量用来计数,可以:typedef int COUNT;COUNT i,j;在程序中将i、j定为COUNT类型,可以使人更一目了然地知道它们是用于计数的。typedef同样可用来说明结构、联合以及枚举 typedef struct date int month;int day;int year;Date;Date today;Date*pDate;,2023/11/7,27,还可以进一步:typedef int Num100;声明Num为整型数组类型Num n;定义n为整型数组 typedef char*String;声明String为字符指针类型String p,s10;p为字符指针变量,s为指针数组 typedef int(*Pointer)()声明Pointer为指向函数的指针类型,该函数返回整型值Pointer p1,p2;p1、p2为Pointer类型的指针变量,2023/11/7,28,归纳起来,声明一个新的类型名的方法是:先按定义变量的方法写出定义体(如:int i;);将变量名换成新类型名(如:int Count);在最前面加typedef(如:typedef int Count);然后可以用新类型名去定义变量。再以定义上述的数组类型为例来说明:int n100;int Num100;typedef int Num100;Num n;,2023/11/7,29,同样,对字符指针类型,也是:char*p;char*String;typedef char*String;String p,s10;,2023/11/7,30,说明,(1)typedef 与#define 有相似之处typedef int COUNT;#define COUNT int作用都是用COUNT 代表int。但事实上,它们二者是不同的。#define是在预编译时处理的,它只能作简单的字符串替换 而typedef是在编译时处理的。实际上它并不是作简单的字符串替换例如:typedef int Num10;并不是用Num10去代替int,而是采用如同定义变量的方法那样来声明一个类型。,2023/11/7,31,(2)当不同源文件中用到同一类型数据(尤其是像数组、指针、结构体、共用体等类型数据)时,常用typedef声明一些数据类型,把它们单独放在一个头文件中,然后在需要用到它们的文件中用#include命令把它们包含进来。(3)使用typedef除了表达方式更简洁之外,还有利于程序的通用与移植。有时程序会依赖于硬件特性,用typedef便于移植。,2023/11/7,32,例如,有的计算机系统int型数据用两个字节,数值范围为-3276832767,而另外一些机器则以4个字节存放一个整数,数值范围为21亿。如果把一个C程序从一个以4个字节存放整数的计算机系统移植到以2个字节存放整数的系统,按一般办法需要将定义变量中的每个int改为long。例如,将int a,b,c;改为long a,b,c;,如果程序中有多处用int定义变量,则要改动多处。现可以用一个Integer来声明int:typedef int Integer;在程序中所有整型变量都用Integer定义。在移植时只需改动typedef定义体即可:typedef long Integer;,2023/11/7,33,这一节我们学到了,共用体(联合)枚举使用typedef为已有类型定义新名,2023/11/7,34,作业,一个宿舍一组20121214第15周周五 检查大作业演示程序每组不超过5分钟演示结束,提交每组成员(学号姓名班级)和工作量比例,2023/11/7,35,读书,读好书,读经典之书,精研经典之书CThe C Programming Language(C语言程序设计,第2版新版,Brian W.Kernighan,Dennis M.Ritchie,机械,经典,强烈推荐)C Traps and Pit falls(C陷阱与缺陷,邮电,深入学习)C入门C+程序设计教程,钱能,清华大学出版社,国内为数不多的C经典书籍之一,推荐或C+大学基础教程(第五版),电子工业,2007 年2月,厚 或C+程序设计实用教程,张国锋,清华大学出版社C进阶C+编程思想(第二版),Bruce Eckel,机械工业出版社,强烈推荐或C+Primer(第4版),人民邮电,厚,2023/11/7,36,C+深入Effective C+中文版(2nd Edition),Scott Meyers,候捷译,华中科技大学出版社:对于这本书,我认为任何想把C+学好,想用C+做项目开发的都应该好好研读本书。孟岩在该书的印介中如是说:曾经在网络讨论组中间看到这样的说法,C+程序员可以分成两类,读过Effective C+的和没读过的。个人认为,Effective C+将面向对象的思想和原则与软件设计、C+开发很好地结合在一起,达到了一种完美统一的境界:你在学习C+技术(以原则条款的方式给出)的同时,OO思想得到了升华和提高。纯粹的OO思想的学习会略显得枯燥和无味,但是以为使用、掌握了一门用于面向对象系统开发语言便以为懂得了OO的开发与设计(OO的精华)则会显得多么的无知和轻浮。如果大家想真正体验OO设计开发、享受C+的强大与精髓,请读Effective C+。-k_eckels book list,2023/11/7,37,创建工程AddressBook,源文件名person.c,定义结构体person,字段如下,并完成结构体数组的查找函数searchPersonByName。编号idunsigned int姓名namechar40学号stuidchar16性别genderchar4出生日期birthdaychar8 如:19910401民族nationchar40家庭电话homephonechar40家庭住址addresschar100手机cellphonechar40emailchar100qqchar40个人主页personalhomepagechar100兴趣爱好hobbychar100备注commentchar100,