c语言程序设计与项目实践第10章_第1页
c语言程序设计与项目实践第10章_第2页
c语言程序设计与项目实践第10章_第3页
c语言程序设计与项目实践第10章_第4页
c语言程序设计与项目实践第10章_第5页
已阅读5页,还剩31页未读 继续免费阅读

下载本文档

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

文档简介

1、第10章 结构体与共用体 本章的学习重点结构体的定义结构体变量的使用结构体指针的定义和使用结构体的内存结构结构体指针作函数参数的使用共用体的定义共用体的内存结构 10.1 结构体的定义 结构体(struct)是由一系列相同或不同数据类型构成的数据结构,也简称为结构。C语言中,可以按照程序设计需求定义结构体类型,将多个相关的变量封装起来,成为一个有机的整体,这样的结构就是结构体。例如,要存储一个班级的信息,包括班号、男生人数、女生人数和班主任姓名等,可以将这些信息封装成下面的格式:班号班主任姓名男生人数女生人数C语言规定了使用结构体封装其他数据类型的方式,并且可以对这些封装命名。结构体使用str

2、uct来定义其类型,例如,上述班级信息使用结构体定义为:struct ClassInfoint ClassNumber;/成员1,定义班号char ClassAdministratorName30;/成员2,定义班主任姓名int MaleNumber;/成员3,定义男生人数int FamaleNumber;/成员4,定义女生人数;10.1 结构体的定义 C语言中,结构体定义的一般形式为:struct 结构体名 成员表列;成员的一般表达形式为:类型说明符 成员名;其中成员名属于用户自定义标识符,同样遵循用户自定义标识符的命名规则。范例10.1 PeopleIDcardInfo.c 身份证上通常包

3、括身份证持有人的姓名、性别、出生日期、籍贯等,使用C语言表示时,这些信息的格式各不相同。设计一个结构体,存储身份证信息。 10.2 结构体变量 结构体是一种构造数据类型,C语言使用结构体变量来对结构体成员进行引用。定义结构体变量不同于基本数据类型的定方式,它需要先定义结构体类型,然后定义结构体变量,或者定义结构体类型的同时定义结构体变量。 10.2.1 结构体变量的定义 结构体变量有两种定义形式:一种是定义结构体类型时定义结构体变量,另一种是先定义结构体,然后定义结构体变量。结构体变量的一般定义形式为:struct 结构体名成员表列;变量名1,变量名2;或者省略结构体名,直接定义结构体变量:s

4、truct 成员表列;变量名1,变量名2;10.2.1 结构体变量的定义 另外,也可以先定义结构体类型,再定义结构体变量:struct 结构体名成员表列;struct 结构体名 变量名1,变量名2;例如,记录某次数学考试时学生张三的成绩,可以使用下面的结构体:struct MathScorechar name30; /成员1,定义姓名,char型数组namechar sex10; /成员2,定义性别,char型数组sexfloat score; /成员3,定义分数,float型变量score;struct MathScore Zhangsan;/定义结构体变量Zhangsan 10.2.2 结

5、构体变量的初始化 1结构体变量定义赋初值结构体变量可以在定义时赋初值,例如:01struct MathScore0203char name30;04char sex10;05float score;06Student1 = “Zhangsan”, “Male”, 92;上述程序代码定义了结构体类型MathScore,同时定义了该类型的变量Student1,并赋初值,将字符串”Zhangsan”赋给成员name,将”Male”赋给成员sex,将数字92赋给成员score。注意,赋值时各成员的值应一一对应,假如代码第6行改为:Student = “Male”, ”Zhangsan”, 92;则程序

6、将字符串“Male”赋给成员name,将字符串”Zhangsan”赋给成员sex,将数字92赋给成员score。 10.2.2 结构体变量的初始化 2结构体变量成员赋初值结构体变量定义后,不能使用一次赋值的方式对结构体变量各个成员赋值,只能对每个成员单独赋值。此时需要使用结构体成员引用运算符”.”,即通过点号索引结构体变量下面的各个成员。例如:01struct MathScore0203char name30;04char sex10;05float score;06Student1;07S = “Zhangsan”;/对结构体变量Student1的成员name赋初值0

7、8Student1.sex = .“Male”; /对结构体变量Student1的成员sex赋初值09Student1.score = 92; /对结构体变量Student1的成员score赋初值 10.2.2 结构体变量的初始化 3结构体变量间的赋值若定义两个类型完全相同的结构体变量,当其中一个变量赋初值后,可以将已赋值的变量整体赋值给另一个变量。例如:01struct MathScore0203char name30;/成员1,定义姓名,char型数组name04char sex10; /成员2,定义性别,char型数组sex05float score; /成员3,定义分数,float型变

8、量score06Student1 = “Zhangsan”, “Male”, 92, StudentCopy;这里定义了两个MathScore类型的结构体变量Student1和StudentCopy,可以执行如下定义:StudentCopy = Student1;单当两个结构体变量类型不一致时,不能使用这种变量赋值的操作方式。 10.2.3 结构体变量的引用 结构体定义以后,在程序中通常不能对结构体作为整体来操作,而只能通过引用结构体的各个成员来实现对结构体的使用。C语言中,结构体变量定义以后可以通过结构体成员引用运算符”.”索引结构体内所有的成员。例如,某结构体IDcard中含有name、s

9、ex和Tel等成员。若定义了该结构体类型的变量:struct IDcard YanSl, Zhangyc;则这两个结构体变量可以通过结构体成员引用运算符引用每个成员:YanS = “Yan Shulei”;/为YanSl变量成员name赋值YanSl.sex = “Male”/为YanSl变量成员sex赋值Zhangyc.Tel = 123456;/为Zhangyc变量成员Tel赋值 范例10.2 BookInfo.c 书店管理图书时需要将每本图书的信息输入到书库中,包括书名、定价和作者等。设计一个结构体,将一本名为C language Study的书的信息存储为结构体,作者为Wa

10、rd.Harfman,定价为80.65元。 10.2.4 结构体数组 1结构体数组的定义和结构体变量类似,结构体数组可以在结构体类型定义时定义,也可以在结构体类型定义完毕后单独定义。例如,范例10.2中书籍的信息,可以再添加几个成员如出版社、ISDN号以及书籍类型等。定义如下:01struct BookInfo0203char Name30;04char Author20;05float PublishedPrice;06char Publisher30;07float ISDN;08char Category30;09Book100;10.2.4 结构体数组 2结构体数组赋初值结构体数组可以

11、在定义时赋初值,例如,存储5个学生的某次数学成绩,可以使用下面的定义:01struct Stu_math_Score0203char Name30;04char Sex;05int StuNo;06float Score;07StuInfo5 = 08“Zhangsan”, M, 1001, 86.5, 09 “Lijuan” , F, 1002, 95,10 “Wangjun”, M, 1003, 88.5,11 “Wangyi”, F, 1004, 92,12 “Chenli”, F, 1005, 94.513 ;实训10.1身份证信息录入 每个人都有自己的身份证,身份证信息记录了个人基本

12、的社会信息,包括姓名、性别、民族、出生日期、住址和身份证号码。设计一个数据库,存储20个人的身份证信息。并输出所有男性的身份信息。1需求分析:需求1:设计一个结构体类型,用于存储身份证信息需求2:输入20个人的身份信息,并输出男性信息2技术应用对于需求1,定义结构体IdentificationCard,成员变量有Name、Sex、Nationality、Birth_year、Birth_month、Birth_day、Addr和IDNo等,根据不同成员的功能设置为不同的数据类型。例如设置Sex为char型的数组。对于需求2,定义结构体类型为IdentificationCard的结构体数组Peo

13、pleInfo20,用于存储20个人的身份信息。设计子函数void OutputMale(struct IdentificationCard PeopleInfoType20),输出男性的信息。源代码:PeopleIDInfo.c 10.2.5 结构体的嵌套 1结构体嵌套的定义结构体嵌套的定义类似于函数的嵌套,应先将内层的结构体定义在前面。例如,在作个人身份信息的定义时,需要定义人员的出生日期,为了详细的表示人员的出生年月日,可以定义结构体BirthDay:01struct BirthDay/定义出生日期结构体BrithDay0203unsigned int year; /定义成员变量year

14、,表示年份04unsigned int month; /定义成员变量month,表示月份05unsigned int day; /定义成员变量day,表示日期06;对出生年月日重新定义,作为成员放在下面结构体中:01struct IdentificationCard0203char Name30;04char Sex10;05char Nationality20;06struct BrithDay Birth;/定义结构体成员Birth07char Addr80;08char IDNo20;09Zhangsan; 10.2.5 结构体的嵌套 2结构体嵌套的变量引用结构体嵌套定义之后,可以使用结

15、构体引用运算符进行两次或多次引用。例如,上述代码第9行同时定义了结构体变量Zhangsan,该变量的Birth成员可以这样引用:Zhangsan.Birth.year = 1984;/引用成员yearZhangsan.Birth.month = 11;/引用成员monthZhangsan.Birth.day = 23/引用成员day10.3 结构体指针 C语言中,可以定义结构体变量,也可以定义结构体类型的指针。当指针变量指向一个结构体变量时,就将这个指针变量称为结构体指针变量,简称结构体指针,此时,结构体指针变量的值是它所指向的结构体变量的首地址。此外,结构体指针也常用于建立链表,用于作链表的

16、连接端点。 10.3.1 结构体指针的定义 和普通指针变量类似,结构体指针的定义也使用*作为指针定义的运算符,其一般表达形式为: struct 结构体类型名 *结构体指针变量名 可以定义下面的结构体指针: struct BookInfo *pC_language_Study; 假如要使该结构体指针指向某个结构体变量,可以使用下面的赋值语句:pC_language_Study = &C_language_Study;另外,和定义结构体变量类似,在定义结构体类型时也可以定义结构体指针。例如,要保存一个人的体检结果,可以定义如下结构体类型、结构体变量和结构体指针:01struct PhysicalE

17、xamInfo0203char Name30; /定义成员变量Name,表示姓名04float Height; /定义成员变量Height,表示身高05float Weight; /定义成员变量Weight,表示体重06float BloodPressure; /定义成员变量BloodPressure,表示血压07float Eyesight; /定义成员变量Eyesight,表示视力08Stu1, Stu2, *pStu; /定义结构体变量Stu1, Stu2和结构体指针pStu09struct PhysicalExamInfo pStu = &Stu1; /使结构体指针pStu指向结构体变

18、量Stu1 10.3.2 结构体指针引用结构体成员 使用结构体指针可以引用它所指的结构体变量的每一个成员。和结构体变量引用结构体成员不同,结构体指针引用各个成员时使-运算符,C语言中,该运算符由减号和右尖括号组合而成。例如,10.3.1节中定义的结构体指针pStu可以使用下面的方法引用结构体变量Stu1的各成员变量:pStu-Height = 185;/使用结构体指针引用Stu1的成员Height,并赋值185pStu-Weight = 72; /使用结构体指针引用Stu1的成员Weight,并赋值72printf(“Name: %sn”, pStu-Name); /输出结构体变量Stu1的成

19、员Name 范例10.3 StuSchoolInfo.c 设计一个结构体,存储某个学生的主要学籍信息,包括姓名、性别、班号和学号等,使用结构体指针实现对结构体变量成员的输入和输出。 10.3.3 指向结构体数组的结构体指针 结构体指针也可以指向一个已定义的结构体数组,结构体指针可以指向结构体数组的首地址,也可以指向结构体数组的某个元素地址。可以通过结构体指针值的递增和递减改变其所指的元素,例如,定义了一个通讯录结构体:01struct AddrBook0203char Name30;04char MobilePhone20;05char Addr50;06unsigned int ZipCod

20、e;07;08struct AddrBook Friends20, Family30, SchoolMates30;09struct AddrBook *pAddrBook;上述代码中第8行定义了三个AddrBook类型的结构体数组Friends、Family和SchoolMates,维数分别为20、30和30。可以使用下面的代码通过指针pAddrBook索引各个结构体数组元素的成员:01pAddrBook = Friends;/将pAddrBook指向结构体数组Friends首地址02scanf(“%s”, pAddrBook-Name);03scanf(“%s”, pAddrBook-Mo

21、bilePhone);04scanf(“%s”, pAddrBook-Addr);05scanf(“%u”, pAddrBook-ZipCode);06pAddrBook+;/使指针pAddrBook指向第二个结构体数组元素07scanf(“%s”, pAddrBook-MobilePhone);mnpAddrBook = &Family10;/使指针pAddrBook指向结构体数组Family的第11个元素mn+1scanf(“%s”, pAddrBook-Name); 10.4 结构体变量的内存分配 由于结构体类型是构造类型,其内部各个成员可以是各种数据类型结构,因此,结构体变量或结构体数

22、组在内存中的存储结构也和普通数据类型不同。与普通数据类型相比,结构体在内存中的逻辑结构更复杂,占用内存也更多。 10.4.1 动态分配结构体内存 分配内存空间可以使用malloc函数,也可以使用另一个内存分配库函数calloc。1malloc分配动态内存使用malloc函数分配结构体类型的动态内存空间,可以借助sizeof运算符计算结构体的内存字节数,然后按需要分配内存块。例如,设计一个简单的机动车驾驶证模版,包括注册号(RegisterCode)、车种(Sedan)、持有人(Owner)和引擎号(EngineCode)等,可以使用下面的结构体:01struct TheLicenseOfMot

23、orVehiclesOfPRC0203char RegisterCode20;04char Type20;05char Owner30;06char EngineCode20;07;定义结构体类型后,可以使用sizeof运算符获取该结构体类型所占的内存字节大小,表达方式为:int i = 0;i = sizeof(struct TheLicenseOfMotorVehiclesOfPRC);10.4.1 动态分配结构体内存 上述两条语句表示计算结构体类型TheLicenseOfMotorVehiclesOfPRC在内存中的字节大小,并将结果赋给int型变量i。使用malloc函数可以分配需要的

24、内存空间,表达方式为:struct TheLicenseOfMotorVehiclesOfPRC *pMotorVehicles;pMotorVehicles = (struct TheLicenseOfMotorVehiclesOfPRC *)malloc(i * 100);上述第一行代码表示定义了一TheLicenseOfMotorVehiclesOfPRC结构体类型的指针变量pMotorVehicles,第二行代码表示分配了100个结构体类型的连续内存区域。范例10.4 CarInfo.c 汽车销售系统中通常有一个简单的汽车搜索界面,包括车型、车名、车牌号、排量和价格等。设计一个简单的结

25、构体模版,用于汽车销售系统的搜索界面数据库。动态分配一定的内存空间,存储已有的各种类型的汽车信息。 10.4.1 动态分配结构体内存 2calloc分配动态内存calloc函数也用于分配内存空间。其一般调用形式为:(类型说明符 *)calloc(n,size)calloc函数使用两个参数表示分配的内存空间大小。两个参数n和size的作用是在内存动态存储区中分配n块长度为size字节的连续存储区域。函数的返回值为该区域的首地址。(类型说明符*)用于强制类型转换。例如,定义了通讯录结构体模版和相对应的结构体指针:01struct AddrBook0203char Name30;04char Mob

26、ilePhone20;05char Addr50;06unsigned int ZipCode;07;08struct AddrBook *pAddrBook;可以使用calloc函数分配100个AddrBook结构体类型的内存区域,并将该内存区域的首地址赋给指针pAddrBook,执行方法为:pAddrBook = (struct AddrBook *)calloc(100, sizeof(struct AddrBook);10.4.2 结构体在内存中的存储结构 1结构体首地址选择结构体变量的首地址必须能够被其最宽的基本数据类型成员的大小所整除。例如,定义如下结构体:struct Test1

27、char c;int i;struct Test1 ForTest;运行语句:printf(“%dn”, sizeof(ForTest);输出结果为8,这是因为系统需要作字节对齐。结构体Test1最宽的成员为长度为4字节的int型变量i,因此,结构体变量ForTest的首地址要能够被4整除,而变量i的地址也要被4整除,因此,为了满足这些需求,要在char型变量c和int型变量i之间加入填充字节。如图所示为结构体Test1的内存结构示意图。 10.4.2 结构体在内存中的存储结构 2结构体成员地址结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,当不满足这一要求时将在

28、成员之间加上填充字节。3结构体总字节数结构体的总字节数等于结构体最宽基本类型成员大小的整数倍。当不满足这一要求时,将在最后一个成员后面添加填充字节。4嵌套结构体类型当有嵌套结构体类型时,内部的嵌套结构体类型以其最大基本数据类型成员的大小为准。例如,定义一个人员基本信息的结构体:01struct BirthDay0203int year;04short month;05short day;06;07struct PeopleInfo0809char Name20;10char Sex;11struct BirthDay birth;12;13struct PeopleInfo Lihong;10

29、.4.2 结构体在内存中的存储结构 上述定义执行语句:printf(“%dn”, sizeof(PeopleInfo);输出结果为32,上述定义中,由于PeopleInfo结构体类型中最大的成员宽度为struct BirthDay birth,其长度按照内部最大的基本数据类型int year计算,为4,因此,struct BirthDay birth成员前面的所有成员地址应该能够被4整除。因此,成员Sex后应该有3个填充字节。如图所示为结构体类型PeopleInfo的内存结构示意图。 10.5 结构体指针作函数参数 结构体变量和结构体指针都可以作为函数参数进行传递。但使用结构体变量作函数传递时

30、,需要传送结构体中的每个成员,当结构体成员比较多时,将给程序带来很大不便。可以使用结构体指针或结构体名实现结构体变量向子函数的传递,这样传递到子函数形参的仅仅是内存的地址,因此可以大大减少程序执行时时间和空间的开销。 10.5.1 结构体指针作函数参数的定义 子函数定义时形参的类型应与传入的实参类型相同。1结构体数组名作函数参数当使用结构体数组名作函数参数时,形参可以使用结构体数组,也可以使用结构体指针类型。例如,定义结构体:01struct Test0203short Input;04int Output;05ForTest10;可以定义下面的函数将结构体数组ForTest的首地址传入函数体

31、:void TestStr(struct Test VisualArray10) 函数体可以通过下面的语句调用该子函数,并将结构体数组ForTest首地址传递给形参:TestStr ( ForTest );这样定义的缺点是形参struct Test VisualArray10中数组名VisualArray不能作为指针使用,由于数组名是地址常量,因此不能对自身做算术运算。优点是可以通过形参数组常量表达式的大小,明确限定所要处理的实参传入的内存块的大小。 10.5.1 结构体指针作函数参数的定义 2结构体变量作函数参数在上述结构体Test定义的基础上,定义:struct Test *pForTes

32、t; /定义结构体指针pForTestpForTest = (struct Test *)malloc(100 * sizeof(struct Test);/分配100个Test结构体类型的内存若定义子函数:void TestStr2(struct Test *pVisualTest)函数体此时可以调用子函数TestStr2,并将动态分配的内存区域首地址传递给形参:TestStr2 ( pForTest ); 10.5.2 结构体指针作函数参数的应用 实际程序设计中结构体指针作函数参数应用非常广泛,通常对数据库的遍历、计算等均可以通过结构体指针实现。范例10.5 CalcAverageAge.

33、c 有一个工作小组,为更好的掌握小组中各成员的工作能力,需要统计该组人员中男性和女性的平均年龄。试设计一个子函数,实现这一功能,分别打印出男性和女性的平均年龄。 10.6 共用体的定义 C语言中另外一种常用的构造类型是共用体,和结构体类似,共用体也由其他基本数据结构组合而成,但在内存结构中结构体和共用体却有本质区别。 10.6.1 共用体的定义C语言中,共用体使用关键字union定义,其定义的一般表达形式为:union 共用体名成员表列;其中,共用体名属于用户自定义标识符,遵循用户自定义标识符的命名规则。成员表列中可以包含一个或多个共用体成员。共用体成员的一般表达形式为:类型说明符 成员名;成员名的命名应符合标识符的规定。例如,有如下的共用体定义:01union data0203int temp;04char stable10;05;上述代码定义了一个名为data的共用体类型,它含有两个成员,一个为整型,成员名为temp;另一个为字符数组,数组名为stable。和结构体类似,共用体定义之后,就可以定义该类型的共用体变量。 10.6.2 共用体变量的定义与应用 共用体变量的定义和结构体类似,可

温馨提示

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

评论

0/150

提交评论