资源预览内容
第1页 / 共81页
第2页 / 共81页
第3页 / 共81页
第4页 / 共81页
第5页 / 共81页
第6页 / 共81页
第7页 / 共81页
第8页 / 共81页
第9页 / 共81页
第10页 / 共81页
亲,该文档总共81页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
第八章第八章 结构体、共用体结构体、共用体结构体共用体(人民邮电管银枝主篇)本章内容本章内容8.1 结构体类型结构体类型8.2 结构体变量结构体变量8.3 结构体数组结构体数组8.4 共用体共用体8.5 枚举类型枚举类型 8.6 用typedef定义类型 8.7 本章小结本章小结结构体共用体(人民邮电管银枝主篇)8.1 结构体类型结构体类型任务提出:学生信息管理系统数据库中,学生的信息包括学号、姓名、性别、出生日期、五门课程的成绩及平均成绩,如何定义一个数据类型。任务分析:在此例中,学生的学号、姓名、性别、出生日期、课程的成绩他们的数据类型并不一致,其中的学号、姓名为字符型数组,性别为单个的字符型数据,成绩为实型数据,而出生日期又包括年月日三项。一个学生的学号、姓名、性别、出生年月日、成绩等项,这些项都与某一学生相联系。如果将它们分别定义成互相独立的简单变量,难以反映它们之间的内在联系。但如果把它们组织成一个组合项,定义为另一种如下表所示的结构体类型的数据:结构体共用体(人民邮电管银枝主篇)结构体类型的定义如下: struct birthday int year; int month; int day; ; struct studentchar num7char name20; char sex; struct birthday bir; float score5; float average; ;结构体共用体(人民邮电管银枝主篇)8.1.1结构体定义格式结构体定义格式struct struct 结构体名结构体名结构体名结构体名 数据类型数据类型数据类型数据类型1 1 成员名成员名成员名成员名1;1;数据类型数据类型数据类型数据类型2 2 成员名成员名成员名成员名2;2; . . . . . . . . . . . . 数据类型数据类型数据类型数据类型n n 成员名成员名成员名成员名n;n; ;如: struct studentchar num7; char name20; char sex; float score;结构体共用体(人民邮电管银枝主篇)在以上定义中:(1)“结构体名”是用户取的标识符,是结构体类型的标志。如上例中的结构体定义中student就是一个结构体名。(2)大括弧内是结构体中的各个成员,由它们组成一个结构体。如上例中的num、name、sex、score等都是成员名。(3)对每个成员必须作类型说明。数据类型可以是基本数据类型说明符,也可以是用户已经定义过的结构体名,还可以是后面将要介绍的其它数据类型的类型说明符。类型说明的格式是:数据类型名数据类型名 成员名成员名(4)成员名是用户取的标识符,是用来标识所包含的成员名称。成员名的命名规则与变量名相同。成员也称为“域”,每一个成员也称为结构体中的一个域。如在上例中的结构体定义中,定义了一个名为student的结构体,该结构共有4个成员组成。第一个成员为 num,整型变量;第二个成员为name,字符数组;第三个成员为sex,字符变量;第四个成员为score,实型变量。应注意括号外面的分号“;”不能少。(5)结构体定义可以嵌套,即某个结构体成员的数据类型可以说明为另一个已定义过的结构体型。结构体共用体(人民邮电管银枝主篇)例:例:定义一个结构体类型用来表示学生的基本情况,其中的每个学生的数据包括:学号、姓名、性别、年龄、成绩、家庭地址等。分析:分析:该结构体中,可将学号、姓名、家庭地址定义成字符型数组,性别定义成字符型数据,年龄、成绩定义实型数据。结构体名取为“student”,它包括num、name、sex、age、score、addr等不同类型的数据项。结构体类型定义如下:struct student char num7;char name20;char sex;int age;float score;char addr30;结构体共用体(人民邮电管银枝主篇)例:例:定义一个结构体类型用来表示一个单位的职工档案,职工档案中包括:职工姓名、性别、年龄、工资等。分析:分析:该结构体中,可将职工档案中的职工姓名定义成字符型数组,性别定义成字符型数据,年龄定义成整型数据,工资定义实型数据。结构体名取为“person”,它包括name、sex、age、wage 等不同类型的数据项。结构体类型定义如下:可定义如下的结构体:struct person char name20; char sex; int age; float wage; ;结构体共用体(人民邮电管银枝主篇)8.1.2嵌套的结构体类型定义方法嵌套的结构体类型定义方法例:例:定义一个结构体类型用来表示职工档案,职工档案中除和上例一样包括职工姓名、性别、工资外,职工的出生日期要能体现年月日。分析:分析:假设此结构体类型名person1,其成员有职工姓名name、性别sex、出生日期bir、工资wage等五个成员。其中的职工姓名、性别、工资等成员的定义方法同上例一样。而对于出生日期bir又包括三个部分year、month、day(分别对应年、月、日),则要用嵌套的结构体类型定义方法来定义。结构体共用体(人民邮电管银枝主篇)嵌套的结构体类型定义如下: struct birthday int year; int month; int day; ; struct person1 char name20; char sex; struct birthday bir; float wage; ;这里,在定义结构体类型person1时用到了基本数据类型外的结构体类型birthday,此时结构体类型birthday的定义必须出现在前面,否则就会出现“结构体未定义”的错误。结构体共用体(人民邮电管银枝主篇)8.1.3结构体类型使用说明结构体类型使用说明1.当用户需要将一些不同类型但又相互联系的数据放在一起时,就可以将它们定义成结构体类型,以便于反映它们之间的相互联系。2.结构体定义中的花括号里面的每一个定义语句后面均要用分号“;”作为语句结束标记, 花括号外也有一个分号“;”作为结构体定义语句的结束标记。 3.结构体是一种数据类型,其中的成员不是变量,系统也不会给成员分配内存。 4.已经定义的某种结构体可以作为一种数据类型,用来定义变量、数组、指针等。这时才会给定义的变量、数组、指针分配内存。5.如在定义结构体成员类型时要用到基本数据类型外的结构体类型,即需嵌套定义时,一定要注意引用的结构体类型名必须是已经定义过的,否则就会出现“结构体未定义”的错误。如上面例11.3,名为“birthday”的定义必须在结构体“person1”的定义之前,否则就会出错。结构体共用体(人民邮电管银枝主篇)8.2 结构体变量结构体变量任务提出:任务提出:学生信息管理系统数据库中,学生信息包括学号、姓名、性别、出生日期、五门课程的成绩、平均成绩等数据,从键盘中输入某学生的数据信息,并输出该学生的所有信息。任务分析:任务分析:前面已定义了一个名为student的结构体,但只是指定了一个结构体类型,它相当于一个模型,其中并没有具体的数据,系统也不给它分配内存单元。为了能在程序中使用结构体类型的数据,还应当定义结构体类型的变量,并在其中存放具体的数据。如果在程序中已经定义了某个结构体,则在此后就可使用这种用户自定义的数据类型来定义变量。上述问题的所需的类型变量的定义如下:struct student stu;结构体共用体(人民邮电管银枝主篇)#include stdio.h #define MAX2 5struct birthday int year; int month; int day; ;struct studentchar num7;char name20; char sex; struct birthday bir; int scoreMAX2; float average; ;结构体共用体(人民邮电管银枝主篇)main() int i; struct student stu; stu.average=0.0; scanf(%c,&stu.sex); scanf(%d,%d,%d,&stu.bir.year,&stu.bir.month,&stu.bir.day); for(i=0;iMAX2;i+) scanf(%d,&stu.scorei); stu.average+=stu.scorei; scanf(%s%s,stu.num,stu.name);stu.average=stu.average/MAX2;printf(学号:%s,stu.num); printf(n姓名:%s,stu.name); printf(n性别:%c,stu.sex);printf(出生年月日:%d年%d月%d日,stu.bir.year,stu.bir.month,stu.bir.day)printf(n五门课程的成绩为:n);for(i=0;iMAX2;i+) printf (%4d,stu.scorei);printf(n平均成绩为:n);printf(%5.2fn,stu.average);getch(); 结构体共用体(人民邮电管银枝主篇)程序运行情况如下:程序运行情况如下:F1991,11,1668 78 88 76 69100001 李平则输出结果为:学号:100001姓名:李平性别:F出生年月日:1991年11月16日五门课程的成绩为:6878887669平均成绩为:75.80结构体共用体(人民邮电管银枝主篇)8.2.1 结构体变量的定义与初始化结构体变量的定义有以下三种方法:1、 用结构体类型名定义变量用结构体类型名定义变量用结构体类型名定义变量的一般格式:结构体类型名结构体类型名结构体类型名结构体类型名 变量名变量名变量名变量名1 1,变量名,变量名,变量名,变量名2 2,变量名,变量名,变量名,变量名n n 其中结构体类型名是已经定义过的结构体名,后面的各结构体变量名之间用逗号分隔。这种方法也就是先定义结构体类型再定义变量名。例如:struct student char num7;char name20;char sex;int age;float score;char addr30;结构体共用体(人民邮电管银枝主篇)也可以用宏定义使用一个符号常量来表示一个结构体类型名。例如,在程序的前面有宏定义:#define STU struct student则以上的结构体及变量定义可修改为:struct student char num7;char name20;char sex;int age;float score;char addr30; STU student1,student2;结构体共用体(人民邮电管银枝主篇)在定义变量的同时,可以对变量赋初值,例如上面的变量定义语句可以改为如下语句: struct student student1=10001,Zhang Xin,M,19,90.5,Shanghai,student2=10002,Wang Li,F,20,98,Beijing;定义结果如下表所示: 在定义了结构体变量后,系统会为之分配内存单元。例如student1和student2在内存中各占64个字节(7+20+1+2+4+30=64)。应当注意,将一个变量定义为基本数据类型与将一个变量定义成结构体类型的方法是不同的,后者不仅要求指定结构体类型,而且要求指定为某一特定的结构体类型。结构体共用体(人民邮电管银枝主篇)2、定义结构体类型的同时定义变量、定义结构体类型的同时定义变量这种定义的一般格式为: struct 结构体名 数据类型1 成员名1; 数据类型2 成员名2; . . 数据类型n 成员名n; 变量名表列;例如,为两个学生信息定义2个变量,程序段如下 struct student char num7; char name20; char sex; int age; float score; char addr30; student1,student2;结构体共用体(人民邮电管银枝主篇)3、定义无名结构体类型的同时定义变量、定义无名结构体类型的同时定义变量这种定义的一般格式为: struct 数据类型1 成员名1; 数据类型2 成员名2; . . 数据类型n 成员名n; 变量名表列;例如: struct char num7; char name20; char sex; int age; float score; char addr30; student1,student2;结构体共用体(人民邮电管银枝主篇)或直接为:struct char num7;char name20;char sex;int age;float score;char addr30;student1=10001,Zhang Xin,M,19,90.5,Shanghai,student2=10001,Wang Li,F,20,98,Beijing;即定义的同时给变量赋初值。这种方法是将类型定义和变量定义同时进行,但是结构体类型的名称省略了,以后将无法使用这种结构体来定义其它的变量。结构体共用体(人民邮电管银枝主篇)关于结构体类型,有几点说明:(1)类型和变量是两个不同的概念。只能对变量赋初值、存取或运算,而不能对一个类型赋值、存取或运算。对类型不分配内存空间,对变量却要分配内存空间。(2)对结构体中的变量成员(即“域”),可以单独使用,其作用与地位相当于普通变量。 (3)成员也可以是一个结构体变量。此时即构成了嵌套的结构。 例如:struct dateint momth; int day; int year; ; struct student char num7;char name20;char sex;int age;struct date birthday; /* birthday是struct date类型*/char addr30; student1,student2;(4)成员名可以与程序中的变量名同,二者不代表同一对象。例如,程序中可以另定义一个变量num,它与struct student中的num 是两回事,互不干扰。但初学者应尽量不要这样使用,以防使用不小心时相混。结构体共用体(人民邮电管银枝主篇)8.2.2 结构体成员的引用结构体成员的引用1、结构体变量成员的引用格式为:结构体变量成员的引用格式为: 结构体变量名成员名其中的“”称为成员运算符,其运算的优先级别是最高的,和圆括号“( )”、下标运算符“ ”是同一级别的,运算顺序是自左向右。如:student1.num表示student1中的num(学号)项。由于该成员是一字符型数组类型的,不能用赋值方法给此成员赋值,例如:student1.num10001;是不合法。正确的方法是把“student1.num”看作一个整体,用字符串复制的方法,如:strcpy(student1.num, 10001);结构体共用体(人民邮电管银枝主篇)2、引用结构体变量应遵循的规则、引用结构体变量应遵循的规则(1)不能将一个结构体变量作为一个整体变量进行输入输出,只能对结构体变量中的各个成员分别进行输入输出。例如,前面已定义了student1和student2为结构体变量并且它们也已有了初值。不能这样引用:printf(%s,%s,%c,%d,%f,%sn,student1);(2)如果某个结构体类型的变量成员的数据类型又是一个结构体类型,则只能对最低级的成员进行赋值、输入输出以及运算。外层结构体类型的变量成员是不能单独引用的。这种嵌套的结构体变量成员的引用方法是逐级找到最低级的成员才能使用。例如对具有两层的结构体变量名的引用为: 外层结构体类型变量名外层成员名内层成员名如上节已定义过的结构体变量student1,可以这样访问各成员:student1.numstudent1.birthday.month结构体共用体(人民邮电管银枝主篇)(3)结构体变量的成员可以像普通变量一样进行各种运算(参与运算时注意其类型)。如:student1.score=student2.score+10; sum=student1.score+student2.score; student1.age+;+student2.age; (4)可以引用结构体变量成员的地址,其引用格式为:&结构体变量名成员名例如:scanf(%d,&student1.num);(输入student1.num的值) (5)可以引用结构体变量的地址。结构体变量的地址主要用于作函数的参数,传递结构体的地址。结构体变量的地址的引用格式为: &结构体变量名例如:printf(%x,&student1) ;(输出student1的首地址)结构体共用体(人民邮电管银枝主篇)例:例:给结构体变量成员赋值并输出其值。#include main( ) struct char num7; char name20; char sex; float score3;x=10001,Zhang Xin,M,68,89,78;printf(学号:%sn姓名:%sn性别:%cn,x.num,x.name,x.sex);printf(成绩:%.2f、%.2f、%.2f、n,x.score0,x.score1,x.score2);getch();结构体共用体(人民邮电管银枝主篇)用赋值语句等给结构体变量成员赋值: #include main( ) /*定义一结构体类型*/*定义一结构体类型的变量*/struct student x;/*给结构体类型的变量x赋值*/strcpy(x.num,100001);strcpy(x.name,Zhang Xin);x.sex= M;x.score0=68;x.score1=89;x.score2=78;/*输出结果*/getch();结构体共用体(人民邮电管银枝主篇)例:例:嵌套的结构体变量成员的引用举例#include #include struct birthdayint year; int momth; int day;;struct personchar name20;char sex;struct birthday bir; float wage;x;结构体共用体(人民邮电管银枝主篇)main( )strcpy(x.name,gu); x.sex= F; x.bir.year=1972;x.bir.month=10;x.bir.day=3;x.wage=2880.0;printf(姓名:%s,性别:%c,工资:%fn,x.name,x.sex,x.wage);printf(出生年、月、日%4d%2d%2dn,x.bir.year,x.bir.month,x.bir.day);getch();结构体共用体(人民邮电管银枝主篇)8.2.3 结构体与函数结构体与函数 可以将一个结构体变量的值传递给另一个函数,在函数间传递结构体型的数据和传递其它类型数据的方法完全相同,可以使用全局外部变量、返回值、形式参数与实际参数结合方式(参数传递方式又分为值传递和地址传递两种)。将一个结构体变量的值传给另一个函数的具体用法如下:1、使用返回值方式传递结构体数据、使用返回值方式传递结构体数据 函数的返回值必须是某种已定义过的结构体指针(即指向结构体变量的指针),利用“return(表达式);”语句返回的表达式值也必须是同种结构体型的指针,该指针指向的数据则是同一种结构体型的数据;而接受返回值的变量也必须是这种结构体型的指针变量。结构体共用体(人民邮电管银枝主篇)2、使用形式参数和实际参数结合方式传递结构体型数据、使用形式参数和实际参数结合方式传递结构体型数据 要注意是单向的值传递还是双向的地址传递。使用单向的值传递方式,通常形式参数要说明成某种结构体型,而对应的实际参数必须是同一种结构体型。如果使用双向的地址传递方式,要区分不同的情况,如果形式参数被说明成某种结构体型的指针变量,则实际参数必须是同一种结构体型的变量地址、数组名或已赋值的指针变量等;如果形式参数是某种结构体型数组,则对应的实际参数必须是同一种结构体型的数组或指针变量。(关于指针部分内容将在后面讲解), 用结构体变量的成员作参数。例如,用student1.num 或student1.name作函数的实参,将实参值传给形参。其用法和普通变量作实参的用法一样,属于“值传递”方式。只是要注意实参和形参的类型保持一致。 用结构体变量作实参。采用的是“值传递”的方式,将结构体变量所占的内存单元的内容全部顺序传递给形参。形参也必须是同类型的结构体变量。在函数的调用期间形参也要占用内存单元。此外由于采用的是值传递方式,如果在调用过程中改变了形参的值,则该值不能返回主调函数,这是很不方便的。因此这种方法一般很少用。结构体共用体(人民邮电管银枝主篇)【例例8-6】用结构体变量作函数参数#include #include struct studentchar num7; char name20; char sex; float score3;void print(struct student x) printf(学号:%sn姓名:%sn性别:n,x.num,x.name,x.sex); printf(成绩1:%fn,x.score0); printf(成绩2:%fn,x.score1); printf(成绩3:%fn,x.score2);结构体共用体(人民邮电管银枝主篇)main()void print(struct student);struct student x;strcpy(x.num,10002);strcpy(x.name,zhang shang);x.sex= F; x.score0=85; x.score1=74; x.score2=90; print(x);getch();结构体共用体(人民邮电管银枝主篇)【例例8-7】用全局外部变量方式传递数据struct student3 /* 定义一个结构体student3*/ char num7;char name20;int age;x; /*定义结构体型的外部变量x*/void printin( ) /*无参无返回值的函数*/ scanf(%s,x.num); scanf(%s,x.name); scanf(%d,&x.age); return;main( ) printin( ); /*调用函数printfin( )*/ printf(学号:%s,姓名:%s,年龄:%dn,x.num,x.name,x.age); /*依次输出学生的有关信息*/ getch();结构体共用体(人民邮电管银枝主篇)【例例8-8】学院图书馆要购进一批书籍,共4种。编写程序,从键盘输入书名、购书数量、书的单价,请编写程序,计算每一种书的总金额,和所有要购书籍的总金额,输出购书清单,输出的购书清单的格式如下:购书清单:书名 数量 单价 合计购书金额总计:#include #include #include struct BookLib char name12; int num; float price; float SumMoney;void list(struct BookLib StuBook);结构体共用体(人民邮电管银枝主篇)main( )struct BookLib Book4; int i; float Total=0; printf(请输入4本要购进的书籍信息:书名 数量 单价n); for(i=0;i4;i+) scanf(%s,Booki.name); /* 输入书名*/ scanf(%d%f,&Booki.num,&Booki.price); Total=Total+Booki.num*Booki.price; printf(n-n); printf(购书清单:n);printf(书名ttt 数量t单价t合计n);for(i=0;i4;i+) list(Booki); /* 输出购书清单*/ printf(购书金额总计:%.2fn,Total); getch(); void list(struct BookLib StuBook) StuBook.SumMoney=StuBook.num*StuBook.price; printf(%-24s%dt%.2ft%.2fn,StuBook.name,StuBook.num, StuBook.price,StuBook.SumMoney); 结构体共用体(人民邮电管银枝主篇)运行结果如下:运行结果如下:请输入4本要购进的书籍信息:书名 数量 单价:计算机基础 10 18.5数学 10 15C语言 15 16英语 20 17 购书清单:书名 数量 单价 合计计算机基础 10 18.5 185.00数学 10 15.00 150.00C语言 15 16.00 160.00英语 20 17.00 340.00购书金额总计:915.00结构体共用体(人民邮电管银枝主篇)8.3 结构体数组结构体数组任务提出:任务提出:假设一个班有50个学生,每个学生信息包括学号、姓名、性别、出生日期、五门课程的成绩及平均成绩等数据,从键盘中输入50个学生的数据信息,按平均成绩排序后输出所有学生的信息表。任务分析:任务分析:前面已定义了一个名为student的结构体,还定义了结构体类型的变量,并可在其中存放具体的数据。用此方法处理单个或几个学生数据时时是可行的,但若学生数较多,用前面单个定义结构体变量来存放数据是很不方便的。将学生数定义成符号常量:#define MAX1 50则可定义如下的结构体数组:struct student stuMAX1;结构体共用体(人民邮电管银枝主篇)#define MAX1 50#define MAX2 5struct birthday int year; int month; int day; ;struct student char num7;char name20; char sex; struct birthday bir; float scoreMAX2; float average; ;结构体共用体(人民邮电管银枝主篇)main() int i,j,k; char tnum7,tname20,tsex; int tbir; float tscore;struct student stuMAX1;for(i=0;iMAX1;i+) scanf(%s,stui.num); scanf(%s,stui.name);scanf(%c,&stui.sex);scanf(%d,%d,%d,&stui.bir.year, &stui.bir.month, &stui.bir.day);for(j=0;jMAX2;j+) scanf(%f,&stui.scorej);stui.average+=stui.scorej; stui.average=stui.average/MAX2; 结构体共用体(人民邮电管银枝主篇)for(j=0;jMAX1-1;j+) /*共比较MAX1-1轮*/ for(i=0;iMAX1-j;i+) if(stui.average stui+1.average) strcpy(tnum,stui.num); strcpy(stui.num,stui+1.num); strcpy(stui+1.num,tnum);strcpy(tname,stui.name); strcpy(stui.name,stui+1.name); strcpy(stui+1.name,tname); tsex=stui.sex;stui.sex=stui+1.sex;stui+1.sex=tsex; tbir=stui.bir.year;stui.bir.year=stui+1.bir.year; stui+1.bir.year=tbir; tbir=stui.bir.month;stui.bir.month=stui+1.bir.month; stui+1.bir.month=tbir; tbir=stui.bir.day;stui.bir.day=stui+1.bir.day; stui+1.bir.day=tbir; for(k=0;kMAX2;k+) tscore=stui.scorek; stui.scorek=stui+1.scorek; stui+1.scorek=tscore; 结构体共用体(人民邮电管银枝主篇)for(i=0;iMAX1;i+) printf(%10s,stui.num); printf (%25s,stui.name);printf (%3c,stui.sex);printf (%d/%d/%d ,stui.bir.year, stui.bir.month, stui.bir.day);for(j=0;jMAX2;j+) printf (%5.2f,&stui.scorej);printf(%5.2f,stui.average); getch();结构体共用体(人民邮电管银枝主篇)8.3.1结构体数组的定义和引用结构体数组的定义和引用 结构体数组的定义方法和定义结构体变量一样也有三种不同的方法。1、先定义结构体,然后再定义结构体数组并赋初值。、先定义结构体,然后再定义结构体数组并赋初值。如:struct student char num7; char name20; char sex; float score3;struct student s3=200001,钱企,M,65,87,90,200002,李小艳,F,75,98,60,200003,徐强,M,85,76,69;结构体共用体(人民邮电管银枝主篇)2、定义结构体的同时定义结构体数组并赋初值、定义结构体的同时定义结构体数组并赋初值如:struct student char num7;char name20;char sex;float score3;s3= 200001,钱企,M,65,87,90,200002,李小艳,F,75,98,60,200003,徐强,M,85,76,69;结构体共用体(人民邮电管银枝主篇)3、定义无名结构体的同时定义结构体数组并赋初值、定义无名结构体的同时定义结构体数组并赋初值如:struct char num7;char name20;char sex;float score3;s3=200001,钱企,M,65,87,90,200002,李小艳,F,75,98,60,200003,徐强,M,85,76,69;结构体共用体(人民邮电管银枝主篇) 定义了一个结构体数组,就可以使用这个数组中的元素。对结构体数组,可以引用其成员,引用方法和普通变量一样。也可以引用结构体数组元素的地址。结构体数组元素的引用格式如下: 结构体数组名下标.成员名结构体共用体(人民邮电管银枝主篇)例:例:设有三个候选人,每次输入一个候选人的名字,最后输出各人的得票结果。分析:分析:该问题要求编一程序,实现候选人得票的统计。程序中涉及到两种数据:候选人的姓名及候选人的得票数。定义一个结构体数组用来存放此数据: struct person char name20; int count; leader3= Zhang Xin,0, Li Shan,0, Wan pin,0;此结构体数组有三个元素,每个元素包含两个成员 name(姓名)、count(票数)。在定义时使之初始化,使三位候选人的票数都先设为零。为方便起见,假设参加选举的代表共有10人,用符号常量定义:#define number 10结构体共用体(人民邮电管银枝主篇)#include #define number 10struct person char name20; int count; leader3= Zhang Xin,0, Li Shan,0, Wan pin,0;main()int i,j; char leader_name11; for(i=0;inumber;i+) scanf(%s,leader_name); for(j=0;j3;j+) if(strcmp(leader_name, leaderj.name)=0) leaderj.count+; printf(n);for(i=0;i3;i+) printf(%25s:%dn, leaderi.name,leaderi.count+);getch();结构体共用体(人民邮电管银枝主篇)8.4 共用体共用体任务提出:任务提出:设有若干个人员的数据,其中有学生和教师。学生的数据中包括:姓名、号码、性别、职业、班级。教师的数据中包括:姓名、号码、性别、职业、职务。要求:当输入人员的数据时能打印出他们的资料,并把资料放在同一表格中。任务分析:任务分析:为简化程序,这里只给出两个人员的数据,假设两人的数据如下:其中:“sex”项中,“F”表示“女”,“M”表示“男”;“job”项中,“S”表示“学生”,“T”表示“教师”;第五项中,若前面是学生,则表示“班级”,若是教师,则表示“职务”。结构体共用体(人民邮电管银枝主篇) struct /*定义一个无名结构体*/ char num7; char name20; char sex; char job; union /*定义一个无名共用体* char clas10; char position10; pos; /*定义一共用体变量pos,它同时又是结构体中的一成员*/ person2; /*定义一外部结构体数组,内含两个数组元素*/main( ) int n,i;for(i=0;i2;i+)scanf(%c%c%s%s,&personi.sex,&personi.job,personi.num,personi.name);printf(%ct%ct%st%s,personi.sex,personi.job,personi.num,personi.name); getch();结构体共用体(人民邮电管银枝主篇)if(personi.job=S) scanf(%s,personi.pos.clas);else if(personi.job=T) scanf(%s,personi.pos.position);else printf(input error!);printf(编号: 姓名 性别 职业 班级/职务n);for(i=0;i2;i+)if(personi.job=S) printf(%-10s,%-25s,%-6c,%-12sn,personi.num,personi.name,personi.sex,personi.job,personi.pos.clas);else if(personi.job=T) printf(%-10s,%-25s,%-6c,%-12sn,personi.num,personi.name,personi.sex,personi.job,personi.pos.position);getch();结构体共用体(人民邮电管银枝主篇)8.4.1共用体的定义共用体的定义共用体定义的一般格式如下: union 共用体名 数据类型1 成员名1; 数据类型2 成员名2; . . 数据类型n 成员名n; ;其中:(1)共用体名是用户自己取的标识符;(2)数据类型可以是基本数据类型,也可以是已定义过的结构体、共用体等其它数据类型;(3)成员名是用户自己取的标识符,用来标识所包含的成员名称;例如: union data int i; char c; float f; ;结构体共用体(人民邮电管银枝主篇)注意几点:(1)右花括号后面的分号“;”不能少,它是共用体定义语句的结束标志;(2)共用体中的每个成员所占的内存单元都是连续的,而且都是从分配的连续内存单元的第一个内存单元开始存放。因此,一共用体数据的所有成员的首地址都是相同的。(3)共用体所占的内存单元等于最长的成员的长度,这一点和结构体是不同的。结构体所占的内存单元是各成员所占的内存长度之和,每个成员分别占有自己的内存单元。结构体共用体(人民邮电管银枝主篇)8.4.2共用体变量的定义共用体变量的定义 在定义了某个共用体类型后,就可以使用它来定义相应的变量、数组和指针等。共用体变量的定义方法和结构体相同,也有三种方法:一是先定义共用体,再定义共用体类型的变量;二是定义的同时定义共用体和变量;三是定义无名共用体的同时定义变量。例如: union data int i; char c; float f; ; union data a,b,c;或是: union data int i; char c; float f; a,b,c;或是: union int i; char c; float f; a,b,c;结构体共用体(人民邮电管银枝主篇)8.4.3共用体变量的引用共用体变量的引用共用体变量成员引用的一般格式如下: 共用体变量名.成员名其中的“.”和结构体中的成员运算符“.”相同。如前面定义了a,b,c为共用体变量,则在程序中可以这样引用:a.i=12;scanf(%cn,&a.c);printf(%fn,a.f);共用体成员的地址也可以引用,其引用格式为: &共用体变量名.成员名注意,如果用指针变量来存放共用体成员变量的地址,则该指针变量的类型必须和该共用体成员的类型一致。共用体变量的地址也可引用,其引用格式为: &共用体变量名注意,如果用指针变量来存放该共用体变量的地址,则该指针变量的类型也必须和该共用体变量一样是同一种共用体类型。结构体共用体(人民邮电管银枝主篇)例:例:阅读下列程序,分析和了解共用体变量成员的取值情况。#include union memb double v; int n; char c; ;main() union memb tag; tag.n=18; tag.c=T; tag.v=36.7; printf(tag.v=%6.2fntag.n=%4dntag.c=%cn,tag.v,tag.n,tag.c); 结构体共用体(人民邮电管银枝主篇)例:例:定义自定义类型struct VARIANT,从键盘输入数据类型(1-整数,2-单精度浮点数,3-双精度浮点数),然后从键盘输入该类型的数据存储到共用体成员变量中。struct VARIANTint vt; /*当前的结构体存储的数据类型*/union unsigned int iVal; /* int型数据*/float fVal; /* float型数据*/double dVal; /* double型数据*/u; /*共用体类型成员变量u,存储当前的数据信息共用体定义*/;结构体共用体(人民邮电管银枝主篇)void main() struct VARIANT varValue; printf(请输入数据类型,然后输入此数据(1-整数,2-单精度浮点数,3-双精度浮点数));scanf(%d,&(varValue.vt) ; switch(varValue.vt)case 1:scanf(%d,&varValue.u.iVal) ;printf(%dn,varValue.u.iVal);break;case 2:scanf(%f,&varValue.u.fVal); printf(%dn,varValue.u.fVal);break;case 3:scanf(%lf,&varValue.u.dVal); printf(%lfn,varValue.u.dVal);break;getch();结构体共用体(人民邮电管银枝主篇)8.5 枚举类型 任务提出:口袋中有红、黄、蓝、白、黑5种颜色的球若干。从口袋中取出3个球,问得到3种不同颜色的球的可能取法,打印出每种组合的3 种颜色。 任务分析: 设取出球为 i、j、k。它分别是5种色球之一,并要求ijk。用n累计得到不同色球的次数。用三重循环来实现:外循环使第一个球i从red变到black,第二层循环使第二个球j从red变到black,若i和j同色则不可取,只有i和j不同色(ij)时才需要继续找第三个球,此时内循环使第三个球k从red变到black,但也要求第三个球既不能和第一个球同色,也不能和第二个球同色,即ki且kj。如果满足以上条件就输出这种3色的组合方案,同时n加1。外循环执行完毕,全部方案也就输出完毕。最后输出总数n。结构体共用体(人民邮电管银枝主篇)main( )enum color /*定义一种枚举类型定义一种枚举类型 */ red,yellow,blue,white,blacki,j,k,pri; int n=0,loop;for(i=red;i=black;i+) for(j=red;j=black;j+) if(i!=j) for(k=red;k=black;k+) if(k!=i)&(k!=j) n=n+1; printf(%-4d,n); for(loop=1;loopsun) 枚举值的比较规则是按其在定义时的值进行比较。结构体共用体(人民邮电管银枝主篇)3、在循环中用枚举变量或数组元素控制循环在循环中用枚举变量或数组元素控制循环 如:enum color red,yellow,blue,white,blacki;int j=0;for(i=red;i=black;i+)j+;printf(j=%dn,j);则此程序段的结果为:j=5。结构体共用体(人民邮电管银枝主篇)例:例:使用枚举定义一年中的12个月,在输入月份数时显示对应月份的天数。(为方便起见,这里假设该年不是闫年)#include enum monthsJan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec;main() enum months month; int n;printf(请输入月份数:n);scanf(%d,&month); switch(month) case Jan: /*1,3,5,7,8,10,12月都是31天*/ case Mar: case May: case Jul: case Aug: case Oct: case Dec:n=31;break; case Feb:n=28;break; case Apr: case Jun: case Sep: case Nov:n=30;break; default:printf(输入数据有错n );printf( 月份与天数:n);printf(%d月共有%d天n,month,n); getch();结构体共用体(人民邮电管银枝主篇)例:例:输入两个整数,依次求出它们的和、差、积并输出结果。要求用枚举类型数据来处理和、差、积的判断。分析:分析:三种运算定义成枚举成员,定义方式如下:enum plus,minus,timesi; 在此基础上再定义两个整数,用x、 y表示,从键盘中输入两个整数后,进行和、差、积运算。完整的程序清单如下:完整的程序清单如下:结构体共用体(人民邮电管银枝主篇) main( ) enum plus,minus,timesi; int x,y; scanf(%d,%d,&x,&y); i=plus; while(i=times) switch(i+) case plus:printf(%d+%d=%dn,x,y,x+y);break; case minus:printf(%d-%d=%dn,x,y,x-y);break; case times:printf(%d*%d=%dn,x,y,x*y);break; getch(); 结构体共用体(人民邮电管银枝主篇)8.6 用typedef定义类型 在现实生活中,信息的概念可能是长度,数量和面积等。在C语言中,信息被抽象为int、float和double等基本数据类型。从基本数据类型名称上,不能够看出其所代表的物理属性,并且int、float和double为系统关键字,不可以修改。为了解决用户自定义数据类型名称的需求,C语言中引入类型重定义语句typedef,可以为数据类型定义新的类型名称,从而丰富数据类型所包含的属性信息。结构体共用体(人民邮电管银枝主篇)8.6.1 用用typedef定义类型的格式定义类型的格式用typedef定义类型的格式 typedef 原类型名 用户自定义类型名;其中,typedef为系统保留字,“原类型名”为已知数据类型名称,包括基本数据类型和用户自定义数据类型,“用户自定义类型名”是一标识符,为新的类型名称。例如:typedef double LENGTH;typedef unsigned int COUNT;定义新的类型名称之后,可像基本数据类型那样定义变量。例如: typedef unsigned int COUNT; unsigned int b; COUNT c;结构体共用体(人民邮电管银枝主篇)8.6.2 用用typedef定义类型的应用定义类型的应用 typedef 的主要应用有如下的几种形式:1、将基本数据类型定义新的类型名、将基本数据类型定义新的类型名 例如: typedef unsigned int COUNT; typedef double AREA; 此种应用的主要目的,首先是丰富数据类型中包含的属性信息,其次是为了系统移植的需要,稍后详细描述。2、 数组类型自定义数组类型自定义例如:typedef float Array10; /*将数组类型与数组变量分离开来*/Array a,b; /* 等同于定义:float a10,b10;*/int i;for(i=0;i10;i+) ai=i; bi=ai;结构体共用体(人民邮电管银枝主篇)3、将自定义数据类型(结构体、共用体和枚举类型等)定将自定义数据类型(结构体、共用体和枚举类型等)定义简洁的类型名称义简洁的类型名称例如:struct studentint num; char name20; char sex; float score;struct student stu1,stu2;其中结构体struct student为新的数据类型,在定义变量的时候均要有保留字struct,而不能像int和double那样直接使用student来定义变量。 结构体共用体(人民邮电管银枝主篇)如果经过如下的修改,typedef struct studentint num; char name20; char sex; float score;Pstu;则定义变量的方法可以简化为: Pstu stu1,stu2;为共用体类型定义简洁的类型名称的方法等同于结构体类型。同样,也可以为枚举类型定义简洁的类型名称,如: enum color /*定义一种枚举类型 */ red,yellow,blue,white,black;enum color i,j,k,pri;可改为:typedef enum color /*Pcol代替原枚举类型 */ red,yellow,blue,white,blackPcol;Pcol i,j,k,pri;结构体共用体(人民邮电管银枝主篇)4、为指针定义简洁的名称。为指针定义简洁的名称。首先为数据指针定义新的名称,例如 typedef char * STRING; /* 将指针类型与指针变量定义分开 */ STRING p1; /* 等同于char * p1; */ STRING p210; /* 等同于char * p210; */其次,可以为函数指针定义新的名称,例如 typedef int (*MyFUN)(int a,int b);其中MyFUN代表 int *XFunction(int a,intb)类型指针的新名称。例如 typedef int (*MyFUN)(int a,int b); int Max(int a,int b); MyFUN *pMyFun; pMyFun= Max;结构体共用体(人民邮电管银枝主篇)8.6.3 使用使用typedef定义类型注意的几个问题定义类型注意的几个问题在使用typedef时,应当注意如下的问题:1) typedef的目的是为已知数据类型增加一个新的名称。因此并没有引入新的数据类型。2) typedef 只适于类型名称定义,不适合变量的定义。3) typedef 与#define具有相似的之处,但是实质不同。#define AREA double 与 typedef double AREA 可以达到相同的效果。但是其实质不同, #define为预编译处理命令,主要定义常量,此常量可以为任何的字符及其组合,在编译之前,将此常量出现的所有位置,用其代表的字符或字符组合无条件的替换,然后进行编译。typedef是为已知数据类型增加一个新名称,其原理与使用int double等保留字一致。结构体共用体(人民邮电管银枝主篇)例:例:输出数据类型的存储长度#include void main() typedef struct int i; float f; stru; typedef union int i; float f; UNION; typedef enumSun,Mon,Tue,Wed,Thu,Fri,SatWEEK; printf(%d,%dn,sizeof(int),sizeof(float); printf(%d,%d,%dn,sizeof(stru),sizeof(UNION),sizeof(WEEK); getch(); 结构体共用体(人民邮电管银枝主篇)8.7 本章小结本章小结1、结构体和共用体是两种构造类型数据,是用户定义新数据类型的重要手段。结构体和共用体有很多的相似之处,它们都由成员组成。成员可以具有不同的数据类型。成员的表示方法相同。都可用三种方式作变量说明。2、在结构体中,各成员都占有自己的内存空间,它们是同时存在的。一个结构体类型的变量的总长度等于所有成员长度之和。在共用体中,所有成员不能同时占用它的内存空间,它们不能同时存在。共用体变量的长度等于最长的成员的长度。3、“.”是成员运算符,可用它表示成员项,成员还可用“-”运算符来表示。4、结构体类型的变量可以作为函数参数,函数也可返回指向结构体的指针变量。而共用体变量不能作为函数参数,函数也不能返回指向共用体类型的指针变量。但可以使用指向共用体变量的指针。5、结构体和共用体的定义允许嵌套,结构体中可以用共用体作为成员,共用体中也可以用结构体作为成员,形成结构体和共用体的嵌套。6、枚举类型是一种用户自定义的基本数据类型。枚举变量的取值是有限的,枚举元素是常量,不是变量。7.枚举变量通常由赋值语句赋值,而不是动态输入赋值。枚举元素虽可由系统或用户定义一个顺序值,但枚举元素和整数并不相同,它们属于不同的类型。因此,也不能用printf语句来输出元素值(可输出顺序值)。8、使用typedef进行自定义类型说明,其目的是使程序书写简单,提高可读性。结构体共用体(人民邮电管银枝主篇)结构体共用体(人民邮电管银枝主篇)
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号