第11章 结构与共用体_第1页
第11章 结构与共用体_第2页
第11章 结构与共用体_第3页
第11章 结构与共用体_第4页
第11章 结构与共用体_第5页
已阅读5页,还剩36页未读 继续免费阅读

下载本文档

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

文档简介

1、结构类型与结构变量的定义结构类型与结构变量的定义结构变量的引用与初始化结构变量的引用与初始化结构数组结构数组指向结构类型数据的指针指向结构类型数据的指针链表处理链表处理结构指针的应用结构指针的应用共用型和枚举型共用型和枚举型定义已有类型的别名定义已有类型的别名结构类型定义结构类型定义struct 结构类型名结构类型名 数据类型数据类型 数据项数据项1; 数据类型数据类型 数据项数据项2; 数据类型数据类型 数据项数据项; ;例: 定义一个反映学生基本情况的结构类型,用以存储学生的相关信息。struct date /*日期结构类型日期结构类型*/ int year; int month; int

2、 day; ;struct std_info /*学生信息结构类型学生信息结构类型*/ char no7; char name9; char sex2; struct date birthday; ; struct score /*成绩结构类型成绩结构类型*/ char no7; int score1; int score2; int score3; ; “结构类型名结构类型名”和和“数据项数据项”的命名规则,与变量名相同。的命名规则,与变量名相同。数据类型相同的数据项,既可逐个、逐行分别定义,也可合数据类型相同的数据项,既可逐个、逐行分别定义,也可合并成一行定义。并成一行定义。例如,本案例代

3、码中的日期结构类型,也可改为如下形式:例如,本案例代码中的日期结构类型,也可改为如下形式: struct date int year, month, day; ;结构类型中的数据项,既可以是基本数据类型,也允许是另结构类型中的数据项,既可以是基本数据类型,也允许是另一个已经定义的结构类型。一个已经定义的结构类型。 例如,本案例中的结构类型例如,本案例中的结构类型std_info,其数据项,其数据项“birthday”就是一个已经定义的日期结构类型就是一个已经定义的日期结构类型date。将个数据项称为结构类型的个成员(或分量)。将个数据项称为结构类型的个成员(或分量)。间接定义法间接定义法 :先

4、定义结构类型、再定义结构变量:先定义结构类型、再定义结构变量 struct std_info /*学生信息结构类型学生信息结构类型*/ char no7; char name9; char sex2; struct date birthday; ; struct std_info student;student拥有结构类型的全部成员,其中拥有结构类型的全部成员,其中birthday成成员是一个结构类型(日期),它由员是一个结构类型(日期),它由3个成员构成。个成员构成。使用间接定义法定义结构变量时,必须同时指定结使用间接定义法定义结构变量时,必须同时指定结构类型名构类型名直接定义法直接定义法:

5、定义结构类型的同时,定义结构变量定义结构类型的同时,定义结构变量一般格式:一般格式: struct 结构类型名结构类型名 结构变量表;结构变量表;struct std_info /*学生信息结构类型学生信息结构类型*/ char no7; char name9; char sex2; struct date birthday; student; 结构类型与结构变量是两个不同的概念结构类型与结构变量是两个不同的概念成员名可以与程序中的变量同名,代表不同的对象成员名可以与程序中的变量同名,代表不同的对象例:例: 利用定义的结构类型利用定义的结构类型struct std_info,定义一个结构变量,

6、定义一个结构变量student,存储和显示一个学生的基本情况。,存储和显示一个学生的基本情况。#includestruct.h/*定义并初始化一个外部结构变量定义并初始化一个外部结构变量student */struct std_info student=000102,“angel,“f,1980,9,20;void main() printf(No: %sn,student.no); printf(Name: %sn,); printf(Sex: %sn,student.sex); printf(Birthday: %d-%d-%dn,student.birthday.

7、year, student.birthday.month, student.birthday.day);/struct.h文件文件struct date int year; int month; int day; ;struct std_info char no7; char name9; char sex2; struct date birthday; ; 通过成员运算符通过成员运算符“.”,逐个访问其成员,格式:,逐个访问其成员,格式:结构变量结构变量.成员成员 /*其中其中“.”是成员运算符是成员运算符*/例如,例如,student.no;如果某成员本身又是一个结

8、构类型,则通过多级的分量运算,如果某成员本身又是一个结构类型,则通过多级的分量运算,对最低一级的成员进行引用对最低一级的成员进行引用引用格式扩展为:引用格式扩展为:结构变量结构变量.成员成员.子成员子成员.最低一级子成员最低一级子成员student.birthday.yearstudent.birthday.monthStudent.birthday.day对最低一级成员,可像同类型的普通变量一样,进行相应的对最低一级成员,可像同类型的普通变量一样,进行相应的各种运算。各种运算。既可引用结构变量成员的地址,也可引用结构变量的地址。既可引用结构变量成员的地址,也可引用结构变量的地址。如:如:&a

9、mp; ,&student初始化的格式,与一维数组相似:初始化的格式,与一维数组相似: 结构变量结构变量=初值表初值表如果某成员本身又是结构类型,则该成员的初值为如果某成员本身又是结构类型,则该成员的初值为一个初值表一个初值表例如:例如:student=000102, “angel, “f, 1980,9,20。初值的数据类型,应与结构变量中相应成员所要求初值的数据类型,应与结构变量中相应成员所要求的一致,否则会出错。的一致,否则会出错。 结构数组的定义也分直接定义和间接定义两种结构数组的定义也分直接定义和间接定义两种 结构数组也可在定义时初始化结构数组也可在定

10、义时初始化 格式为:格式为:结构数组结构数组n初值表初值表1,初值表初值表2,.,初值表初值表n#includestruct.h/*定义并初始化一个外部结构数组定义并初始化一个外部结构数组student3 */struct std_info student3= “000102”,“john”,“m”,1980,9,20, “000105”,“apple”,“f”,1980,8,15, “000112”,“kitty”,“f”,1980,3,10 ;Void main() int i; printf(No. Name Sex Birthdayn); /*输出三个学生的基本情况输出三个学生的基本情

11、况*/ for(i=0; ino); printf(Name: %sn, p-name); printf(Sex: %sn, p-sex); printf(Birthday: %d-%d-%dn, p-birthday.year, p-birthday.month, p-birthday.day); 通过指向结构变量的指针来访问结构变量的成员,与通过指向结构变量的指针来访问结构变量的成员,与直接使用结构变量的效果一样。直接使用结构变量的效果一样。如果指针变量如果指针变量pointer已指向结构变量已指向结构变量a,则以下三种,则以下三种形式等价:形式等价:a.成员成员 /a只能是结构变量只能是

12、结构变量pointer-成员成员 /p必须是指向结构变量或结构数组的必须是指向结构变量或结构数组的指针指针(*pointer).成员成员 例例: 使用指向结构数组的指针来访问结构数组。使用指向结构数组的指针来访问结构数组。#includestruct.h/*定义并初始化一个外部结构数组定义并初始化一个外部结构数组student */struct std_info student3=000102,“john,“m,1980,5,20, 000105,“apple,“f,1980,8,15, “000112”,“kitty”,“f”,1980,3,10 ;Void main() struct st

13、d_info *p=student; int i=0; printf(No. Name Sex Birthdayn);for( ; ino, p-name, p-sex); printf(%4d-%2d-%2dn, p-birthday.year, p-birthday.month, p-birthday.day); 如果指针变量如果指针变量p已指向某结构数组,则已指向某结构数组,则p+1指向指向结构数组的下一个元素,而不是当前元素的下一结构数组的下一个元素,而不是当前元素的下一个成员。个成员。如果指针变量如果指针变量p已经指向一个结构变量(或结已经指向一个结构变量(或结构数组),就不能再使之

14、指向结构变量(或结构构数组),就不能再使之指向结构变量(或结构数组元素)的某一成员。数组元素)的某一成员。 10.4.3 指向结构数据的指针作函数参数例例:编写显示函数,通过主函数调用输出学生信息编写显示函数,通过主函数调用输出学生信息 #includestruct.h“struct std_info student3=000102,“john,“m,1980,5,20, 000105,“apple,“f,1980,8,15, “000112”,“kitty”,“f”,1980,3,10 ;void main() void display(); /*函数声明函数声明*/ int i=0; pr

15、intf(No. Name Sex Birthdayn);for( ; ino, p-name, p-sex); printf(%4d-%2d-%2dn, p-birthday.year, p-birthday.month, p-birthday.day);链表链表常用的、能够实现动态存储分配的数据结构常用的、能够实现动态存储分配的数据结构头指针变量头指针变量head指向链表的首结点指向链表的首结点每个结点由每个结点由2个域组成:个域组成:数据域数据域存储结点本身的信息。存储结点本身的信息。指针域指针域指向后继结点的指针。指向后继结点的指针。尾结点的指针域置为尾结点的指针域置为“NULL(空)

16、(空)”,作为链表结,作为链表结束的标志。束的标志。 数据域数据域 指针域指针域 数据域数据域 NULLhead对链表的基本操作对链表的基本操作创建、检索(查找)、插入、删除和修改等。创建、检索(查找)、插入、删除和修改等。创建链表:从无到有地建立起一个链表,即往空链表中依次插创建链表:从无到有地建立起一个链表,即往空链表中依次插入若干结点,并保持结点之间的前驱和后继关系。入若干结点,并保持结点之间的前驱和后继关系。检索:按给定的检索条件,查找某个结点。如果找到指定的结检索:按给定的检索条件,查找某个结点。如果找到指定的结点,则称为检索成功;否则,称为检索失败。点,则称为检索成功;否则,称为检

17、索失败。插入:在结点插入:在结点ki-1与与ki之间插入一个新的结点之间插入一个新的结点k,使线性表的长,使线性表的长度增度增1,且,且ki-1与与ki的逻辑关系发生如下变化:的逻辑关系发生如下变化:插入前,插入前,ki-1是是ki的前驱,的前驱,ki是是ki-1的后继;插入后,新插入的结点的后继;插入后,新插入的结点k成为成为ki-1的后继、的后继、ki的前驱的前驱删除:删除结点删除:删除结点ki,使线性表的长度减,使线性表的长度减1,且,且ki-1、ki和和ki+1之间之间的逻辑关系发生如下变化:的逻辑关系发生如下变化:删除前,删除前,ki是是ki+1的前驱、的前驱、ki-1的后继;删除后

18、,的后继;删除后,ki-1成为成为ki+1的前驱,的前驱,ki+1成为成为ki-1的后继的后继 例如:例如: struct grade char no7;/*学号学号*/ struct grade *next;/*指针域指针域*/ ;例:编写例:编写create()函数,按照规定的结点结构,创函数,按照规定的结点结构,创建一个链表(链表中的结点个数不限)。建一个链表(链表中的结点个数不限)。基本思路:基本思路:首先向系统申请一个结点的空间,然后输入结点首先向系统申请一个结点的空间,然后输入结点数据域的(数据域的(2个)数据项,并将指针域置为空(链尾标个)数据项,并将指针域置为空(链尾标志),最

19、后将新结点插入到链表尾。对于链表的第一志),最后将新结点插入到链表尾。对于链表的第一个结点,还要设置头指针变量。个结点,还要设置头指针变量。例程的例程的3个指针变量个指针变量head、new和和tail的说明如下:的说明如下:Head:头指针变量,指向链表的第一个结点,用作函:头指针变量,指向链表的第一个结点,用作函数返回值。数返回值。New:指向新申请的结点。:指向新申请的结点。Tail:指向链表的尾结点,用:指向链表的尾结点,用tail-next=new,实现将,实现将新结点插入到链表尾,使之成为新的尾结点新结点插入到链表尾,使之成为新的尾结点#define NULL 0#define L

20、EN sizeof(struct grade)/*定义结点长度定义结点长度*/struct grade/*定义结点结构定义结点结构*/ char no7;/*学号学号*/ struct grade *next;/*指针域指针域*/ ;/*create()函数函数: 创建一个具有头结点的链表创建一个具有头结点的链表*/*返回值:返回链表的头指针返回值:返回链表的头指针*/struct grade *create() struct grade *head=NULL, *new, *tail; int count=0; /*链表中的结点个数链表中的结点个数(初值为初值为0)*/ for( ; ; )

21、 /*缺省缺省3个表达式的个表达式的for语句语句*/ new=(struct grade *)malloc(LEN);/*申请一个新结点申请一个新结点*/*输入结点数据域的数据项输入结点数据域的数据项*/scanf(%s, new-no);if(strcmp(new-no,000000)=0) /*如果学号为如果学号为6个个0,则退出,则退出*/ free(new); /*释放最后申请的结点空间释放最后申请的结点空间*/ break; /*结束结束for语句语句*/ count+; /*结点个数加结点个数加1*/*将新结点插入到链表尾,并设置新的尾指针将新结点插入到链表尾,并设置新的尾指针*

22、/if(count=1) head=new; /*是第一个结点是第一个结点, 置头指针置头指针*/ else tail-next=new; /*非首结点非首结点, 将新结点插入到链表尾将新结点插入到链表尾*/ tail=new; /*设置新的尾结点设置新的尾结点*/new-next=NULL; /*置新结点的指针域为空置新结点的指针域为空*/ return(head);例编写例编写insert()函数,在单链表的第函数,在单链表的第i个结点后插入个结点后插入1个新结点。当个新结点。当i=0时,表示新结点插入到第一个结点之前,时,表示新结点插入到第一个结点之前,成为链表新的首结点。成为链表新的首

23、结点。基本思路:基本思路:通过单链表的头指针,首先找到链表的第一个结点;通过单链表的头指针,首先找到链表的第一个结点;然后顺着结点的指针域找到第然后顺着结点的指针域找到第i个结点,最后将新结点插个结点,最后将新结点插入到第入到第i个结点之后。个结点之后。/*函数功能:在单链表的第函数功能:在单链表的第i个结点后插入个结点后插入1个新结点个新结点*/*函数参数:函数参数:head为单链表的头指针,为单链表的头指针,new指向要插指向要插入的新结点,入的新结点,i为结点索引号为结点索引号*/*函数返回值:单链表的头指针函数返回值:单链表的头指针*/struct grade *insert(stru

24、ct grade *head, struct grade *new, int i) struct grade *pointer; /*将新结点插入到链表中将新结点插入到链表中*/if(head=NULL) head=new, new-next=NULL; /*将新结点插入到空链表中将新结点插入到空链表中*/else/*非空链表非空链表*/ if(i=0) new-next=head, head=new; /*使新结点成为使新结点成为 链表链表 新的首结点新的首结点*/ else /*其他位置其他位置*/ pointer=head; /*查找单链表的第查找单链表的第i个结点个结点(pointer

25、指向它指向它)*/ for(; pointer!=NULL & i1; pointer=pointer-next, i-) ; if(pointer=NULL) /*越界错越界错*/ printf(Out of the range, cant insert new node!n); else /*一般情况:一般情况:pointer指向第指向第i个结点个结点 */ new-next=pointer-next, pointer-next=new; return(head); 内部函数(又称静态函数) 外部函数 l多个源程序文件的编译和连接 当一个源程序由多个源文件组成时,语言根据当一个源程

26、序由多个源文件组成时,语言根据函数能否被其它源文件中的函数调用,将函数分为内函数能否被其它源文件中的函数调用,将函数分为内部函数和外部函数。部函数和外部函数。如果在一个源文件中定义的函数,只能被本文件中的函数调如果在一个源文件中定义的函数,只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用,称为内部函数。用,而不能被同一程序其它文件中的函数调用,称为内部函数。定义内部函数定义内部函数static 函数类型函数类型 函数名函数名(函数参数表函数参数表) “static”:内部函数又称静态函数,:内部函数又称静态函数,static指函数的作用域仅局指函数的作用域仅局限于本文件限于本文件

27、使用内部函数的优点使用内部函数的优点不同的人编写不同的函数时,不用担心自己定义的函数,不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名,因为同名也没有关系。是否会与其它文件中的函数同名,因为同名也没有关系。外部函数的定义:在定义函数时,如果没有加关外部函数的定义:在定义函数时,如果没有加关键字键字“static”,或冠以关键字,或冠以关键字“extern”,表示此函,表示此函数是外部函数数是外部函数extern 函数类型函数类型 函数名函数名(函数参数表函数参数表) 调用外部函数时,需要对其进行说明:调用外部函数时,需要对其进行说明:extern 函数类型函数类型

28、 函数名函数名(参数类型表参数类型表),函数,函数名名2(参数类型表参数类型表2);例:外部函数应用例:外部函数应用(1)文件)文件mainf.cmain() extern void input(),process(),output(); input(); process(); output();(2)文件)文件subf1.cextern void input()/*定义外部函数定义外部函数*/ (3)文件)文件subf2.cextern void process()/*定义外部函数定义外部函数*/ (4)文件)文件subf3.cextern void output()/*定义外部函数定义外部

29、函数*/ 8.5.3 多个源程序文件的编译和连接多个源程序文件的编译和连接 l(1)一般过程)一般过程l编辑各源文件编辑各源文件 创建创建Project(项目)文件(项目)文件 设置项目名称设置项目名称 编译、连接,运行,查看结果。编译、连接,运行,查看结果。l(2)创建)创建Project(项目)文件(项目)文件l用编辑源文件相同的方法,创建一个扩展名用编辑源文件相同的方法,创建一个扩展名为为.PRJ的项目文件:该文件中仅包括将被编译、连的项目文件:该文件中仅包括将被编译、连接的各源文件名,一行一个,其扩展名接的各源文件名,一行一个,其扩展名.C可以缺省;可以缺省;文件名的顺序,仅影响编译的

30、顺序,与运行无关。文件名的顺序,仅影响编译的顺序,与运行无关。l注意注意:如果有某个(些)源文件不在当前目录下,:如果有某个(些)源文件不在当前目录下,则应在文件名前冠以路径则应在文件名前冠以路径。 (3)设置项目名称设置项目名称打开菜单,选取ProjectProject name,输入项目文件名即可。(4)编译、连接,运行,查看结果)编译、连接,运行,查看结果与单个源文件相同。编译产生的目标文件,以及连接产生的可执行文件,它们的主文件名,均与项目文件的主文件名相同。注意注意:当前项目文件调试完毕后,应选取ProjectClear project,将其项目名称从“Project name”中清

31、除(清除后为空)。否则,编译、连接和运行的,始终是该项目文件!(5)关于错误跟踪)关于错误跟踪缺省时,仅跟踪当前一个源程序文件。如果希望自动跟踪项目中的所有源文件,则应将OptionsEnvironmentMessage Tracking开关置为“All files ”:连续按回车键,直至“All files”出现为止。此时,滚动消息窗口中的错误信息时,系统会自动加载相应的源文件到编辑窗口中。也可关闭跟踪(将“Message Tracking”置为“Off”)。此时,只要定位于感兴趣的错误信息上,然后回车,系统也会自动将相应源文件加载到编辑窗口中。Return动态存储动态存储程序运行期间根据需

32、要动态地分配存储空间程序运行期间根据需要动态地分配存储空间函数的形参,未加函数的形参,未加static的局部变量,函数调用的局部变量,函数调用时的现场保护和返回地址时的现场保护和返回地址静态存储静态存储程序运行期间由系统分配固定的存储空间程序运行期间由系统分配固定的存储空间全局变量全局变量变量的属性变量的属性数据类型数据类型存储类别:存储类别:auto,static,register,extern变量的作用域和生存期变量的作用域和生存期 自动局部变量(又称自动变量)自动局部变量(又称自动变量)动态存储动态存储定义格式:定义格式:auto 数据类型数据类型 变量表;变量表;存储特点存储特点自动变

33、量属于动态存储方式。在函数中定义的自动变量,只在自动变量属于动态存储方式。在函数中定义的自动变量,只在该函数内有效;函数被调用时分配存储空间,调用结束就释放。该函数内有效;函数被调用时分配存储空间,调用结束就释放。在复合语句中定义的自动变量,只在该复合语句中有效;退出在复合语句中定义的自动变量,只在该复合语句中有效;退出复合语句后,也不能再使用,否则将引起错误复合语句后,也不能再使用,否则将引起错误定义而不初始化,则其值是不确定的定义而不初始化,则其值是不确定的。如果初始化,则赋初值。如果初始化,则赋初值操作是在调用时进行的,且每次调用都要重新赋一次初值操作是在调用时进行的,且每次调用都要重新

34、赋一次初值自动变量的作用域,局限于定义它的个体内自动变量的作用域,局限于定义它的个体内 静态存储静态存储静态局部变量静态局部变量定义格式:定义格式: static 数据类型数据类型 局部变量表;局部变量表;存储特点存储特点静态局部变量属于静态存储。静态局部变量属于静态存储。程序执行过程中,即使所在函数调用结束也不释程序执行过程中,即使所在函数调用结束也不释放放即:程序执行期间,静态局部变量始终存在,但即:程序执行期间,静态局部变量始终存在,但其它函数不能引用它们其它函数不能引用它们每次调用它们所在的函数时,不再重新赋初值,只是每次调用它们所在的函数时,不再重新赋初值,只是保留上次调用结束时的值

35、保留上次调用结束时的值定义但不初始化,则自动赋以定义但不初始化,则自动赋以“”或或0例:自动变量与静态局部变量的存储特性例:自动变量与静态局部变量的存储特性void auto_static() int var_auto=0;/*自动变量:每次调用都重新初始化自动变量:每次调用都重新初始化*/ static int var_static=0; /*静态局部变量:只初始化静态局部变量:只初始化1次次*/ printf(“var_auto=%d,var_static=%dn”,var_auto, var_static); +var_auto; +var_static; Void main() int

36、 i; for(i=0; i5; i+) auto_static(); 运行结果:运行结果:Var_auto=0,var_static=0Var_auto=0,var_static=1Var_auto=0,var_static=2Var_auto=0,var_static=3Var_auto=0,var_static=4寄存器存储寄存器存储寄存器变量寄存器变量一般情况下,变量的值都是存储在内存中的一般情况下,变量的值都是存储在内存中的为提高执行效率,语言允许将局部变量的值存放到为提高执行效率,语言允许将局部变量的值存放到寄存器中,称为寄存器变量寄存器中,称为寄存器变量定义格式:定义格式: register 数据类型数据类型 变量表;变量表;只有局部变量才能定义成寄存器变量,全局变量不行只有局部变量

温馨提示

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

评论

0/150

提交评论