第九章 用户建立的数据类型.

Slides:



Advertisements
Similar presentations
目 录  第 1 章 C++ 概述  第 2 章 数据类型、运算符和表达式  第 3 章 简单的输入 / 输出  第 4 章 C++ 的流程控制  第 5 章 函数  第 6 章 编译预处理  第 7 章 数组  第 8 章 结构体、共同体和枚举类型  第 9 章 指针和引用  第.
Advertisements

程序设计导论 ——第15讲 结构与结构数组.
程序设计导论 结构与结构数组.
电子成绩单项目实现.
第10章 结构体与链表 本章要点: 结构体类型与结构体变量的定义 结构体变量的引用与初始化 结构体数组 链表处理 共用体类型和枚举类型
大学实用教程 C语言.
第6章 指针 6.1 指针的概念 6.2 变量与指针 6.3 数组与指针 6.4 字符串与指针 6.5 函数与指针 6.6 返回指针值的函数
6.4 字符串与指针 1. 用字符数组存放一个字符串.
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
第九章 系 统 安 全 性 9.1 结构体 9.2 结构体型数组  9.3 结构体型指针 9.4 内存的动态分配 9.5 共用体
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
第7章 结构体、联合体和枚举类型 本章导读 本章主要知识点 《 C语言程序设计》 (Visual C++ 6.0环境)
C程序设计 第9章 自定义数据类型 主讲教师: 鲁 萍 西安建筑科技大学 理学院.
第九章 结构体 主讲教师 :贾月乐 电话:
第10章 结构体与共用体 概述 结构体 共用体 枚举类型.
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
7.1 结构体类型 7.2 共用体 7.3 枚举类型 7.4 用typedef声明类型
第9章 结构体.
第 十 章 指 针.
结构体和共用体 2 梁春燕 华电信息管理教研室.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第9章 用户自己建立数据类型 9.1 定义和使用结构体变量 9.2 使用结构体数组 9.3 结构体指针 9.4 用指针处理链表
程序设计专题 第2讲 - 结构 刘新国.
STRUCTURE 授課:ANT 日期:2010/5/12.
自定义数据类型 潘荣江 山东大学计算机科学与技术学院
程序设计基础.
C++语言程序设计 C++语言程序设计 第四章 数组及自定义数据类型 C++语言程序设计.
第九章 结构体和共用体 结构体的定义 结构体的使用 共用体的定义 共用体的使用 主讲:李祥 时间:2015年10月.
C语言程序设计 李祥.
走进编程 程序的顺序结构(二).
辅导课程六.
第7讲 结构体与共用体 7.1 结构体 7.2 共用体.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
第8章 结 构 体.
第11章 结构体和共用体.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第七章 结构体、共同体和枚举类型.
第13章 结构体的应用 13.1 了解由用户构造的数据类型 13.2 结构体类型说明及结构体变量 13.3 结构体数组
第五章 习题课 电子信息与计算机科学系 曾庆尚.
用event class 从input的root文件中,由DmpDataBuffer::ReadObject读取数据的问题
Struct結構 迴圈
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
C语言复习3----结构体.
C语言程序设计.
第十章 用户自定义数据类型 目录 学生信息管理系统的开发 结构体数据类型的概述 结构体变量的使用 结构体数组
目录 9.1 结构体类型 9.2 共用体类型 9.3 枚举类型 9.4 类型声明符typedef 1.
第十章 结构体与链表 西安工程大学.
第9章 用户自己建立数据类型 C语言提供了一些系统已定义好的数据类型,如int,float,char,用户可以用它们定义变量。
浙江长征职业技术学院—计算机与信息技术系—相方莉制作
C++大学基础教程 第7章 其它自定义数据类型 北京科技大学 信息基础科学系.
<编程达人入门课程> 本节内容 内存的使用 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群: ,
C语言程序设计 第一章 数据类型, 运算符与表达式 第二章 顺序程序设计 第三章 选择结构程序设计 第四章 循环控制 第五章 数组.
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
C++语言程序设计 C++语言程序设计 第四章 数组及自定义数据类型 C++语言程序设计.
第九节 赋值运算符和赋值表达式.
3.16 枚举算法及其程序实现 ——数组的作用.
本节内容 结构体 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
结构体与共用体 结构体 结构体是一种构造数据类型 用途:把不同类型的数据组合成一个整体 自定义数据类型 结构体类型定义
本节内容 结构体.
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
C语言程序设计 第9章 结构体.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
基本知识 数据类型、变量、常量、运算符.
第14讲 结构体和共用体 计算机与通信工程学院.
多重條件選擇敘述
第八章 结构体和共用体 结构体类型和结构体变量 结构体数组 结构体指针变量 共用体.
安排座位.
Presentation transcript:

第九章 用户建立的数据类型

结构体的概念 结构体的定义和引用 结构体数组 本章要点 结构体的概念 结构体的定义和引用 结构体数组

主要内容 9.1 结构体类型和结构体变量 9.2 结构体数组 9.3 结构体指针 9.4 用指针处理链表 9.5 共用体类型 9.1 结构体类型和结构体变量 9.2 结构体数组 9.3 结构体指针 9.4 用指针处理链表 9.5 共用体类型 9.6 枚举类型 9.7 用typedef命名类型

§9.1 结构体类型和结构体变量 9.1.1 结构体类型 问题定义: 有时需要将不同类型的数据组合成一个有机 的整体,以便于引用。如: §9.1 结构体类型和结构体变量 9.1.1 结构体类型 问题定义: 有时需要将不同类型的数据组合成一个有机 的整体,以便于引用。如: 一个学生有学号/姓名/性别/年龄/地址等属性 int num; char name[20]; char sex; int age; int char addr[30]; 图9-1 100101 Li Fun M 18 87.5 Beijing Num name sex age score addr 应当把它们组织成一个组合项,在一个组合 项中包含若干个类型不同(当然也可以相同) 的数据项。

§9.1 结构体类型和结构体变量 9.1.1 结构体类型 如:struct student 声明一个结构体类型的一般形式为: §9.1 结构体类型和结构体变量 9.1.1 结构体类型 声明一个结构体类型的一般形式为: struct 结构体名 {成员表列}; 如:struct student { int num;char name[20];char sex; int age;float score;char addr[30]; } 结构体名 成员名 类型名

§9.1 结构体类型和结构体变量 9.1.1 结构体类型 说明: (1)结构体类型并不是只有一种,而是可以设计出许多种结构体类型. §9.1 结构体类型和结构体变量 9.1.1 结构体类型 说明: (1)结构体类型并不是只有一种,而是可以设计出许多种结构体类型. (2) 成员也可以是一个结构体变量。 (3)“结构体”这个词是根据英文单词structure译出的。

9.1.2 定义结构体类型变量 例如:struct student student1, student2; 9.1.2 定义结构体类型变量 可以采取以下3种方法定义结构体类型变量: (1)先声明结构体类型再定义变量名 例如:struct student student1, student2; | | | 结构体类型名 结构体变量名 定义了student1和student2为struct student类型的变量,即它们具有struct student类型的结构. 图9-3 student1 100101 ZhangXin M 19 90.5 Shanghai 100102 WangLi F 20 98 Beijing student2

9.1.2 定义结构体类型变量 在定义了结构体变量后,系统会为之分配内存单元。 9.1.2 定义结构体类型变量 在定义了结构体变量后,系统会为之分配内存单元。 例如:student1和student2在Turbo C的内存中各占59个字节(2+20+1+2+4+30=59)。 (2)在声明类型的同时定义变量 这种形式的定义的一般形式为: struct 结构体名 { 成员表列 }变量名表列;

9.1.2 定义结构体类型变量 例如: 它的作用与第一种方法相同,即定义了两个struct student 类型的变量student1, 9.1.2 定义结构体类型变量 例如: struct student { int num; char name[20]; char sex; int age; float score; char addr[30];     }student1,student2; 它的作用与第一种方法相同,即定义了两个struct student 类型的变量student1, student2

9.1.2 定义结构体类型变量 (3) 不指定类型名而直接定义结构体类型变量 其一般形式为: struct 注意: { 9.1.2 定义结构体类型变量 (3) 不指定类型名而直接定义结构体类型变量 其一般形式为: struct {      成员表列     }变量名表列; 即不出现结构体名。 注意: (1) 结构体类型与结构体变量是不同的概念,不能混同。 (2) 结构体类型中的成员名可以与程序中的变量名相同,但二者不代表同一对象。 (3) 对结构体变量中的成员(即“域”),可以单独使用,它的作用与地位相当于普通变量。

 9.1.3 引用结构体变量 在定义了结构体变量以后,当然可以引用这个变量。但应遵守以下规则: (1)同类的结构体变量可以互相赋值,如: student1=student2; 不能将一个结构体变量作为一个整体进 行输入和输出。 例如: 已定义student1和student2为结构体变量并且它们已有值。 printf(″%d,%s,%c,%d,%f,%\n″,student1); 

9.1.3 引用结构体变量 引用结构体变量中成员的方式为 结构体变量名.成员名 例如, student1.num表示student1变量中的num成员,即student1的num(学号)项。可以对变量的成员赋值,例如:student1.num=10010;“.”是成员(分量)运算符,它在所有的运算符中优先级最高,因此可以把student1.num作为一个整体来看待。上面赋值语句的作用是将整数10010赋给student1变量中的成员num。

9.1.3 引用结构体变量 注意: 不能用student1.birthday来访问student1变量中的成员birthday,因为birthday本身是一个结构体变量。 (2) 如果成员本身又属一个结构体类型,则要用若干个成员运算符,一级一级地找到最低的一级的成员。只能对最低级的成员进行赋值或存取以及运算。 例如: 对上面定义的结构体变量student1, 可以这样访问各成员: student1.num student1.birthday.month

9.1.3 引用结构体变量 (3) 对结构体变量的成员可以像普通变量一样进行各种运算(根据其类型决定可以进行的运算)。 由于“.”运算符的优先级最高,因此student1.age++是对student1.age进行自加运算,而不是先对age进行自加运算。 (3) 对结构体变量的成员可以像普通变量一样进行各种运算(根据其类型决定可以进行的运算)。 例如: student2.score=student1.score; sum=student1.score+student2.score; student1.age++; ++student2.age;

9.1.3 引用结构体变量 (4) 可以引用结构体变量成员的地址,也可以引用结构体变量的地址。 例如: scanf(″%d″,&student1.num); (输入student1.num的值) printf(″%o″,&student1); (输出student1的首地址)

9.1.3 引用结构体变量 传递结构体变量的地址。 但不能用以下语句整体读入结构体变量, 例如: scanf(″%d,%s,%c,%d,%f,%s″,&student1); 结构体变量的地址主要用作函数参数, 传递结构体变量的地址。

9.1.4 结构体变量的初始化 例9.1 对结构体变量初始化. #include <stdio.h> void main() {struct student {long int num; char name[20]; char sex; char addr[20]; }a={10101,″LiLin″,′M′,″123 Beijing Road″}; /* 对结构体变量a赋初值*/ printf(″No.:%ld\nname:%s\nsex:%c\naddress:%s\n″,a.num,a.name,a.sex,a.addr);   }  但不能用以下语句整体读入结构体变量, 例如: scanf(″%d,%s,%c,%d,%f,%s″,&student1); 结构体变量的地址主要用作函数参数,传递结构体变量的地址。 运行结果: No.:10101 name:LiLin sex:M address:123 Beijing Road

§9.2 结构体数组 一个结构体变量中可以存放一组数 据(如一个学生的学号、姓名、成绩等 数据)。如果有10个学生的数据需要 参加运算,显然应该用数组,这就是结 构体数组。结构体数组与以前介绍过的 数值型数组不同之处在于每个数组元素 都是一个结构体类型的数据,它们都分 别包括各个成员(分量)项。

§9.2 结构体数组 9.2.1 定义结构体数组 和定义结构体变量的方法相仿,只需说明其为数组即可。例如: struct student {int num;char name[20];char sex;int age; float score;char addr[30]; };struct student[3];  以上定义了一个数组stu,数组有3个元素,均为struct student类型数据。

§9.2 结构体数组 或: 也可以直接定义一个结构体数组,例如: struct student {int num; …};stu[3]; strcut student 图9-4

§9.2 结构体数组 9.2.2 结构体数组的初始化 与其他类型的数组一样,对结构体数组可以初始化。例如: struct student 图9-5 9.2.2 结构体数组的初始化 与其他类型的数组一样,对结构体数组可以初始化。例如: struct student {int num;char name[20]; char sex; int age; float score; char addr[30];   };stu[2]={{10101,″LiLin″,′M′,18,87.5,″103 BeijingRoad″},{10102,″Zhang Fun″,′M′,19,99,″130 Shanghai Road″}}; 

§9.2 结构体数组 当然,数组的初始化也可以用以下形式: struct student {int num; … }; struct student str[]{{…},{…},{…}}; 即先声明结构体类型,然后定义数组为该结构体类型,在定义数组时初始化。 结构体数组初始化的一般形式是在定义数组的后面加上“={初值表列};”。

§9.2 结构体数组 9.2.3 结构体数组应用举例 例9.2对候选人得票的统计程序。设有3个候选人,每次输入一个得票的候选人的名字,要求最后输出各人得票结果。 #include <string.h> #include <stdio.h> struct person { char name[20];in count; }; leader[3]={“Li”,0,”Zhang”,0,”Fun”,0}

例9.2 void main() { int i,j; char leader_name[20]; for(i=1;i<=10;i++) { scanf(“%s”,leader_name); for(j=0;j<3;j++) if(strcmp(leader_name,leader[j].name)==0) leader[j].count++; } printf(“\n”); for(i=0;i<3;i++) printf(“%5s:%d\n”,leader[i].name,leader[i].count);} 运行结果: Li↙   Fun↙   Zhang↙   Fun↙   Li↙   Li:4   Zhang:3   Fun:3

§9.2 结构体数组 程序定义一个全局的结构体数组leader,它有3个元素,每一个元素包含两个成员name(姓名)和count(票数)。在定义数组时使之初始化,使3位候选人的票数都先置零. 在主函数中定义字符数组leader-name,它代表被选人的姓名,在10次循环中每次先输入一个被选人的具体人名,然后把它与3个候选人姓名相比,看它和哪一个候选人的名字相同。在输入和统计结束之后,将3人的名字和得票数输出。   图9-6 Li 0 Zhang 0 Fun 0 name count

struct student pt; /* pt可以指 向struct student类型的数据 */ §9.3 结构体指针 结构体指针是指向结构体数据的指针,一个结构体变量的起始地址就是这个结构体变量的指针。指针变量既可以指向结构体变量,也可以用来指向结构体数组中的元素。但是,指针变量的基类型必须与结构体变量的类型相同。 例如: struct student pt; /* pt可以指 向struct student类型的数据 */ 9.3.1 指向结构体变量的指针变量 下面通过一个简单例子来说明指向结构体变量的指针变量的应用。

定义指针变量p,指向struct student 类型的数据 例9.3通过指向结构体变量的指针变量输出该结构体变量的信息。 #include <string.h> #include <stdio.h> void main() {struct student{long num;char name[20]; char sex; float score;}; struct student stu_1; struct student* p; p=&stu_1; stu_1.num=89101;strcpy(stu_1.name,”LiLin”); stu_1.sex=‘M’;stu_1.score=89.5; printf(″No.:%ld\nname:%s\nsex:%c\nscore:%f\n″,stu-1.num,stu-1.name,stu-1.sex,stu-1.score); printf(″No.:%ld\nname:%s\nsex:%c\nscore:%f\n″,(*p).num,(*p).name,(*p).sex,(*p).score); } 运行结果: No.:89101       name:LiLin sex:M score:89.500000 定义指针变量p,指向struct student 类型的数据 p指向的结构体变量中的成员

9.3.1 指向结构体变量的指针变量 图9-7 程序分析: 在函数的执行部分将结构体变量stu-1的起始地址赋给指针变量p,也就是使p指向stu-1,然后对stu-1的各成员赋值。第一个printf函数是输出stu-1的各个成员的值。用stu-1.num表示stu-1中的成员num,依此类推。第二个printf函数也是用来输出stu-1各成员的值,但使用的是(*p).num这样的形式。

9.3.1 指向结构体变量的指针变量 以下3种形式等价: 其中->称为指向运算符。 ① 结构体变量.成员名 ②(*p).成员名 p->成员名 其中->称为指向运算符。 请分析以下几种运算: p->n得到p指向的结构体变量中的成员n的值。 p->n++ 得到p指向的结构体变量中的成员n的值,用完该值后使它加1。 ++p->n 得到p指向的结构体变量中的成员n的值加1,然后再使用它。

9.3.2 指向结构体数组的指针 11.6.2 指向结构体数组的指针 运行结果: 例9.4 指向结构体数组元素的指针的应用 #include <stdio.h> struct student {int num;char name[20];char sex;int age;}; struct student stu[3]={{10101,″Li Lin″,′M′,18},{10102,″Zhang Fun″,′M′,19},{10104,″WangMing″,′F′,20}}; void main() { struct student *p; printf(″ No. Name sex age\n″); for (p=str;p<str+3;p++) printf(″%5d %-20s %2c %4d\n″,p->num, p->name, p->sex, p->age); } 11.6.2 指向结构体数组的指针 运行结果: No.  Name  sex age  10101 LiLin M  18  10102  Zhang Fun   M  19  10104 WangMing   F  20  

9.3.2 指向结构体数组的指针 图9-8 程序分析: p是指向struct student结构体类型数据的指针变量。在for语句中先使p的初值为stu,也就是数组stu第一个元素的起始地址。在第一次循环中输出stu[0]的各个成员值。然后执行p++,使p自加1。p加1意味着p所增加的值为结构体数组stu的一个元素所占的字节数。执行p++后p的值等于stu +1,p指向stu[1]。在第二次循环中输出stu[1]的各成员值。在执行p++后,p的值等于stu+2,再输出stu [2]的各成员值。在执行p++后,p的值变为stu +3, 已不再小于stu+3了,不再执行循环。

9.3.2 指向结构体数组的指针 注意: 请注意以上二者的不同。 (1) 如果p的初值为stu,即指向第一个元素,则p加1后p就指向下一个元素。例如: (++p)->num 先使p自加1,然后得到它指向的元素中的num成员值(即10102)。 (p++)->num 先得到p->num的值(即10101),然后使p自加1,指向stu[1]。 请注意以上二者的不同。

 9.3.2 指向结构体数组的指针 注意: 例如: p=stu[1].name; (2) 程序已定义了p是一个指向struct student类型数据的指针变量,它用来指向一个struct student类型的数据,不应用来指向stu数组元素中的某一成员。 例如: p=stu[1].name; 如果要将某一成员的地址赋给p,可以用强制类型转换,先将成员的地址转换成p的类型。 例如:p=(struct student *)stu[0].name; 

§9.3 结构体指针 9.3.3 结构体变量和指向结构体的指针作函数参数 将一个结构体变量的值传递给另一个函数,有3个方法: 用结构体变量的成员作参数。 (2) 用结构体变量作实参。 (3) 用指向结构体变量(或数组)的指针作实参,将结构体变量(或数组)的地址传给形参.

§9.3 结构体指针 例9.5 有一个结构体变量stu,内含学生学号、姓名和3门课程的成绩。要求在main函数中赋予值,在另一函数print中将它们输出。今用结构体变量作函数参数。 #include <stdio.h> struct student { int num; char name[20]; float score[3]; }; 11.6.2 指向结构体数组的指针

§9.3 结构体指针 void main() { void print(struct student); struct student stu; stu.num=12345;strcpy(stu.name, ″LiLin″;stu.score[0]=67.5;stu.score[1]=89;stu.score[2] =78.6); print(stu); } void print(struct student stu) { printf(FORMAT,stu.num,stu.name, stu.score[0], stu.score[1],stu.score[2]); printf(″\n″);} 运行结果: 12345 Li Li 67.500000 89.000000 78.599998

例9. 6 将上题改用指向结构体变量的指针作实参。 #include <stdio 例9.6 将上题改用指向结构体变量的指针作实参。 #include <stdio.h> struct student { int num; char name[20]; float score[3]; };stu={12345, ″LiLi″,67.5,89,78.6}; void main() {void print(struct student *); /*形参类型修改成指向结构体的指针变量*/ print(&stu);} /*实参改为stu的起始地址*/ void print(struct student *p) /*形参类型修改了*/ { printf(FORMAT,p->num,p->name, p->score[0],p->score[1],p->score[2]); /*用指针变量调用各成员的值*/ printf(″\n″);} 运行结果: 12345 Li Li 67.500000 89.000000 78.599998

§9.3 结构体指针 图9-9 程序分析: 此程序改用在定义结构体变量stu时赋初值,这样程序可简化些。print函数中的形参p被定义为指向struct student类型数据的指针变量。注意在调用print函数时,用结构体变量str的起始地址&stu作实参。在调用函数时将该地址传送给形参p(p是指针变量)。这样p就指向stu。在print函数中输出p所指向的结构体变量的各个成员值,它们也就是stu的成员值.   main函数中的对各成员赋值也可以改用scanf函数输入.

§ 9.4 用指针处理链表 9.4.1 链表概述 链表的组成: 链表是一种常见的重要的数据结构,是动 态地进行存储分配的一种结构。 头指针:存放一个地址,该地址指向一个元素 结点:用户需要的实际数据和链接节点的指针 图9-10

§ 9.4 用指针处理链表 用结构体建立链表: struct student { int num; float score;     struct student *next ;}; 其中成员num和score用来存放结点中的有用数据(用户需要用到的数据),next是指针类型的成员,它指向struct student类型数据(这就是next所在的结构体类型) 图9-11

§ 9.4 用指针处理链表 9.4.2 建立简单的静态链表 运行结果: 1010189.5 1010390.0 1010785.0 例9.7 建立一个如图9.11所示的简单链表,它由3个学生数据的结点组成。输出各结点中的数据。 #include <stdio.h> #define NULL 0 struct student {long num; float score; struct student *next; }; main() { struct student a,b,c,*head,*p; a. num=99101; a.score=89.5; b. num=99103; b.score=90; c. num=99107; c.score=85; head=&a; a.next=&b; b.next=&c; c.next=NULL; p=head; do {printf("%ld %5.1f\n",p->num,p->score); p=p->next; } while(p!=NULL); }

§ 9.4 用指针处理链表 程序分析: 开始时使head指向a结点,a.next指向b结点,b.next指向c结点,这就构成链表关系。“c.next=NULL” 的作用是使c.next不指向任何有用的存储单元。在输出链表时要借助p,先使p指向a结点,然后输出a结点中的数据,“p=p->next” 是为输出下一个结点作准备。p->next的值是b结点的地址,因此执行“p=p->next”后p就指向b结点,所以在下一次循环时输出的是b结点中的数据。

§ 9.4 用指针处理链表 9.4.3 建立动态链表 所谓建立动态链表是指在程序执行过程中从 无到有地建立起一个链表,即一个一个地开辟结 图9-12 9.4.3 建立动态链表 所谓建立动态链表是指在程序执行过程中从 无到有地建立起一个链表,即一个一个地开辟结 点和输入各结点数据,并建立起前后相链的关系 例9.8 写一函数建立一个有3名学生数据的单向动 态链表. 算法如图

§ 9.4 用指针处理链表 算法的实现: 我们约定学号不会为零,如果输入的学号为 0,则表示建立链表的过程完成,该结点不应连 接到链表中。 如果输入的p1->num不等于0,则输入的是第 一个结点数据(n=1),令head=p1,即把p1的值 赋给head,也就是使head也指向新开辟的结点p1 所指向的新开辟的结点就成为链表中第一个结点 图9-13

§ 9.4 用指针处理链表 算法的实现: 再开辟另一个结点并使p1指向它,接着输入该 结点的数据. 图9-14 如果输入的p1->num≠0,则应链入第2个结点 (n=2), 将新结点的地址赋给第一个结点的 next成员. 接着使p2=p1,也就是使p2指向刚才建 立的结点

§ 9.4 用指针处理链表 算法的实现: 再开辟一个结点并使p1指向它,并输入该结点的 数据. 在第三次循环中,由于n=3(n≠1),又 将p1的值赋给p2->next,也就是将第 3个结点连接到第2个结点之后,并使p2= p1,使p2指向最后一个结点. 图9-15

§ 9.4 用指针处理链表 算法的实现: 再开辟一个新结点,并使p1指向它,输入该结 点的数据。由于p1->num的值为0,不再执行循环 ,此新结点不应被连接到链表中. 图9-16 将NULL赋给p2->next. 建立链表过程至此结束,p1最后所指的结点 未链入链表中,第三个结点的next成员的值 为NULL,它不指向任何结点。

§ 9.4 用指针处理链表 建立链表的函数如下: #include <stdio.h> #include <malloc.h> #define NULL 0 //令NULL代表0,用它表示“空地址 #define LEN sizeof(struct student) //令LEN代表struct //student类型数据的长度 struct student { long num; float score; struct student *next; };int n; //n为全局变量,本文件模块中各函数均可使用它

§ 9.4 用指针处理链表 struct student *creat() {struct student *head; struct student *p1,*p2; n=0; p1=p2=( struct student*) malloc(LEN); scanf("%ld,%f",&p1->num,&p1->score); head=NULL; while(p1->num!=0) { n=n+1; if(n==1)head=p1; else p2->next=p1; p2=p1; p1=(struct student*)malloc(LEN); } p2->next=NULL; return(head);

§ 9.4 用指针处理链表 9.4.4 输出链表 首先要知道链表第一个结点的地址,也就是 要知道head的值。然后设一个指针变量p,先指向 第一个结点,输出p所指的结点,然后使p后移 一个结点,再输出,直到链表的尾结点。 图9-17,9-18

§ 9.4 用指针处理链表 例9.9 编写一个输出链表的函数print. void print(struct student *head) {struct student *p; printf("\nNow,These %d records are:\n",n); p=head; if(head!=NULL) do {printf("%ld %5.1f\n",p->num,p->score); p=p->next; }while(p!=NULL); }

§ 9.4 用指针处理链表 可以把例9.7和例9.9合起来加上一个主函数,组 成一个程序,即: #include <stdio.h> #include <malloc.h> #define LEN sizeof(struct student) struct student {long num; float score; struct student *next; }; int n;

§ 9.4 用指针处理链表 struct student *creat() /* 建立链表的函数 */ {struct student *head; struct student *p1,*p2; n=0; p1=p2=( struct student*) malloc(LEN); scanf("%ld,%f",&p1->num,&p1->score); head=NULL; while(p1->num!=0) {n=n+1; if(n==1)head=p1; else p2->next=p1;

p2=p1; § 9.4 用指针处理链表 p1=(struct student*)malloc(LEN); scanf("%ld,%f",&p1->num,&p1->score); } p2->next=NULL; return(head); void print(struct student head) /* 输出链表的函数 */ {struct student *p; printf("\nNow,These %d records are:\n",n);

§ 9.4 用指针处理链表 p=head; if(head!=NULL) do {printf("%ld %5.1f\n",p->num,p->score); p=p->next; }while(p!=NULL); } void main() {struct student *head ; head=creat(); print(head); /* 调用print函数 */

§ 9.5 共用体类型 9.5.1 什么是共用体类型 使几个不同的变量共占同一段内存的结构称为 “共用体”类型的结构. 图9-19 定义共用体类型变量的一般形式为: union 共用体名 { 成员表列 }变量表列;

§ 9.5 共用体类型 例如: union data union data { int i; { int i; char ch; 或 char ch; float f; float f;  }a,b,c; };union data a,b,c;

§ 9.5 共用体类型 共用体和结构体的比较: 结构体变量所占内存长度是各成员占的内存长度之和。每个成员分别占有其自己的内存单元。   共用体变量所占的内存长度等于最长的成员的长度。 共用体和结构体的比较: 结构体变量所占内存长度是各成员占的内存长度之和。每个成员分别占有其自己的内存单元。   共用体变量所占的内存长度等于最长的成员的长度。 例如:上面定义的“共用体”变量a、b、c各占4 个字节(因为一个实型变量占4个字节),而不 是各占2+1+4=7个字节。

§ 9.5 共用体类型 9.5.2 共用体变量的引用方式 例如:前面定义了a、b、c为共用体变量 只有先定义了共用体变量才能引用它,而且不 能引用共用体变量,而只能引用共用体变量中的 成员。 例如:前面定义了a、b、c为共用体变量 a.i (引用共用体变量中的整型变量i) a.ch(引用共用体变量中的字符变量ch) a.f (引用共用体变量中的实型变量f)

§ 9.5 共用体类型 9.5.3 共用体类型数据的特点 (1)同一个内存段可以用来存放几种不同类型的成员,但在每一瞬时只能存放其中一种,而不是同时存放几种。 (2) 共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员就失去作用。 (3) 共用体变量的地址和它的各成员的地址都是同一地址。

§ 9.5 共用体类型 (4) 不能对共用体变量名赋值,也不能企图引用变量名来得到一个值,又不能在定义共用体变量时对它初始化。 (5) 以前的C规定不能把共用体变量作为函数参数,但可以使用指向共用体变量的指针作函数参数。ANSI新标准放宽了限制,允许用共用体变量作为函数参数。 (6) 共用体类型可以出现在结构体类型定义中,也可以定义共用体数组。反之,结构体也可以出现在共用体类型定义中,数组也可以作为共用体的成员。

§ 9.5 共用体类型 例9.10 设有若干个人员的数据,其中有学生和教师。学生的数据中包括:姓名、号码、性别、职业、班级。教师的数据包括:姓名、号码、性别、职业、职务。可以看出,学生和教师所包含的数据是不同的。现要求把它们放在同一表格中。 图9-10

§ 9.5 共用体类型 #include <stdio.h> struct { int num; char name[10]; char sex; char job; union int banji; char position[10]; }category; }person[2];/*先设人数为2*/

11.8 共用体 void main() {int i; for(i=0;i<2;i++) {scanf("%d %s %c %c", &person[i].num, &person[i].name, &person[i].sex, &person[i].job); if(person[i].job == 'S') scanf("%d", &person[i].category.banji); else if(person[i].job == 'T') scanf("%s", person[i].category.position); else printf(“Input error!”);} printf("\n"); printf("No. name sex job class/position\n"); {if (person[i].job == 'S') printf(“%-6d%-10s%-3c%-3c%-6d\n”,person[i].num, person[i].name, person[i].sex, person[i].job, person[i].category.banji); else printf(“%-6d%-10s%-3c%-3c%-6s\n”,person[i].num, person[i].name,person[i].sex, person[i].job, person[i].category.position);}} 11.8 共用体 运行情况如下: 101 Li f s 501 Wang m t professor   No. Name sex jobclass/position 101  Li   f s  501 102  Wang m t professor

9.5 共用体类型 也可以不在结构体类型的声明中声明共用体类型, 而把它放在结构体类型的声明之前,即: {int i; union categ { int banji; char position[10]; }; struct { int num; char name[10]; char sex; char job; union categ category;}person[2];

§9.6 枚举类型 枚举:将变量的值一一列举出来,变量的值只限于列举 出来的值的范围内。 申明枚举类型用enum enum weekday{sun,mon,tue,wed,thu,fri,sat};  定义变量: enum weekday workday,week-day; enum{sun,mon,tue,wed,thu,fri,sat}workday; 变量值只能是sun到sat之一 枚举元素 枚举常量

§9.6 枚举类型 说明: 在C编译中,对枚举元素按常量处理,故称枚举 常量。它们不是变量,不能对它们赋值。 (2) 枚举元素作为常量,它们是有值的,C语言编译 按定义时的顺序使它们的值为0,1,2… (3) 枚举值可以用来作判断比较。 (4) 一个整数不能直接赋给一个枚举变量。

§9.6 枚举类型 算法: 例11.13口袋中有红、黄、蓝、白、黑5种颜色的球若干 个。每次从口袋中先后取出3个球,问得到3种不同色的球 的可能取法,输出每种排列的情况。 算法: 图9-22 9-23

§13.9 枚举类型 #include <stdio.h> main() {enum color {red,yellow,blue,white,black}; enum color i,j,k,pri; int n,loop;n=0; 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;loop<=3;loop++) { switch (loop) { case 1: pri=i;break; case 2: pri=j;break; case 3: pri=k;break; default:break; } §13.9 枚举类型

§13.9 枚举类型 运行情况如下: 1redyellowblue2redyellowwhite3redyellowblack switch (pri) { case red:printf("%-10s","red"); break; case yellow: printf("%-10s","yellow"); break; case blue: printf("%-10s","blue"); break; case white: printf("%-10s","white"); break; case black: printf("%-10s","black"); break; default :break; } printf("\n"); printf("\ntotal:%5d\n",n); §13.9 枚举类型 运行情况如下: 1redyellowblue2redyellowwhite3redyellowblack 58blackwhitered59blackwhiteyellow60blackwhiteblue total:60

§9.7 用typedef命名类型 用typedef声明新的类型名来代替已有的类型名 声明INTEGER为整型 typedef int INTEGER 声明结构类型 Typedef struct{ int month; int day; int year;}DATE;

§9.7 用typedef命名类型 声明NUM为整型数组类型 typedef int NUM[100]; 声明STRING为字符指针类型 typedef int NUM[100]; 声明STRING为字符指针类型 typedef char *STRING; 声明POINTER为指向函数的指针类型,该函数返回 整型值 typedef int (*POINTER)()

§9.7 用typedef命名类型 用typedef定义类型的方法 ① 先按定义变量的方法写出定义体(如:int i)。 ② 将变量名换成新类型名(例如:将i换成COUNT)。 ③ 在最前面加typedef (例如:typedef int COUNT)。 ④ 然后可以用新类型名去定义变量。

§9.7 用typedef命名类型 用typedef定义类型的方法(举例) ① 先按定义数组变量形式书写:int n[100]; ② 将变量名n换成自己指定的类型名: int NUM[100]; ③ 在前面加上typedef,得到 typedef int NUM[100]; ④ 用来定义变量:NUM n;

§9.7 用typedef命名类型 说明: 用typedef可以声明各种类型名,但不能用 来定义变量。 而没有创造新的类型。 (3) 当不同源文件中用到同一类型数据时,常用 typedef声明一些数据类型,把它们单独放在一个文件 中,然后在需要用到它们的文件中用#include命令把 它们包含进来。 (4) 使用typedef有利于程序的通用与移植。

§9.7 用typedef命名类型 说明: (5) typedef与#define有相似之处,例如: typedef int COUNT;#define COUNT int的作用都是 用COUNT代表int。但事实上,它们二者是不同的。 #define是在预编译时处理的,它只能作简单的字符串 替换,而typedef是在编译时处理的。实际上它并不是 作简单的字符串替换,而是采用如同定义变量的方法 那样来声明一个类型