资源预览内容
第1页 / 共88页
第2页 / 共88页
第3页 / 共88页
第4页 / 共88页
第5页 / 共88页
第6页 / 共88页
第7页 / 共88页
第8页 / 共88页
第9页 / 共88页
第10页 / 共88页
亲,该文档总共88页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
第第8章章 结构体、共用体和枚举类型结构体、共用体和枚举类型n教学目的:教学目的:通过本章学习,要求了解结构型、链表、通过本章学习,要求了解结构型、链表、共用型和枚举型数据的特点,熟练掌握结构型共用型和枚举型数据的特点,熟练掌握结构型的定义方法,结构型变量、数组、指针变量的的定义方法,结构型变量、数组、指针变量的定义、初始化和成员的引用方法;掌握简单链定义、初始化和成员的引用方法;掌握简单链表的基本操作原理和应用;掌握共用型和枚举表的基本操作原理和应用;掌握共用型和枚举型的定义方法和对应用变量的定义和引用;掌型的定义方法和对应用变量的定义和引用;掌握用户自定义类型的定义和使用。学习本章内握用户自定义类型的定义和使用。学习本章内容可以为今后学习数据结构中的链表创建和使容可以为今后学习数据结构中的链表创建和使用打下基础。用打下基础。第第8章章 结构体、共用体和枚举类型结构体、共用体和枚举类型 n教学内容教学内容 结构型的引入,很好的处理生活总的各种表格或表格中的记录结构型的引入,很好的处理生活总的各种表格或表格中的记录结构型的定义,结构型变量的定义、赋值、引用及引用链表等方法结构型的定义,结构型变量的定义、赋值、引用及引用链表等方法共用型的定义,共用型变量的定义、赋值、引用共用型的定义,共用型变量的定义、赋值、引用枚举型的定义,共用型变量的定义、赋值、引用枚举型的定义,共用型变量的定义、赋值、引用第第8章章 结构体、共用体和枚举类型结构体、共用体和枚举类型n重点和重点和难点点重点:重点: (1)结构型、共用型、枚举型数据的特点和定义。结构型、共用型、枚举型数据的特点和定义。 (2)结构型变量、数组、指针变量的定义、初始化和成员结构型变量、数组、指针变量的定义、初始化和成员引用方法。引用方法。 (3)共用型和枚举型变量的定义和引用方法。共用型和枚举型变量的定义和引用方法。难点难点: (1)嵌套的结构型数据的处理嵌套的结构型数据的处理 (2)用结构体解决链表问题(建立、插入、删除、输出和用结构体解决链表问题(建立、插入、删除、输出和查询)。查询)。 8.1 C语言的数据类型语言的数据类型结构型是用户自己定义的数据类型结构型是用户自己定义的数据类型8.1 结构体型的实例结构体型的实例 前面我们学习过了基本数据类型,例如:前面我们学习过了基本数据类型,例如:short、long、int 、float、double、char,这些基本数据类型都是系统已,这些基本数据类型都是系统已经定义好的,用户可以直接使用它们。但现实世界是复杂经定义好的,用户可以直接使用它们。但现实世界是复杂的,在我们的日常生活中有很多的表格,各表格之间又有的,在我们的日常生活中有很多的表格,各表格之间又有关联。因此用户需要自己定义数据类型,用户自己定义的关联。因此用户需要自己定义数据类型,用户自己定义的数据类型一旦定义好之后,就可以像使用系统类型一样使数据类型一旦定义好之后,就可以像使用系统类型一样使用它。例如:对一个新生进行入学登记时,就需要填一张用它。例如:对一个新生进行入学登记时,就需要填一张表格,填写的内容包括姓名、性别、学号、年龄、家庭住表格,填写的内容包括姓名、性别、学号、年龄、家庭住址、联系电话、总分等多个数据项来完成,其中姓名是字址、联系电话、总分等多个数据项来完成,其中姓名是字符串型(可以用字符数组来表示),性别是字符型(用符串型(可以用字符数组来表示),性别是字符型(用m表示男性、用表示男性、用f表示女性),年龄是整型,总分是实型。表示女性),年龄是整型,总分是实型。 如图如图8-1所示,所示, 这些数据项之间关系紧密,每一个这些数据项之间关系紧密,每一个学生通过姓名、性别、学号、年龄、家庭地址、联系学生通过姓名、性别、学号、年龄、家庭地址、联系电话、总分等属性构成一个整体反映一个学生的基本电话、总分等属性构成一个整体反映一个学生的基本情况。如果将姓名、性别、学号、年龄、家庭地址、情况。如果将姓名、性别、学号、年龄、家庭地址、联系电话、总分分别定义为互相独立的简单变量,难联系电话、总分分别定义为互相独立的简单变量,难以反映它们之间的内在联系。为了方便处理此类数据,以反映它们之间的内在联系。为了方便处理此类数据,常常把这些关系密切但类型不同的数据项组织在一起,常常把这些关系密切但类型不同的数据项组织在一起,即即“封装封装”起来,并为其取一个名字,在语言中就起来,并为其取一个名字,在语言中就称其为结构体(也人称为构造体),结构体是用户自称其为结构体(也人称为构造体),结构体是用户自己定义数据类型的一种。己定义数据类型的一种。结构体类型的定义结构体类型定义的一般形式结构体类型定义的一般形式struct 结构型名结构型名数据类型标识符成员;数据类型标识符成员; 数据类型标识符成员;数据类型标识符成员; 数据类型标识符成员数据类型标识符成员n; ; 请读者注意结构体定义语句的右花括号后面用请读者注意结构体定义语句的右花括号后面用“分号(;分号(;)”做语句结束标记。做语句结束标记。结构体类型的定义结构体型定义实例结构体型定义实例n例如:为了存放一个人的姓名、性别、年龄、工资,例如:为了存放一个人的姓名、性别、年龄、工资,可以定义如下的结构型:可以定义如下的结构型: struct person char name10; char sex; int age; float wage; ; /*这个名为这个名为person的结构型共含有的结构型共含有4个成员个成员*/结构体类型的定义 结构型嵌套定义结构型嵌套定义结构型嵌套定义结构型嵌套定义【例8.1】一开始所讲的例题中的birthday类型和person类型。 struct birthday /*定义含有定义含有3个整型成员的结构型个整型成员的结构型 birthday*/ int year; int month; int day;struct person /*定义含有定义含有4个整型成员的结构型个整型成员的结构型 person*/char name20; char sex; struct birthday bir; /*该成员的数据类型是结构型该成员的数据类型是结构型*/ float wage;结构型变量的定义和初始化结构型变量的定义和初始化n先定义结构型,后定义变量先定义结构型,后定义变量n定义结构型的同时定义变量定义结构型的同时定义变量 n定义无名称的结构型的同时定义变量定义无名称的结构型的同时定义变量 结构体变量的定义和引用结构体变量的定义和引用 例如:为学生信息定义例如:为学生信息定义2个变量个变量x和和y ,并给它们赋初值,和一并给它们赋初值,和一个变量个变量z,没有赋初值的程序段如下:,没有赋初值的程序段如下:struct studentlong number; char name20; char sex; float score3;struct student x,y;在定义变量的同时,可以变量赋初值,例如上例中的定义语在定义变量的同时,可以变量赋初值,例如上例中的定义语句可以改写如下:句可以改写如下:struct student x=100001L,”Tom”,m,86,94,89, y=100002L,”Lucy”,f,78,88,45;1. 1. 先定义结构型,后定义变量先定义结构型,后定义变量先定义结构型,后定义变量先定义结构型,后定义变量 2. 定义结构型的同时定义变量定义结构型的同时定义变量例如:为学生信息定义例如:为学生信息定义2个变量个变量x和和y ,并给它们赋初并给它们赋初值,和一个变量值,和一个变量z,没有赋初值的程序段如下:,没有赋初值的程序段如下:struct studentlong number; char name10; char sex; float score3;x=100001L,”Tom”,m,86,94,89, y=100002L,”Lucy”,f,78,88,45,z; 这种方法是将类型定义和变量定义同时进行。以这种方法是将类型定义和变量定义同时进行。以后仍然可以使用这种结构型来定义其它的变量。后仍然可以使用这种结构型来定义其它的变量。 3. 定义无名称的结构型的同时定义变量定义无名称的结构型的同时定义变量例如:为学生信息定义例如:为学生信息定义2个变量个变量x和和y ,并给它们赋初值,和并给它们赋初值,和一个变量一个变量z,没有赋初值的程序段如下:,没有赋初值的程序段如下:structlong number; char name10;char sex; float score3;x=100001L,”Tom”,m,86,94,89, y=100002L,”Lucy”,f,78,88,45,z; 这种方法是将类型定义和变量定义同时进行,但结构型这种方法是将类型定义和变量定义同时进行,但结构型的名称省略,以后将无法使用这种结构型来定义其它变的名称省略,以后将无法使用这种结构型来定义其它变量,建议尽量少用。量,建议尽量少用。 结构型变量成员的引用结构型变量成员的引用1.结构型变量成员的结构型变量成员的引用方法引用方法2.结构型变量成员地址的结构型变量成员地址的引用方法引用方法3.结构型变量地址的结构型变量地址的引用方法引用方法1. 结构型变量成员的引用方法结构型变量成员的引用方法结构型变量成员的引用格式如下:结构型变量成员的引用格式如下:n结构型变量名结构型变量名. 成员名成员名 其中的其中的“.”称为成员运算符,其运算级别是最称为成员运算符,其运算级别是最高的,和圆括号运算符高的,和圆括号运算符“()()”、下标运算符、下标运算符“”是同级别的,运算顺序是自左向右的。是同级别的,运算顺序是自左向右的。如果某个结构型变量的成员数据类型又是一个结构型,如果某个结构型变量的成员数据类型又是一个结构型,则其成员的引用方法如下:则其成员的引用方法如下:n外层结构型变量外层结构型变量. 外层成员名外层成员名. 内层成员名内层成员名结构型变量成员的引用实例结构型变量成员的引用实例【例8.2】求Tom的三门课程的成绩总分,并在显示器显示出来(使用结构型变量成员的引用)。 程序清单如下: #” struct student long number; char name10; char sex; float score3; main() struct student stu1; /*定义student类型的变量stu1*/ stu1.number=100001L; /*给结构型变量stu1的成员number赋值*/ strcpy(stu1.name;”Tom”); /*给结构型变量stu1的成员name赋值*/ stu1.sex=f; /*给结构型变量stu1的成员sex赋值*/ stu1.score0=89; /*给结构型变量stu1的成员score赋值*/ stu1.score1=91; stu1.score2=86; printf(“%s的总分是:%fn”,stu.name,stu1.score0+stu1.score1+stu1.score2); 2. 结构型变量成员地址的引用方法结构型变量成员地址的引用方法结构型的变量成员地址引用格式如下:结构型的变量成员地址引用格式如下:n &结构型的变量名结构型的变量名.成员名成员名 存放结构型变量成员地址的指针变量类型必须和该存放结构型变量成员地址的指针变量类型必须和该成员的类型相同。成员的类型相同。【例8.4】结构型变量成员地址引用。程序清单如下:程序清单如下: #include “” /*程序中使用了字符串处理函数程序中使用了字符串处理函数*/ sturct student2 /*定义定义student2结构型结构型*/ long number; char name10; main() struct student2 x; /*定义定义student2类型的变量类型的变量x*/ long *p_number; /*定义能指向结构型定义能指向结构型student成员成员number的指针变的指针变量量*/ char *p_name; /*定义能指向结构型定义能指向结构型student成员成员namer的指针变的指针变量量*/ p_number=&; /*让指针变量指向结构型变量让指针变量指向结构型变量x的成员的成员*/ *p_ number=100001L; /*用指针变量给结构型变量用指针变量给结构型变量x的所有成员赋值的所有成员赋值*/ strucpy(p_ name,”zhongxin”); printf(“number=%1d name=%sn”,*p_number,*p_ name); /*用指针变量输出结构型变量用指针变量输出结构型变量x所有成员的值所有成员的值*/ 从这个例子可以看出,使用指向结构型变量成员的指针变量来引用从这个例子可以看出,使用指向结构型变量成员的指针变量来引用成员的方法比较繁琐,可以直接使用结构型变量的指针成员来引用成员的方法比较繁琐,可以直接使用结构型变量的指针成员来引用成员。具体使用方法请参看第成员。具体使用方法请参看第8章节。章节。3. 结构型变量地址的引用方法结构型变量地址的引用方法 结构型变量地址的引用格式如下:结构型变量地址的引用格式如下: &结构型变量名结构型变量名 例如:借用【例例如:借用【例8.4】中的结构型】中的结构型struct student2 struct student2 y,*sty=&y;存放结构型变量地址的指针变量必须是类型相同的结构存放结构型变量地址的指针变量必须是类型相同的结构型指针,关于如何使用结构型变量地址的例子请参见第型指针,关于如何使用结构型变量地址的例子请参见第8章中介绍的指向结构型数据的指针变量。章中介绍的指向结构型数据的指针变量。结构型数组的定义和引用结构型数组的定义和引用 在实际应用中,我们经常要处理的是具有在实际应用中,我们经常要处理的是具有 相同数据结构的一个群体。比如一批书,所有相同数据结构的一个群体。比如一批书,所有员工的通信地址,一个班级的学生等。由相同员工的通信地址,一个班级的学生等。由相同结构类型变量组成的数组,称为结构型数组。例结构类型变量组成的数组,称为结构型数组。例如,全班有如,全班有40人,在总成绩单上每人占一行,每人,在总成绩单上每人占一行,每行的内容包括学号、姓名、行的内容包括学号、姓名、3门功课的成绩、平门功课的成绩、平均分、名次,这样一个总成绩单就可以用结构型均分、名次,这样一个总成绩单就可以用结构型数组表示。数组表示。8.3.1 结构型数组的定义和初始化结构型数组的定义和初始化n先定义结构型,然后再定义结构型数组并赋初值先定义结构型,然后再定义结构型数组并赋初值 n定义结构型的同时定义数组并赋初值定义结构型的同时定义数组并赋初值 n定义无名称的结构型的同时定义数组并赋初值定义无名称的结构型的同时定义数组并赋初值 1.1.1.1.先定义结构型,再定义结构型数组并赋初值运算先定义结构型,再定义结构型数组并赋初值运算先定义结构型,再定义结构型数组并赋初值运算先定义结构型,再定义结构型数组并赋初值运算 struct student /*定义结构型定义结构型*/ long number; char name10; char sex; float score3; ; struct student s3= 200001L,”Tom”,m,78,86,92 , 200002L,”Lucy”,f,85,69,82 , 200003L,”Jack”,m,84,88,96 ;2. 定义结构型的同时定义数组并赋初值定义结构型的同时定义数组并赋初值 struct student /*定义结构型定义结构型*/long number;char name10;char sex;float score3;s3= 200001L,”Tom”,m,78,86,92 , 200002L,”Lucy”,f,85,69,82 , 200003L,”Jack”,m,84,88,96 ;3. 3. 定义无名称的结构型的同时定义数组并赋初值定义无名称的结构型的同时定义数组并赋初值定义无名称的结构型的同时定义数组并赋初值定义无名称的结构型的同时定义数组并赋初值 struct /*定义结构型定义结构型*/long number;char name10;char sex;float score3;s3= 200001L,”Tom”,m,78,86,92 , 200002L,”Lucy”,f,85,69,82 , 200003L,”Jack”,m,84,88,96 ;8.3.2 结构型数组元素成员的引用结构型数组元素成员的引用1.结构型数组元素的引用结构型数组元素的引用格式如下格式如下; 结构型数组名结构型数组名下标下标 . 成员名成员名2.结构型数组元素成员地址的引用结构型数组元素成员地址的引用格式如下格式如下: &结构型数组名结构型数组名下标下标.成员名成员名1. 1. 结构型数组元素的引用结构型数组元素的引用结构型数组元素的引用结构型数组元素的引用: 结构型数组名结构型数组名结构型数组名结构型数组名 下标下标下标下标 . . 成员名成员名成员名成员名n【例【例8.5】输入】输入3个学生的数据,每个学生的信息个学生的数据,每个学生的信息由学号、姓名和三门功课的成绩组成,然后计算每由学号、姓名和三门功课的成绩组成,然后计算每一个学生的总分,并输出总分最高的学生信息。一个学生的总分,并输出总分最高的学生信息。n分析:将分析:将3个学生定义为结构型类型数组,学号个学生定义为结构型类型数组,学号为长整型、姓名为字符型、成绩为实型数组,总分为长整型、姓名为字符型、成绩为实型数组,总分存在成绩数组中。存在成绩数组中。程序清单如下:程序清单如下:#define N 3struct student /*定义结构型定义结构型*/ long number; char name10; float scoreN+1; /*score数组前三个元素用来存放成绩,第四个元素用来存数组前三个元素用来存放成绩,第四个元素用来存 放放总分总分*/ stuN; main() float max=0;int i,j,max_i=0;for(i=0;iN;i+)printf(“输入第输入第%d个学生的信息,依次输入学号,姓名,三个成绩,各数据之间用个学生的信息,依次输入学号,姓名,三个成绩,各数据之间用,隔开隔开”,i);scanf(“%ld,%s,%f,%f,%f”, ,&stui.number,&stui.name,&stui.score0, &stui.score1, &stui.score2);stui.score3=stui.score0+ stui.score1+ stui.score2;if (max成员名成员名n 方式方式1比较好理解,其中比较好理解,其中“*指针变量指针变量”就代表了它所指向的就代表了它所指向的结构型变量,利用结构型变量,利用“成员运算符成员运算符”来引用,其作用相当于来引用,其作用相当于“结构型变量结构型变量.成员名成员名”。需要注意的是。需要注意的是“*指针变量指针变量”必须用必须用圆括号括住,因为圆括号括住,因为“*”运算符的级别低于运算符的级别低于“.”运算符的级运算符的级别,如果不加括号,则优先处理别,如果不加括号,则优先处理“.”运算符,将出现运算符,将出现“指针指针变量变量.成员名成员名”,会造成语法错误。,会造成语法错误。n 方式方式2是一种新的引用方法,其中是一种新的引用方法,其中“-”称称“指向成员运算符指向成员运算符”,也简称,也简称“指向运算符指向运算符”。其运算级别和。其运算级别和“()()”、“”、“.”是同级的。指向运算符的左边必须是已指向某是同级的。指向运算符的左边必须是已指向某个结构型变量或数组元素的指针变量,其右边必须是对应结个结构型变量或数组元素的指针变量,其右边必须是对应结构型数据的成员名。构型数据的成员名。8.4.2 指向结构型数组的指针1.指针变量指向数组元素指针变量指向数组元素 如果一个结构型数组元素的地址已赋予相同结构型指针变量(即指针变量指如果一个结构型数组元素的地址已赋予相同结构型指针变量(即指针变量指向结构型数组元素),可以使用下列两种方法来引用数组元素的成员,向结构型数组元素),可以使用下列两种方法来引用数组元素的成员,其作用完全相同。其作用完全相同。 方式方式1 (*指针变量)。成员名指针变量)。成员名 方式方式2 指针变量指针变量-成员名成员名 注意,这里的指针变量必须是指向某个数组元素的。例如,它指向的数组注意,这里的指针变量必须是指向某个数组元素的。例如,它指向的数组元素为元素为“数组名数组名k”,则上述两种引用方式均代表,则上述两种引用方式均代表“数组名数组名k。成员。成员名名”。2.指针变量指向数组首地址指针变量指向数组首地址 当一个结构型数组的首地址已经赋予相同结构型的指针变量(即指针变量指当一个结构型数组的首地址已经赋予相同结构型的指针变量(即指针变量指向结构型数组),可以使用下列两种方式来引用下标为向结构型数组),可以使用下列两种方式来引用下标为i的数组元素成员,的数组元素成员,其作用完全相同。其作用完全相同。 方式方式1(*(指针变量(指针变量+i).成员名成员名 方式方式2(指针变量(指针变量+i) 成员名成员名 注意,这里的指针变量必须是指向某个数组首地址的,则上述两种引用方注意,这里的指针变量必须是指向某个数组首地址的,则上述两种引用方式均代表式均代表“数组名数组名i。成员名。成员名8.4.3 在函数间传递结构型数据在函数间传递结构型数据1. 采用采用“全局外部变量方式传递数据全局外部变量方式传递数据” 2. 采用采用“返回值方式传递数据返回值方式传递数据” 3. 采用采用“形式参数和实际参数结合的地址传递方形式参数和实际参数结合的地址传递方式双向传递数据式双向传递数据” 8.5 用指针处理链表用指针处理链表 我们知道用数组存放数据时,必须事先定义好数我们知道用数组存放数据时,必须事先定义好数组的大小,不能在程序中随便进行调整。比如有的组的大小,不能在程序中随便进行调整。比如有的班有班有100人,有的班只有人,有的班只有30人,如果要用同一个数人,如果要用同一个数组先后存放不同班级的学生数据,则必须定义长度组先后存放不同班级的学生数据,则必须定义长度为为100的数组。如果事先难以确定一个班的最多人的数组。如果事先难以确定一个班的最多人数,则必须把数组定义的足够大,以存放任何班级数,则必须把数组定义的足够大,以存放任何班级的学生数据,这显然非常浪费存储空间。为此的学生数据,这显然非常浪费存储空间。为此C语语言提供了动态数组的构建即链表。言提供了动态数组的构建即链表。8.5.1 什么是链表什么是链表 链表如同一条铁链一样,一环扣一环,中间是不链表如同一条铁链一样,一环扣一环,中间是不能断开的。这好比幼儿园的老师带领孩子出去玩,能断开的。这好比幼儿园的老师带领孩子出去玩,老师牵着第一个孩子的手,第一个孩子的另一只手老师牵着第一个孩子的手,第一个孩子的另一只手牵着第二个孩子的手牵着第二个孩子的手这就是一个这就是一个“链链”,最后,最后一个孩子有一只手空着,他就是一个孩子有一只手空着,他就是“链尾链尾”。要找这。要找这个队伍,就必须先找到老师,然后顺序找到每一个个队伍,就必须先找到老师,然后顺序找到每一个孩子。孩子。 链表是一种动态数据结构,在程序的执行过程中链表是一种动态数据结构,在程序的执行过程中可以根据需要随时间系统申请存储空间,动态地进可以根据需要随时间系统申请存储空间,动态地进行存储空间的分配。动态数据结构最显著的特点是行存储空间的分配。动态数据结构最显著的特点是包含的数据对象个数及其相互关系都可以按需要改包含的数据对象个数及其相互关系都可以按需要改变。常用的动态数据结构有链表、循环链表、双向变。常用的动态数据结构有链表、循环链表、双向链表三种。链表三种。1.单链表的结构单链表的结构 链表有一个链表有一个“头指针头指针”head,它存放链表第一个结点的首地址,它存放链表第一个结点的首地址,它没有数据,只是一个指针变量。从图它没有数据,只是一个指针变量。从图11-1中我们看到它指向链中我们看到它指向链表的第一个元素。链表的每一个元素成为一个表的第一个元素。链表的每一个元素成为一个“结点结点”(node)。每个结点都分为两个域,一个是数据域,存放各种实际的数据,每个结点都分为两个域,一个是数据域,存放各种实际的数据,如学号如学号num、姓名、姓名name、性别、性别sex、和成绩、和成绩score等。另一个域为等。另一个域为指针域,存放下一个结点的首地址,即指向下一个结点。链表中指针域,存放下一个结点的首地址,即指向下一个结点。链表中的每一个结点都是同一个结构类型。最后一个结点成为的每一个结点都是同一个结构类型。最后一个结点成为“表尾表尾”,尾结点无后续点,因此不指向其他的元素,表尾结点的指针为,尾结点无后续点,因此不指向其他的元素,表尾结点的指针为空空(NUILL)。 2.链表节点的构成链表节点的构成 由于每个结点包含数据域或者指针域两部分内容,所以链表结点采用由于每个结点包含数据域或者指针域两部分内容,所以链表结点采用结构体表示。例如链表结点的数据结构定义如下:结构体表示。例如链表结点的数据结构定义如下:struct node int num; char name10; float score; struct node *next; 在链表结构中,除了数据项成员之外,还应包含一个指向本身的指在链表结构中,除了数据项成员之外,还应包含一个指向本身的指针,该指针在使用时指向具有相同类型结构体的下一个结点。针,该指针在使用时指向具有相同类型结构体的下一个结点。 在链表结点的数据结构中,比较特殊的一点就是结构体内指针域的数在链表结点的数据结构中,比较特殊的一点就是结构体内指针域的数据类型使用了未定义成功的数据类型。这是在据类型使用了未定义成功的数据类型。这是在C语言中唯一可以先使语言中唯一可以先使用后定义的数据结构。用后定义的数据结构。3.如何建立和输出一个简单静态链表 n【例【例 8.10】建立一个如图】建立一个如图8-3所示的简单链表,它由三所示的简单链表,它由三个学生数据结点组成。请输出各结点中的数据。个学生数据结点组成。请输出各结点中的数据。n分析:为方便操作,将学生定义为一个结构体类型分析:为方便操作,将学生定义为一个结构体类型student,它有三个成员分别用来表示学生的学号、姓,它有三个成员分别用来表示学生的学号、姓名和下一个结点的地址。在程序中逐个输入各学生的名和下一个结点的地址。在程序中逐个输入各学生的数据,通过地址赋值操作建立链表。利用当型循环用数据,通过地址赋值操作建立链表。利用当型循环用printf语句逐个输出个结点中成员的值。语句逐个输出个结点中成员的值。【例【例 8.10 8.10】建立一个如图】建立一个如图8-38-3所示的简单链表,它由三个所示的简单链表,它由三个学生数据结点组成。请输出各结点中的数据。学生数据结点组成。请输出各结点中的数据。程序如下:程序如下:#includestruct studentchar no6; char name10; struct student *next;void main()struct student A=“02001”,”tom”, B=“02002”,”jane”, C=“02003”,”henry”; struct srudent *head=NULL,*p; head=&A;=&B;=&C;=NULL;p=head;while (p!=NULL) printf(“No:%stName:%sn”,p-no,p-name); p=p-next;在本例中,所有结点都是在程序中定义的、不是临时开辟的、用完后也不能释放,我们把在本例中,所有结点都是在程序中定义的、不是临时开辟的、用完后也不能释放,我们把这种链表成为这种链表成为“静态链表静态链表”4动态存储分配函数动态存储分配函数n所谓所谓“动态链表动态链表”就是链表的结构是动态分配和就是链表的结构是动态分配和存储的,在程序的执行过程中要根据需要随时向存储的,在程序的执行过程中要根据需要随时向系统申请存储空间,动态地进行存储空间的分配。系统申请存储空间,动态地进行存储空间的分配。在在C语言中,提供了一下函数完成存储空间的动语言中,提供了一下函数完成存储空间的动态分配和释放。态分配和释放。nmalloc函数函数ncalloc函数函数nfree函数函数malloc函数n其函数原型为:其函数原型为:void * malloc(unsigned size)n 其作用是在内存的动态存储区分配一个长度为其作用是在内存的动态存储区分配一个长度为size的连续空间,并返回指向该空间起始地址的连续空间,并返回指向该空间起始地址的指针。若分配失败(如系统不能提供所需内的指针。若分配失败(如系统不能提供所需内存),则返回空指针存),则返回空指针NULL.。calloc函数n其函数原型为:其函数原型为:void * calloc(unsigned n,unsigned size)n 该函数有两个形参该函数有两个形参n和和size。其作用是在内存。其作用是在内存的动态存储区中分配的动态存储区中分配n个长度为个长度为size的连续空间,的连续空间,并返回指向该空间首地址的指针。如用并返回指向该空间首地址的指针。如用calloc(20,20)可以开辟可以开辟20个(每个大小为个(每个大小为20字节)字节)的空间,即空间总长为的空间,即空间总长为400字节。若分配失败,字节。若分配失败,则返回空指针则返回空指针NULL。free函数n其函数原型为:其函数原型为:void * free(void * ptr)n其作用是释放由其作用是释放由malloc、calloc等函数申请的内等函数申请的内存空间,使这部分内存区能够被其他变量所使存空间,使这部分内存区能够被其他变量所使用。用。Ptr是最近一次调用是最近一次调用malloc()或或calloc()函数函数返回的值。返回的值。Free函数没有返回值。函数没有返回值。n在使用上述函数时要注意,函数的原型在文件在使用上述函数时要注意,函数的原型在文件和中定义。在程序中必须包含这两个头文件。和中定义。在程序中必须包含这两个头文件。下面的程序就是下面的程序就是mallloc()和和free()两个函数配合两个函数配合使用的简单实例。使用的简单实例。【例 8.11】存储空间的动态分配。程序清单如下:程序清单如下:#include#include#includemain()char *str; if(str=(char*) malloc(10)=NULL) printf(“Not enough memory to allocate buffern”);exit(1);strcpy(str,”welcome”);printf(“String is %sn”,str);free(str); 本例中首页用本例中首页用malloc函数向内存申请一块内存区,并把首地址赋予指针变量函数向内存申请一块内存区,并把首地址赋予指针变量str,是,是str指向该区域。最后用指向该区域。最后用free函数释放函数释放str指向的内存空间。整个程序包含指向的内存空间。整个程序包含了申请内存空间、使用内存空间、释放内存空间三个步骤,实现存储空间的动了申请内存空间、使用内存空间、释放内存空间三个步骤,实现存储空间的动态分配。态分配。8.5.2 动态链表的基本操作动态链表的基本操作n链表有五种基本操作链表有五种基本操作n建立建立n插入插入n删除删除n输出输出n查找查找1.单链表的创建单链表的创建n建立动态链表就是建立结点空间、输入各结点数建立动态链表就是建立结点空间、输入各结点数据和进行结点链接的过程,也就是在程序执行过据和进行结点链接的过程,也就是在程序执行过程中从无到有地建立起一个链表。程中从无到有地建立起一个链表。n通过以下实例来说明如何建立一个动态链表。通过以下实例来说明如何建立一个动态链表。 【例【例 8.12】建立一个链表存放学生数据。为简单起】建立一个链表存放学生数据。为简单起见,我们假定学生数据结构中有学号和年龄两项。见,我们假定学生数据结构中有学号和年龄两项。编写一个建立链表的函数编写一个建立链表的函数creat。创建单链表的算法单链表创建过程分析创建单链表实例程序清单程序清单如下:程序清单如下:#define LEN sizeof(struct stu)sruct stu /*结构结构stu定义为外部类型,方便程序中的各个函数使用定义为外部类型,方便程序中的各个函数使用*/ int num; int age; struct stu *next;struct stu *creat(void)/*creat函数用语动态建立一个有函数用语动态建立一个有n个结点的链表,返回与结点相同类型的指针个结点的链表,返回与结点相同类型的指针*/ struct stu *p1,*p2,*head;/*head为头指针,为头指针,p2指向已建链表的最后一个结点,指向已建链表的最后一个结点,p1始终指向当前新开辟的结点始终指向当前新开辟的结点*/ int n=0; p1=p2=(struct stu *) malloc(LEN);/*申请新结点,长度与申请新结点,长度与stu长度相等;同时使指针变量长度相等;同时使指针变量p1、p2指向新结点指向新结点*/ scanf (“%d %d”,&p1-num,&p1-page); /*输入结点的值输入结点的值*/ head=NULL; while (p1-num!=0) /*输入结点的数值不为输入结点的数值不为0*/n+; if(n=1)head=p1; /*输入的结点为第一个新结点即空表,将输入的结点数据接入表头输入的结点为第一个新结点即空表,将输入的结点数据接入表头*/ else p2-next=p1;/*非空表即输入的结点不是第一个结点,将输入的结点数据接到表尾非空表即输入的结点不是第一个结点,将输入的结点数据接到表尾*/p2=p1;p1=(struct stu *)malloc(LEN); /*申请下一个新结点申请下一个新结点*/scanf(“%d %d”,&p1-num,&p1-page);p2-next=NULL;return(head); /*返回链表的头指针返回链表的头指针*/总结建立链表的具体步骤:n定义链表的数据结构。定义链表的数据结构。n创建一个空表。创建一个空表。n利用利用malloc()函数向系统申请分配一个结点。函数向系统申请分配一个结点。n若是空表,则将新结点接到表头;若是非空若是空表,则将新结点接到表头;若是非空表,则将新结点接到表尾。表,则将新结点接到表尾。n判断一下是否有后续结点要接入链表,若有判断一下是否有后续结点要接入链表,若有则转到步骤(则转到步骤(3),否则结束。),否则结束。2.单链表的插入 n链表的插入是指将一个结点插入到一个已有的链链表的插入是指将一个结点插入到一个已有的链表中。表中。 n【例【例 8.13】以前面建立的动态链表为例,编写一】以前面建立的动态链表为例,编写一个函数,使其能够在链表中指定的位置插入一个个函数,使其能够在链表中指定的位置插入一个结点。结点。单链表插入实例分析n要在一个链表的指定位置插入结点,要求链表本身必须已要在一个链表的指定位置插入结点,要求链表本身必须已按某种规律进行了排序。例如学生数据链表中,各结点的按某种规律进行了排序。例如学生数据链表中,各结点的成员项按学号由小到大顺序排列。如果要求按学号顺序插成员项按学号由小到大顺序排列。如果要求按学号顺序插入一个结点,则要将插入的结点依次与链表中各结点比较,入一个结点,则要将插入的结点依次与链表中各结点比较,寻找插入位置。结点可以插在表头、表中、表尾。结点插寻找插入位置。结点可以插在表头、表中、表尾。结点插入存在以下几种情况。入存在以下几种情况。1. 如果原表是空表,只需使链表的头指针如果原表是空表,只需使链表的头指针head指向被插结点。指向被插结点。2. 如果被插结点值最小,则应插入第一个结点之前。将头指如果被插结点值最小,则应插入第一个结点之前。将头指针针head指向被插结点,被插结点的指针域指向原来的第一指向被插结点,被插结点的指针域指向原来的第一结点。结点。3. 如果在链表中某位置插入,使插入位置的前一结点的指针如果在链表中某位置插入,使插入位置的前一结点的指针域指向被插结点,使被插结点的指针域指向插入位置的最域指向被插结点,使被插结点的指针域指向插入位置的最后一个结点。后一个结点。4. 如果被插结点值最大,则在表尾插入,使原表尾结点指针如果被插结点值最大,则在表尾插入,使原表尾结点指针域指向被插结点,被插点指针域置为域指向被插结点,被插点指针域置为NULL。单链表插入实例图形分析单链表插入实例操作步骤单链表插入实例程序清单struct stu *insert (struct stu *head,struct stu *p1) struct stu *p2,*p3; p2=head; if(head=NULL) /*空表插入空表插入*/ head=p1; p1-next=NULL;elsewhile (p1-nump2-num)&(p2-next!=NULL) p3=p2; p2=p2-next; /*找插入位置找插入位置*/if ( p1-numnum) if (head=p2) head=p1; /*在第一结点之前插入在第一结点之前插入*/ else p3-next=p1; /*在其他位置插入在其他位置插入*/ p1-next=p2; else p2-next=p1;p1-next=NULL; /*在表末插入在表末插入*/ return head; /*返回链表的头指针返回链表的头指针*/总结链表插入操作的具体步骤:n定义一个指针变量定义一个指针变量p1指向被插结点。指向被插结点。n首先判断链表是否为空,为空则使首先判断链表是否为空,为空则使head指向被指向被插结点。插结点。n链表若不是空,用当型循环查找插入位置。链表若不是空,用当型循环查找插入位置。n找到插入位置后判断是否在第一个结点之前插找到插入位置后判断是否在第一个结点之前插入,若是则使入,若是则使head指向被插入结点,被插结点指向被插入结点,被插结点指针域指向原第一结点;否则在其他位置插入;指针域指向原第一结点;否则在其他位置插入;若插入的结点大于表中所有结点,则在表末插若插入的结点大于表中所有结点,则在表末插入。入。n函数返回值为链表的头指针。函数返回值为链表的头指针。3.单链表的删除单链表的删除 n链表中不在使用的数据,可以将其从表中删除并链表中不在使用的数据,可以将其从表中删除并释放其所占用的空间,但注意在删除结点的过程释放其所占用的空间,但注意在删除结点的过程中不能破坏链表的结构。中不能破坏链表的结构。n【例【例 8.14】以前面建立的动态链表为例,编写一】以前面建立的动态链表为例,编写一个删除链表中指定结点的函数个删除链表中指定结点的函数delet。单链表的删除实例分析n假设链表按学生的学号排列,当某结点的学号与假设链表按学生的学号排列,当某结点的学号与指定值相同时,将该结点从链表中删除。首先从指定值相同时,将该结点从链表中删除。首先从头到尾依次查找链表中给结点,并与各结点的学头到尾依次查找链表中给结点,并与各结点的学生学号作比较,若相同,则查找成功,否则,找生学号作比较,若相同,则查找成功,否则,找不到结点。由于结点在链表中可以有三种不同位不到结点。由于结点在链表中可以有三种不同位置:位于开头,中间或结尾,因此从链表中删除置:位于开头,中间或结尾,因此从链表中删除一个结点主要分两种情况,即删除链表头结点和一个结点主要分两种情况,即删除链表头结点和非表头结点。非表头结点。1. 如果被删除的结点是表头结点,使如果被删除的结点是表头结点,使head指向第二指向第二结点。结点。2. 如果被删除的结点不是表头结点,使被删结点的如果被删除的结点不是表头结点,使被删结点的前一结点指向被删结点的后一结点。前一结点指向被删结点的后一结点。单链表的删除实例图形分析单链表 的删除实例操作步骤单链表的删除实例程序清单struct stu * delete ( struct stu *head,int num) /*以以head为头指针删除为头指针删除num所在结点所在结点*/struct stu *p1,*p2; if (head=NULL) /*如为空表,输出提示信息如为空表,输出提示信息*/ printf(“nempty list!n”); goto end;p1=head;while ( p1-num!=num & p1-next!=NULL)/*当不是要删除的结点,而且也不是最后一个结点时,继续循环当不是要删除的结点,而且也不是最后一个结点时,继续循环*/p2=p1;p1=p1-next; /*p2指向当前结点,指向当前结点,p1指向下一结点指向下一结点*/if (p1-num=num) if (p1=head) head=p1-next; /*如找到被删结点,且为第一结点,则使如找到被删结点,且为第一结点,则使head指向第二指向第二结点,否则使结点,否则使p2所指结点的指针指向下一结点所指结点的指针指向下一结点*/else p2-next=p1-next;free(p1);printf (“ The node is deletedn”); else printf (“The node not been found!n”); end: return (head);总结链表删除操作的具体步骤 n定义一个指针变量定义一个指针变量p指向链表的头结点。指向链表的头结点。n用循环从头到尾依次查找链表中各结点并与用循环从头到尾依次查找链表中各结点并与各结点的学生学号做比较,若相同,则查找各结点的学生学号做比较,若相同,则查找成功推出循环。成功推出循环。n判断该结点是否为表头结点,如果是使判断该结点是否为表头结点,如果是使head指向第二个结点,如果不是使被删结点的前指向第二个结点,如果不是使被删结点的前一结点指向被删结点的后一结点。同时结点一结点指向被删结点的后一结点。同时结点个数减个数减1。4.单链表的输出 n链表的输出比较简单,只要将链表中的各个结链表的输出比较简单,只要将链表中的各个结点数据依次输出即可点数据依次输出即可 n【例【例 8.14】编写一个输出链表的函数】编写一个输出链表的函数print。n设立一个指针变量设立一个指针变量p,先指向链表的头结点,先指向链表的头结点,输出该结点的数据域,然后使指针输出该结点的数据域,然后使指针p指向下一指向下一个结点,重复上述工作,直到链表尾部。具体个结点,重复上述工作,直到链表尾部。具体算法如图算法如图8-9所示。所示。 单链表的输出实例程序清单#define LEN sizeof (struct stu)struct stu int num; int age; struct stu *next;void print ( struct stu *head) /*print函数用于输出以函数用于输出以head为头的链表各为头的链表各结点的值结点的值*/struct stu *p; p=head; /*取得链表的头指针取得链表的头指针*/ while (p!=NULL) printf ( “%6d%6d”,p-num,p-page); /*输出链表结点的值输出链表结点的值*/p=p-next; /*使指针变量使指针变量p指向下一个结点,跟踪链表增长指向下一个结点,跟踪链表增长*/总结链表输出操作的具体步骤n定义一个指针变量定义一个指针变量p。n使使p指向链表的头结点。指向链表的头结点。n若是非空表,输出该结点的数据域;若空表若是非空表,输出该结点的数据域;若空表则退出。则退出。n使指针使指针p指向下一个结点。指向下一个结点。n重复上述操作直到链表尾部。重复上述操作直到链表尾部。链表综合实例n【例【例 8.16】在前面学习的建立链表,输出链表,】在前面学习的建立链表,输出链表,删除结点,插入结点操作的基础上,试编一主函删除结点,插入结点操作的基础上,试编一主函数将以上的建立链表,删除结点,插入结点的函数将以上的建立链表,删除结点,插入结点的函数组织在一起,并输出全部结点的值。数组织在一起,并输出全部结点的值。综合实例程序清单一#define NULL 0main () struct stu *head; struct stu *stu; int del_num; printf (“input records:n”); head=creat(); /*建立链表,并返回表头建立链表,并返回表头*/ print (head); /*输出链表输出链表 */ printf (“nInput the deleted number:”); scanf (“%d”,&del_num);综合实例程序清单(续) while (del_num!=0)head=delete (head,del_num); /*从链表中删除从链表中删除del_num结点结点*/print (head); /*输出链表输出链表 */printf (“nInput the deleted number:”); scanf (“%d”,&del_num);printf (“nInput the inserted record:”);stu=(struct stu *)malloc(LEN);scanf (“%d,%d”,&stu-num,&stu-age);while (stu-num!=0) head=insert (head,stu); /*在链表中插入一节结点在链表中插入一节结点stu*/ print (head); /*输出链表输出链表 */ printf (“nInput the inserted record:”); stu=( struct student *)malloc (LEN); scanf (“%d,%d”,&stu-num,&stu-age); free (stu); /*对于对于num=0的结点,未插入,应删除其空间的结点,未插入,应删除其空间*/共共 用用 型型n共用型和结构型的比较共用型和结构型的比较共用型的定义共用型的定义nunion共用型名共用型名 数据类型数据类型1 成员名成员名1; 数据类型数据类型2 成员名成员名2; 数据类型数据类型n 成员名成员名n; ;n注意在右花括号的后面有一个语句结束符注意在右花括号的后面有一个语句结束符“分分号号”。共用型的定义实例共用型的定义实例n例如:为了节省内存,可以将不同的使用的三个数组定义在例如:为了节省内存,可以将不同的使用的三个数组定义在如下的一个共用型中,总计可节省如下的一个共用型中,总计可节省300个单元:个单元:n union c_i_f char c1100; /*该成员占用该成员占用100个单元个单元*/ int i2100; /*该成员占用该成员占用200个单元个单元*/ float f3100; /*该成员占用该成员占用400个单元个单元*/ ; /*该共用型数据共用该共用型数据共用400个单元个单元*/n需注意的是,共用型数据中每成员所占用的内存单元都是连需注意的是,共用型数据中每成员所占用的内存单元都是连续的,而且都是从分配的连续内存单元中第一个内存单元开续的,而且都是从分配的连续内存单元中第一个内存单元开始存放。所以,对共用型数据来说,所有成员的首地址都是始存放。所以,对共用型数据来说,所有成员的首地址都是相同的。这是共用型数据的一个特点。相同的。这是共用型数据的一个特点。共用型变量的定义共用型变量的定义n定义方法基本上与结构型相同,也存在以下三定义方法基本上与结构型相同,也存在以下三种方法,但不能在定义时进行初始化。种方法,但不能在定义时进行初始化。1. 先定义共用型,然后定义变量与数组。先定义共用型,然后定义变量与数组。2. 定义共用型的同时定义变量与数组定义共用型的同时定义变量与数组3. 定义无名称的共用型同时定义变量与数组定义无名称的共用型同时定义变量与数组 1. 1.先定义共用型,然后定义变量先定义共用型,然后定义变量u1u1与数组与数组u25u25。union u int i_a10; /*该成员占用该成员占用20个单元个单元*/ char c_a34; /*该成员占用该成员占用12个单元个单元*/ long l; /*该成员占用该成员占用4个单元个单元*/ double d; /*该成员占用该成员占用8个单元个单元*/; /*该共用型数据共占用该共用型数据共占用20个单元个单元*/union u u1,u25;2. 2.定义共用型的同时定义变量定义共用型的同时定义变量u1u1与数组与数组u25u25 union u int i_a10; /*该成员占用该成员占用20个单元个单元*/ char c_a34; /*该成员占用该成员占用12个单元个单元*/ long l; /*该成员占用该成员占用4个单元个单元*/ double d; /*该成员占用该成员占用8个单元个单元*/ u1,u25; 3. 3. 定义无名称的共用型同时定义变量定义无名称的共用型同时定义变量u1u1与数组与数组u25u25 union /*无名称无名称*/ int i_a10; /*该成员占用该成员占用20个单元个单元*/ char c_a34; /*该成员占用该成员占用12个单元个单元*/ long l; /*该成员占用该成员占用4个单元个单元*/ double d; /*该成员占用该成员占用8个单元个单元*/ u1,u25; 共用型变量的引用共用型变量的引用n共用型变量或数组元素成员的引用格式如下:共用型变量或数组元素成员的引用格式如下: 共用型变量名共用型变量名.成员名成员名n共用型变量成员地址的引用和指针变量的使用共用型变量成员地址的引用和指针变量的使用格式如下:格式如下: 指针变量指针变量=&共用型变量名共用型变量名.成员名成员名n共用型变量地址的引用和指针变量的使用方法共用型变量地址的引用和指针变量的使用方法 指针变量指针变量=&共用型变量名共用型变量名枚举型枚举型n顾名思义:就是把有限的数据一一例举出来,例顾名思义:就是把有限的数据一一例举出来,例如:如:n一个星期一个星期7天天n性别只有性别只有”男男”和和”女女” n中国有中国有23个省,个省,5个自治区,个自治区,4个直辖市,个直辖市,2个特别个特别行政区等。行政区等。n如图如图8-11:在填写用户资料中的所在城市时:在填写用户资料中的所在城市时,把中把中国的国的23个省,个省,5个自治区,个自治区,4个直辖市,个直辖市,2个特别行个特别行政区都列举出来,供注册者选择,这样有利于数政区都列举出来,供注册者选择,这样有利于数据的规范且不会出错。枚举型和结构型、共用型据的规范且不会出错。枚举型和结构型、共用型一样,也是一种用户自定义的数据类型,在使用一样,也是一种用户自定义的数据类型,在使用时必须先定义后使用。时必须先定义后使用。图图8-11枚兴型的定义枚兴型的定义nenum 枚举型名枚举型名n 枚举常量枚举常量1,枚举常量,枚举常量2,枚举常量枚举常量n;n注意在右花括号的后面有一个语句结束符注意在右花括号的后面有一个语句结束符”分号分号”。n其中:枚举型名是用户取的标识符;其中:枚举型名是用户取的标识符; 枚举常量是用户给常量取的标识符。枚举常量是用户给常量取的标识符。n该语句定义了一个名为该语句定义了一个名为“枚举型名枚举型名”的枚举类型,的枚举类型,该枚举型中含有该枚举型中含有n个枚举常量,每个枚举型常量均个枚举常量,每个枚举型常量均有值。有值。C语言规定枚举常量的值是依次等于语言规定枚举常量的值是依次等于0、1、2、n-1.枚举型定义实例n例如:定义一个表示星期的枚举型:例如:定义一个表示星期的枚举型: enum week sun,mon,tue,wed,thu,fri,sat; 定义的这个枚举型共有定义的这个枚举型共有7个枚举常量,它们的值依次为个枚举常量,它们的值依次为0、1、2、3、4、5、6。 C语言规定,在定义枚举型时,可以给枚举常量赋初值,方语言规定,在定义枚举型时,可以给枚举常量赋初值,方法是在枚举常量的后面跟上法是在枚举常量的后面跟上“=整型常量整型常量”。n例如:表示三原色的枚举型可定义如下:例如:表示三原色的枚举型可定义如下: enum color1 red=2,yellow=4,blue=7; 则枚举常量则枚举常量red的值为的值为2,yellow的值为的值为4,blue的值为的值为7。882枚举型变量的定义枚举型变量的定义n当某个枚举型定义后,可以用这种数据枚举型来定义变量、数组。定义当某个枚举型定义后,可以用这种数据枚举型来定义变量、数组。定义的方法有三种。的方法有三种。n1. 先定义枚举型,后定义枚举型变量、数组先定义枚举型,后定义枚举型变量、数组enum colorred,yellow,blue;enum color color_1,color_22; /*定义一个枚举型变量定义一个枚举型变量color1和具有两个元素的数组和具有两个元素的数组color_2*/n2. 定义枚举型的同时定义枚举型变量、数组定义枚举型的同时定义枚举型变量、数组enum colorred,yellow,blueenum color color_1,color_22; /*定义一个枚举型变量定义一个枚举型变量color1和具有两个元素的数组和具有两个元素的数组color_2*/n3. 定义无名称的枚举型的同时定义枚举型变量、数组定义无名称的枚举型的同时定义枚举型变量、数组enum red,yellow,blue enum color color_1,color_22; /*定义一个枚举型变量定义一个枚举型变量color1和具有两个元素的数组和具有两个元素的数组color_2*/枚举型变量的引用枚举型变量的引用n给变量或数组元素赋值,格式为:给变量或数组元素赋值,格式为: 枚举型变量或数组元素枚举型变量或数组元素=同一种枚举型常量名同一种枚举型常量名 enum color red,yellow,blue c_1; c_1=yellow; /*赋值赋值*/n在循环中用枚举变量或数组元素控制循环在循环中用枚举变量或数组元素控制循环 enum color red,yellow,bluec_1; int k=0; for(c_1=red;c_1=blue;c_1+) k+; printf(“k=%dn”,k);用户自定义类型用户自定义类型nC语言允许用户定义自己习惯的数据类型名称语言允许用户定义自己习惯的数据类型名称,来来替代系统默认的基本类型名称、数组类型名称、替代系统默认的基本类型名称、数组类型名称、指针类型名称和用户自定义的结构型名称、共用指针类型名称和用户自定义的结构型名称、共用型名称、枚举行名称等。型名称、枚举行名称等。 n用户字定义类型名的方法是通过下列定义语句实用户字定义类型名的方法是通过下列定义语句实现的。现的。 格式格式 typedef 类型名类型名1 类型名类型名2;1.基本类型的自定义基本类型的自定义n对所有系统默认的基本来性可以利用下面的自定义类型语对所有系统默认的基本来性可以利用下面的自定义类型语句来重新定义类型名。句来重新定义类型名。n【例【例 8.22】基本类型自定义例。】基本类型自定义例。 typedef float REAL; /*定义单精度实型为定义单精度实型为REAL*/ typedef char CHARACTER /*定义字符型为定义字符型为GHARACTER*/ main() REAL f1; /*相当于相当于float f1;*/ CHARACTER c1; /*相当于相当于char c1,*/ 2.数组类型的自定义数组类型的自定义 n对数组类型可以利用下面的自定义类型语句来定义一个类对数组类型可以利用下面的自定义类型语句来定义一个类型名型名 n【例【例 8.23】数组类型自定义例。】数组类型自定义例。typedef float F_ARRAY20; typedef char C_ARRAY10;main() F_ARRAY f1,f2; /*相当于相当于 float f120, f220*/C_ARRAY name,department; /*相当于相当于char name10,department10*/3.结构型、共用型的自定义结构型、共用型的自定义 n对程序中需要的结构型可以利用下面的自定义类型语句来定义一个类对程序中需要的结构型可以利用下面的自定义类型语句来定义一个类型名型名 n【例【例 8.24】结构型自定义例。】结构型自定义例。typedef struct long num;char name 10;char sex;STUDENT; main()STUDENT stu1,stu10; /*相当于相当于struct long num; char name 10; Char sex; stu1,stu10;*/4.指针型的自定义指针型的自定义 n对某种数据类型的指针型可以利用下面的自定义类对某种数据类型的指针型可以利用下面的自定义类型语句来定义一个类型名型语句来定义一个类型名 n【例【例 8.25】指针类型自定义例】指针类型自定义例typedef int *POINT_I; typedef char *POINT_C; main() POINT_I p1,p2; /*相当于相当于int *p1,*p2*/POINT_C p3,p4; /*相当于相当于char *p3,*p4*/
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号