第7章结构.

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

第7章结构结构是一个或多个变量的集合,这些变量可以属于不同的类型,为了便于处理而组织在一个名字之下。结构通常被用来组织复杂的数据,特别是在大型程序中。本章主要介绍结构类型的声明、结构变量的定义与使用、结构数组、指向结构的指针、自引用结构、单链表操作等,还简要介绍了联合类型、枚举类型、位字段等内容。结构类型的声明结构将同一数据对象的各相关成员(或属性)组织成一个整体,便于数据的表示和处理。如:structdate{intyear;intmonth;intday;};其中struct用于引入结构声明,它由包含在花括号之内的一系列成员说明组成,注意右花括号后的分号不能省。struct后跟的名字是可选的,它是结构类型的标记。在结构类型中命名的变量(如year等)为结构的成员。已定义的结构定义新的结构类型定义结构类型structdate后,可以像使用基本类型一样来使用它,如定义该类型的变量、数组、指针等,还可以利用它来定义新的结构类型。如:structstudent_type{intnum;charname[20];charsex;structdatebirthday;intscore;};结构类型是用户自定义的,它是固定数目的成员变量组成的整体。结构变量的定义与使用定义结构变量可在结构类型声明中定义,在结构成员结束的右花括号之后,可跟随变量表。如:structpoint{intx;inty;}p1;可以在结构声明结束后单独定义,如:structpointp1,p2;结构变量可在定义时进行初始化,如:structdatetoday={2009,11,29};使用结构变量使用结构变量时,除了同类型的结构变量相互赋值以外,一般对结构变量的使用都是通过结构变量的成员来实现的。成员变量的引用是通过结构成员运算符”.”来进行,如:today.yearp1.x应特别注意的是,结构变量与成员之间只能包括成员运算符”.”。使用结构变量若结构的成员也是结构变量,则仍可以利用结构成员运算符对它的成员进行访问,如:structstudent_types1={1,zhang,'m',{1992,3,25},90};printf(%d\n,s1.birthday.year);对结构变量的成员可象普通变量一样进行各种运算。如:s1.num++。结构成员运算符”.”运算符优先级比”++”运算符高,因此是对s1.num自增。例7.1结构类型声明、变量定义与使用程序的运行结果为:1zhangsan11-3090#includestdio.hintmain(void){structdate{intyear;intmonth;intday;};structstudent_type{intnum;charname[20];charsex;structdatebirthday;intscore;};structdatetoday={1990,11,30};structstudent_types1={1,zhangsan,'m',today,90};printf(%d\n,s1.num);printf(%s\n,s1.name);printf(%d-%d\n,s1.birthday.month,s1.birthday.day);printf(%d\n,s1.score);return0;}思考题结构的作用是什么?结构类型与变量的区别是什么?结构类型的成员的类型可否是结构类型?结构数组声明了结构类型后,就可定义该结构类型的数组,也可以在定义数组的同时对数组元素进行初始化。通过下面的程序来说明结构数组的定义、初始化和使用方法,这个程序的功能是选举计票程序,输入每张选票中候选人的名字,统计并输出各候选人的得票数。例7.2选票统计structperson{char*name;intcount;}candidates[3]={//定义候选人数组并初始化{zhangsan,0},{lisi,0},{wangwu,0}};intmain(void){inti;charname[20];printf(namename(nonameend):);gets(name);//输入得票的候选人姓名后回车,直接回车结束while(strlen(name)0){for(i=0;i3;i++)if(strcmp(name,candidates[i].name)==0){candidates[i].count++;//该候选人票数增1break;}printf(namename(nonameend):);gets(name);//输入得票的候选人姓名后回车,直接回车结束}for(i=0;i3;i++)//输出选举结果printf(%s:%d\n,candidates[i].name,candidates[i].count);return0;}程序说明候选人结构类型structperson,其中包含成员姓名name为指向字符的指针,另一个成员为count用来统计得票数。主函数中用gets输入一个得票人的姓名,姓名中可包含空格,输入后按回车,若直接按回车表示选票录入完毕。两个字符串比较的标准函数是strcmp,不能用相等运算符”==”。思考题对于例7.2,思考下列问题:候选人结构类型的name用指向字符的指针,是否可以将其改为字符数组。程序中将候选人数组定义为外部数组,是否可以将它定义在main函数中。标准函数gets、strlen、strcmp的功能是什么,输入函数gets是否可用scanf函数替换。该程序所采用的查找算法为顺序查找,是否可以或有必要改为折半查找。该程序中,计票、输出都在main函数中完成,是否可以将它们改为两个独立的函数实现。指向结构的指针指向结构类型的指针变量指向同类型的结构变量。如:structponit{intx;inty;}p1={1,1},*pp=&p1;可用pp来间接访问结构变量p1的成员了,如p1.x用pp间接访问就是(*pp).x,注意其中的圆括号不能省。用pp间接访问还有一种形式:pp-x,它表示pp所指向对象的x成员,与(*pp).x等价,这种形式较(*pp).x更简洁。例7.3指向结构变量的指针的使用程序的运行结果为:4428816#includestdio.hintmain(void){structponit{intx;inty;}p1={4,2},*pp=&p1;printf(%d%d%d\n,p1.x,(*pp).x,pp-y);pp-x*=pp-y;pp-y*=pp-x;printf(%d%d%d\n,p1.x,(*pp).x,pp-y);return0;}指向结构数组的指针指向结构的指针变量不仅可指向一个单独的结构变量,也可以指向结构数组中的元素,可以通过指向结构的指针变量来访问结构数组中的元素。例7.4用指向结构的指针访问结构数组元素程序清单#includestdio.hintmain(void){structstudent{charname[20];intscore[2];};structstudentstu[3]={//分行初始化{Zhangsan,{78,88}},{Lisi,{58,89}},{Wangwu,{68,96}}};structstudent*p;for(p=stu;pstu+3;p++)printf(%s:(%d,%d)\n,p-name,p-score[0],p-score[1]);return0;}程序的运行结果为:Zhangsan:(78,88)Lisi:(58,89)Wangwu:(68,96)程序说明上面的程序首先声明了结构类型structstudent,其中包括学生姓名成员name和包括两门课的成绩的数组成员score。然后定义了该类型的数组stu,并进行了初始化。最后定义了指向结构的指针p,用来指向stu的各元素,循环3次,输出各数组元素的成员。请思考若在数组stu定义时,不初始化,改用键盘输入各数组元素的值,程序该如何修改。指向结构的指针作函数参数指向结构的指针可以作为函数的参数,这是在函数之间传递结构变量的地址,比直接传递结构变量代价小得多,特别是当结构变量占用的空间较大时。下面的程序说明了指向结构的指针作为函数参数的使用方法,还与结构变量作为函数的参数进行了比较,一般情况下,使用指向结构的指向作为函数的参数更好。例7.5向结构的指向作为函数的参数#includestdio.hstructpoint{intx;inty;};voidadd(structpoint*pp,structpointp2){pp-x=pp-x+p2.x;//各成员分别相加pp-y=pp-y+p2.y;}voidprint(structpoint*pp){printf((%d,%d)\n,pp-x,pp-y);}intmain(void){structpointp1={2,4},p2={3,6};add(&p1,p2);print(&p1);print(&p2);printf(%d,%d\n,sizeofp1,sizeof&p1);printf(%d,%d\n,sizeof(structpoint),sizeof(structpoint*));return0;}程序说明程序首先在所有函数之外声明了结构类型structpoint。然后定义了函数add和print,其中add函数用来实现两个点相加。print函数用来输出结构变量的两个成员的值。sizeof运算符是求变量和类型所占字节数,在求类型占用的字节数时,必须加一对圆括号。思考题:(*pp).x与*pp.x有何不同?(*pp).x与pp-x有何不同?在例7.5中,函数add和print是否必须用指向结构的指针变量,是否都可以改用结构变量或结构指针变量。自引用结构结构类型中包含指向该类型的指针成员时,称该类型为自引用结构。如:structnode{intdata;structnode*next;//next是指向structnode的指针变量};自引用结构类型中包含一个或多个指向该类型的指针成员,这种类型可以用来创建复杂的数据结构。单链表当自引用结构类型中包含一个指向该类型的指针成员时,可用来构建称为单链表的数据结构。单链表可用于组织同类型的多个数据元素,这些元素在逻辑上是一个接一个的排列(每个元素的前一个元素称为其前驱,它的后一个元素称为后继。)。单链表是一种动态的数据结构,元素个数可以动态改变,但相邻元素之间不必顺序存放,它们的逻辑前后关系可通过在前一个元素中存放下一个元素的地址来实现。单链表(续)单链表中的元素只能顺序访问,只要知道第一个元素(称为表头)的地址(头指针,通常用head表示),则可以依次访问单链表中的每一个元素。单链表的最后一个元素(称为表尾)没有后继,它的指针域的值为空。在C语言中,空指针通常为符号常量NULL表示。内存动态分配与释放的标准函数C语言提供了一些管理内存动态分配与释放的标准函数,包含在stdlib.h中。最常用的两个函数为:内存空间分配函数mallocvoid*malloc(intsize);其功能是向系统申请分配指定size个字节的内存空间,并返回该区域的首地址,由于void*表示空类型的指针。释放内存空间函数freevoidfree(void*ptr);该函数的功能是释放ptr所指向的一块内存空间,ptr是一个任意类型的指针变量,它指向被释放区域的首地址,被释放空间应是已分配的区域。单链表的创建、插入、删除、输出函数createLinkList用于创建单链表,将先输入的元素作为表头,以后每输入一个元素,则插入到表尾,单链表中的元素顺序与输入顺序相同。函数InsertLinkList用于在按递增顺序组织的单链表中插入一个数据,使单链表仍然按递增顺序存放。函

1 / 55
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功