




免费预览已结束,剩余71页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第九章 l 本章要点 结构体的概念 结构体的定义和引用 结构体数组 l 主要内容 9.1 结构体类型和结构体变量 9.2 结构体数组 9.3 结构体指针 9.4 用指针处理链表 9.5 共用体类型 9.6 枚举类型 9.7 用typedef命名类型 9.1 结构体类型和结构体变量 9.1.1 结构体类型 n问题定义: 有时需要将不同类型的数据组合成一个有机 的整体,以便于引用。如: 一个学生有学号/姓名/性别/年龄/地址等属性 int num; char name20; char sex; int age; int char addr30; 应当把它们组织成一个组合项,在一个组合 项中包含若干个类型不同(当然也可以相同) 的数据项。 图9-1 100101 li fun m 18 87.5 beijing num name sex age score addr n 声明一个结构体类型的一般形式为: struct 结构体名 成员表列; 如:struct student int num;char name20;char sex; int age;float score;char addr30; 结构体名 类型名 成员名 9.1 结构体类型和结构体变量 9.1.1 结构体类型 说明: (1)结构体类型并不是只有一种,而是可以设计出许 多种结构体类型. (2) 成员也可以是一个结构体变量。 (3)“结构体”这个词是根据英文单词 译出的。 9.1 结构体类型和结构体变量 9.1.1 结构体类型 9.1.2 定义结构体类型变量 n可以采取以下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 在定义了结构体变量后,系统会为之分配内 存单元。 例如:student1和student2在turbo c的内存 中各占59个字节(2+20+1+2+4+30=59)。 (2)在声明类型的同时定义变量 这种形式的定义的一般形式为: struct 结构体名 成员表列 变量名表列; 9.1.2 定义结构体类型变量 例如: struct student int num; char name20; char sex; int age; float score; char addr30; student1,student2; 它的作用与第一 种方法相同,即 定义了两个struct student 类型的变 量student1, student2 9.1.2 定义结构体类型变量 (3) 不指定类型名而直接定义结构体类型变量 其一般形式为: struct 成员表列 变量名表列; 即不出现结构体名。 注意:注意: (1) 结构体类型与结构体变量 是不同的概念,不能混同。 (2) 结构体类型中的成员名可 以与程序中的变量名相同,但二 者不代表同一对象。 (3) 对结构体变量中的成员( 即“域”),可以单独使用, 它的作用与地位相当于普通变 量。 9.1.2 定义结构体类型变量 9.1.3 引用结构体变量 n在定义了结构体变量以后,当然可以引用 这个变量。但应遵守以下规则: (1)同类的结构体变量可以互相赋值,如: student1=student2; 不能将一个结构体变量作为一个整体进 行输入和输出。 例如: 已定义student1和student2为结构体变 量并且它们已有值。 printf(%d,%s,%c,%d,%f,%n,student1); 引用结构体变量中成员的方式为 结构体变量名.成员名 例如, student1.num表示student1变量中的 num成员,即student1的num(学号)项。可 以对变量的成员赋值,例如 :student1.num=10010;“.”是成员(分量 )运算符,它在所有的运算符中优先级最高 ,因此可以把student1.num作为一个整体 来看待。上面赋值语句的作用是将整数 10010赋给student1变量中的成员num。 9.1.3 引用结构体变量 (2) 如果成员本身又属一个结构体类型,则要用 若干个成员运算符,一级一级地找到最低 的一级的成员。只能对最低级的成员进行 赋值或存取以及运算。 例如: 对上面定义的结构体变量student1, 可 以这样访问各成员: student1.num student1.birthday.month 注意:注意: 不能用不能用 student1.birthdaystudent1.birthday 来访问来访问student1student1变变 量中的成员量中的成员 birthday,birthday,因为因为 birthdaybirthday本身是一本身是一 个结构体变量。个结构体变量。 9.1.3 引用结构体变量 (3) 对结构体变量的成员可以像普通变量一样 进行各种运算(根据其类型决定可以进行 的运算)。 例如: student2.score=student1.score; sum=student1.score+student2.score; student1.age+; +student2.age; 由于“”运算符的优 先级最高,因此 是对 进 行自加运算,而不是 先对进行自加 运算。 9.1.3 引用结构体变量 (4) 可以引用结构体变量成员的地址,也可以 引用结构体变量的地址。 例如: scanf(%d, (输入student1.num的值) printf(%o,student1); (输出student1的首地址) 9.1.3 引用结构体变量 但不能用以下语句整体读入结构体变量, 例如: scanf(%d,s,c,d,f, s,student1); 结构体变量的地址主要用作函数参数, 传递结构体变量的地址。 9.1.3 引用结构体变量 9.1.4 结构体变量的初始化 但不能用以下语句整体读入结构体变量, 例如: scanf(%d,s,c,d,f, s,student1); 结构体变量的地址主要用作函数参数, 传递结构体变量的地址。 例9.1 对结构体变量初始化. #include void main() struct student long int num; char name20; char sex; char addr20; a=10101,lilin,m,123 beijing road; /* 对结构体变量a赋初值*/ printf(no.:%ldnname:%snsex:%cnaddress:%s n,a.num,,a.sex,a.addr); 运行结果: no.:10101 name:lilin sex: address:123 beijing road 9.2 结构体数组 一个结构体变量中可以存放一组数 据(如一个学生的学号、姓名、成绩等 数据)。如果有个学生的数据需要 参加运算,显然应该用数组,这就是结 构体数组。结构体数组与以前介绍过的 数值型数组不同之处在于每个数组元素 都是一个结构体类型的数据,它们都分 别包括各个成员(分量)项。 9.2 结构体数组 9.2.1 定义结构体数组 和定义结构体变量的方法相仿,只需说明 其为数组即可。例如: struct student int num;char name20;char sex;int age; float score;char addr30; stu3; 以上定义了一个数 组stu,数组有个元 素,均为struct student类型数据。 9.2 结构体数组 也可以直接定义一个结构体数组,例如: struct student int num; ;stu3; 或: strcut student int num; ;stu3; 图9-4 9.2 结构体数组 9.2.2 结构体数组的初始化 与其他类型的数组一样,对结构体数组可以 初始化。例如: struct student int num;char name20; char sex; int age; float score; char addr30; stu210101,lilin, m,18,87.5,103 beijingroad,10102,zhang fun,m,19,99,130 shanghai road; 图9-5 9.2 结构体数组 当然,数组的初始化也可以用以下形式: struct student int num; ; struct student str=, ; 即先声明结构体类型,然后定义数组为该 结构体类型,在定义数组时初始化。 结构体数组初始化的一般形 式是在定义数组的后面加上 “初值表列;”。 9.2 结构体数组 9.2.3 结构体数组应用举例 例9.2对候选人得票的统计程序。设有3个候选人,每次 输入一个得票的候选人的名字,要求最后输出各人得票 结果。 #include #include struct person char name20;in count; leader3; leader3=“li”,0,”zhang”,0,”fan”,0 例9.2 void main() int i,j; char leader_name20; for(i=1;i #include void main() struct studentlong num;char name20; char sex; float score; struct student stu_1; struct student* p; p= stu_1.num=89101;strcpy(stu_1.name,”lilin”); stu_1.sex=m;stu_1.score=89.5; printf(no.:%ldnname:%snsex:%cnscore:%fn, stu_1.num,stu_1.name,stu_1.sex,stu_1.score); printf(no.:%ldnname:%snsex:%cnscore:%fn ,(*p).num,(*p).name,(*p).sex,(*p).score); 定义指针变量p ,指向struct student 类型的数 据 指向的结 构体变量中 的成员 运行结果: :89101 name:lilin sex: score:89.500000 :89101 name:lilin sex: score:89.500000 9.3.1 指向结构体变量的指针变量 程序分析: 在函数的执行部分将结构体变量-的起 始地址赋给指针变量,也就是使指向- ,然后对-的各成员赋值。第一个 函数是输出-的各个成员的值。用 -表示-中的成员,依 此类推。第二个函数也是用来输出 -各成员的值,但使用的是(*) 这样的形式。 图9-7 9.3.1 指向结构体变量的指针变量 以下3种形式等价: 结构体变量成员名 (*)成员名 -成员名 其中-称为指向运算符。 请分析以下几种运算: -得到指向的结构体变量中的成员的值。 - 得到指向的结构体变量中的成员 的值,用完该值后使它加。 - 得到指向的结构体变量中的成员 的值加,然后再使用它。 9.3.2 指向结构体数组的指针 11.6.2 指向结构体数组的指针 例9.4 指向结构体数组元素的指针的应用 #include struct student int num;char name20;char sex;int age; struct student stu3=10101,li lin,m,18,10102, zhang fun,m,19,10104,wangming,f,20; void main() struct student *p; printf( no. name sex age); for (stu;stu;p) printf(%5d %-20s %2c %4dn,p-num, p-name, p-sex , p-age); 运行结果: lilin 18 zhang fun 19 wangming 20 9.3.2 指向结构体数组的指针 程序分析: 是指向struct student结构体类型数据的指针 变量。在for语句中先使的初值为stu,也就是数 组stu第一个元素的起始地址。在第一次循环中输出 stu0的各个成员值。然后执行,使自加 。加意味着p所增加的值为结构体数组stu的 一个元素所占的字节数。执行+后p的值等于stu 1,指向stu1。在第二次循环中输出stu1的 各成员值。在执行后,p的值等于stu+2,再输 出stu 2的各成员值。在执行+后,的值变为 stu +, 已不再小于stu+3了,不再执行循环。 图9-8 9.3.2 指向结构体数组的指针 注意: (1) 如果的初值为stu,即指向第一个元素, 则加后p就指向下一个元素。例如: (+p)-num 先使自加,然后得到它指向 的元素中的num成员值(即10102)。 (p+)-num 先得到-num的值(即10101) ,然后使自加,指向stu1。 请注意以上二者的不同。 9.3.2 指向结构体数组的指针 注意: (2) 程序已定义了是一个指向struct student 类型数据的指针变量,它用来指向一个struct student类型的数据,不应用来指向stu数组元素中的 某一成员。 例如: 1a; 如果要将某一成员的地址赋给p,可以用强制类 型转换,先将成员的地址转换成p的类型。 例如:( *) 0a; 9.3 结构体指针 9.3.3 9.3.3 结构体变量和指向结构体的指针作函数参数结构体变量和指向结构体的指针作函数参数 将一个结构体变量的值传递给另一个函数,有3个方 法: (1)用结构体变量的成员作参数。 (2)(2) 用结构体变量作实参。 (3)(3) 用指向结构体变量(或数组)的指针作实参, 将结构体变量(或数组)的地址传给形参. 9.3 结构体指针 11.6.2 指向结构体数组的指针 例9.5 有一个结构体变量stu,内含学生学号、姓名和3 门课程的成绩。要求在main函数中赋予值,在另一函数 print中将它们输出。今用结构体变量作函数参数。 #include struct student int num; char name20; float score3; ; 9.3 结构体指针 void main() void print(struct student); struct student stu; stu.num=12345;strcpy(, lilin;stu.score0=67.5;stu.score1=89;stu.score2 =78.6); print(stu); void print(struct student stu) printf(format,stu.num,, stu.score0, stu.score1,stu.score2); printf(n); 运行结果 : 67.500000 89.000000 78.599998 例9.6 将上题改用指向结构体变量的指针作实参。 #include struct student int num; char name20; float score3; ;stu=12345, lili,67.5,89,78.6; void main() void print(struct student *); /*形参类型修改成指向结构体的指针变量*/ print( /*实参改为stu的起始地址*/ void print(struct student *p) /*形参类型修改了*/ printf(format,p-num,p-name, p-score0,p-score1,p-score2); /*用指针变量调用各成员的值*/ printf(); 运行结果 : 67.500000 89.000000 78.599998 9.3 结构体指针 程序分析: 此程序改用在定义结构体变量stu时赋初值,这 样程序可简化些。print函数中的形参被定义为指 向struct student类型数据的指针变量。注意在调 用print函数时,用结构体变量str的起始地址stu 作实参。在调用函数时将该地址传送给形参p(p是指 针变量)。这样就指向stu。在print函数中输出 所指向的结构体变量的各个成员值,它们也就是 stu的成员值. main函数中的对各成员赋值也可以改用scanf函 数输入.图9-9 9.4 用指针处理链表 9.4.1 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 9.4.2 建立简单的静态链表建立简单的静态链表 例9.7 建立一个如图9.11所示的简单链表,它由3个学生数据的 结点组成。输出各结点中的数据。 #include #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.next= b.next= c.next=null; p=head; do printf(“%ld %5.1fn“,p-num,p-score); p=p-next; while(p!=null); 运行结果: 1010189.5 1010390.0 1010785.0 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.4.3 建立动态链表建立动态链表 所谓建立动态链表是指在程序执行过程中从 无到有地建立起一个链表,即一个一个地开辟结 点和输入各结点数据,并建立起前后相链的关系 例9.8 写一函数建立一个有3名学生数据的单向动 态链表. 算法如图 图9-12 9.4 用指针处理链表 算法的实现: 我们约定学号不会为零,如果输入的学号为 ,则表示建立链表的过程完成,该结点不应连 接到链表中。 如果输入的p1-num不等于,则输入的是第 一个结点数据(n=1),令headp1,即把p1的值 赋给head,也就是使head也指向新开辟的结点p1 所指向的新开辟的结点就成为链表中第一个结点 图9-13 9.4 用指针处理链表 算法的实现: 再开辟另一个结点并使p1指向它,接着输入该 结点的数据. 如果输入的p1-num,则应链入第个结点 (n=2), 将新结点的地址赋给第一个结点的 next成员. 接着使,也就是使指向刚才建 立的结点 图9-14 9.4 用指针处理链表 算法的实现: 再开辟一个结点并使p1指向它,并输入该结点的 数据. 在第三次循环中,由于(),又 将的值赋给-,也就是将第 个结点连接到第个结点之后,并使 ,使指向最后一个结点. 图9-15 9.4 用指针处理链表 算法的实现: 再开辟一个新结点,并使p1指向它,输入该结 点的数据。由于p1-num的值为,不再执行循环 ,此新结点不应被连接到链表中. 将null赋给p2-next. 建立链表过程至此结束,p1最后所指的结点 未链入链表中,第三个结点的next成员的值 为null,它不指向任何结点。 图9-16 9.4 用指针处理链表 建立链表的函数如下: #include #include #define null 0 /令null代表,用它表示“空地址 #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“, 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); scanf(“%ld,%f“, p2-next=null; return(head); 9.4 用指针处理链表 9.4.4 输出链表 首先要知道链表第一个结点的地址,也就是 要知道head的值。然后设一个指针变量p,先指向 第一个结点,输出所指的结点,然后使后移 一个结点,再输出,直到链表的尾结点。 图9-17,9-18 9.4 用指针处理链表 例99 编写一个输出链表的函数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.1fn“,p-num,p-score); p=p-next; while(p!=null); 9.4 用指针处理链表 可以把例9.7和例9.9合起来加上一个主函数,组 成一个程序,即: #include #include #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“, head=null; while(p1-num!=0) n=n+1; if(n=1)head=p1; else p2-next=p1; 9.4 用指针处理链表 p2=p1; p1=(struct student*)malloc(len); scanf(“%ld,%f“, 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.1fn“,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 什么是共用体类型 使几个不同的变量共占同一段内存的结构称为 “共用体”类型的结构. 定义共用体类型变量的一般形式为: union 共用体名 成员表列 变量表列; 图9-19 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 共用体类型 共用体和结构体的比较: 结构体变量所占内存长度是各成员占的 内存长度之和。每个成员分别占有其自己的 内存单元。 共用体变量所占的内存长度等于最长的 成员的长度。 共用体和结构体的比较: 结构体变量所占内存长度是各成员占的 内存长度之和。每个成员分别占有其自己的 内存单元。 共用体变量所占的内存长度等于最长的 成员的长度。 例如:上面定义的“共用体”变量、各占 个字节(因为一个实型变量占个字节),而不 是各占个字节。 9.5 共用体类型 9.5.2 共用体变量的引用方式 只有先定义了共用体变量才能引用它,而且不 能引用共用体变量,而只能引用共用体变量中的 成员。 例如:前面定义了a、b、c为共用体变量 a.i (引用共用体变量中的整型变量) a.ch(引用共用体变量中的字符变量) a.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 struct int num; char name10; char sex; char job; union int banji; char position10; category; person2;/*先设人数为2*/ 11.8 共用体 void main() int i; for(i=0;i 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) 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
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 天津医保考试题目及答案
- 支付系统应急响应-洞察及研究
- 2025年公需课专业技术人员的职业发展与时间管理考试题(含答案)
- 2025年高压低压电工证考试题库附答案(含各题型)
- 2025年高级经济师《工商管理》试题及答案
- 2025年高级会计师资格实战演练真题解析与答案
- 旅营体制考试题及答案
- 生活类口语试题及答案
- 运动健康饮食试题及答案
- 财务内部群管理办法
- 《电子商务基础(第二版)》课件 第二章 电子商务交易模式
- 2025年交管12123驾驶证学法减分题库(含答案)
- 2025+CSCO胃癌诊疗指南解读
- 《中国高铁发展》课件
- 一级消防工程师消防安全技术综合能力考试真题卷(2025年)
- 南通市2025届高三第二次调研测试语文试题含答案
- 配电室防汛应急预案
- 成都市商品房购买(预售)合同标准版5篇
- 二年级道德与法治上册 第四单元 我们生活的地方 16 家乡新变化教学实录 新人教版
- 2025年部编版小学二年级语文上册全册教案
- 高中主题班会 《铭记历史强国有我》课件-高一上学期爱国主义教育主题班会
评论
0/150
提交评论