C程序设计 第9章 自定义数据类型 主讲教师: 鲁 萍 西安建筑科技大学 理学院
第9章 自定义数据类型 结构体变量 结构体数组 结构体与指针 指针与链表 共用体 枚举 小 结 习 题
结构体类型的定义 结构体 链表 例1 学生信息:学号,姓名,成绩1,成绩2,成绩3,平均成绩 要求计算平均成绩,并输出学生的学号,姓名和平均成绩 问题:学生信息包含不同类型的数据 例2 对一个班的若干学生进行管理,实现插入新生信息和删除转学学生信息的功能。 问题:新数据无法和已有数据连续存储 结构体 链表
结构体类型的定义 例1学生信息:学号,姓名,成绩1,成绩2,成绩3,平均成绩 要求计算平均成绩,并输出学生的学号,姓名和平均成绩 要求计算平均成绩,并输出学生的学号,姓名和平均成绩 struct student{ int num; char name[20]; float score1; float score2; float score3; float aver; }; 结构体类型: 不同类型的数据的有序集合 struct 类型名称 { 成员表列 }; 结构体变量: 用结构体类型说明的变量 (定义结构体类型不分配内存单元!定义结构体变量时分配存储单元) //定义2个结构体变量 struct student stu1,stu2; struct student stu[3]; //定义3个元素的结构体数组
结构体变量的初始化 定义时初始化:将各元素初值放在“{ }”里赋值给变量。 例: struct student{ int num; char name[20]; float score1; float score2; float score3; float aver; } stu[3]={{001,"zhang3",80,88,75}, {002,"li4",90,83,84}, {003,"wang5",50,62,65}}; 可以这样定义结构体变量
结构体变量的定义 存储: (1)结构体的所有成员各自占用不同的内存单元 stu[0] (2)一共占用多少字节存储单元? stu1 int num char name[20] float score1 float score2 float score3 float aver 存储: (1)结构体的所有成员各自占用不同的内存单元 (2)一共占用多少字节存储单元? sizeof( struct student) stu1 001 “zhang3” 80 88 75 002 “li4” 90 83 84 stu[0] stu[1] stu[2] 38字节 int num char name[20] float score1 float score2 float score3 float aver stu2 struct student{ int num; char name[20]; float score1; float score2; float score3; float aver; }stu1,stu2; stu[3];
结构体 变量引用 例11-1要求计算平均成绩,并输出学生的学号,姓名和平均成绩 for(i=0;i<3;i++) num name[20] score1 score2 score3 aver struct student{ int num; char name[20]; float score1; float score2; float score3; float aver; }stu[3]={{001,"zhang3",80,88,75}, {002,"li4",90,83,84}, {003,"wang5",50,62,65}}; stu[0] 001 “zhang3” 80 88 75 002 “li4” 90 83 84 num name[20] score1 score2 score3 aver stu[1] for(i=0;i<3;i++) { aver= score1+ score2+ score3; aver /=3; } stu[i]. stu[i]. stu[i]. stu[i]. stu[i]. 成员的引用方式:结构体变量名. 成员名
结构体变量引用 × A0901:学生信息:学号,姓名,成绩1,成绩2,成绩3,平均成绩 要求计算平均成绩,并输出学生的学号,姓名和平均成绩 要求计算平均成绩,并输出学生的学号,姓名和平均成绩 for(i=0;i<3;i++) printf("%5d%20s%8.2f\n",stu[i].num,stu[i].name,stu[i].aver); 输出学生的所有信息 printf(”%d,%s,%f,%f,%f,%f\n”,stud1); 不能对结构体变量整体输入输出,只能对各个成员分别输入输出 printf(”%d,%s,%f,%f,%f,%f\n”,stud1.num, stu1.name, stu1.score1, stu1.score2, stu1.score3, stu1.aver);() ×
结构体例题 A0901 :#include<stdio.h> struct student{ int num; char name[20]; float score1; float score2; float score3;float aver; }; void main() { struct student stu[3]={{001,"zhang3",80,88,75}, {002,"li4",90,83,84}, {003,"wang5",50,62,65}}; int i; for(i=0;i<3;i++) { stu[i].aver=stu[i].score1+stu[i].score2+stu[i].score3; stu[i].aver /=3; } for(i=0;i<3;i++) printf("%5d%20s%8.2f\n",stu[i].num,stu[i].name,stu[i].aver);
指向结构体变量的指针 P A0901 :#include<stdio.h> struct student{ int num; char name[20]; float score1; float score2; float score3;float aver; }stu={001,"zhang3",80,88,75}; struct student *p=&stu; stu. aver=stu. score1+ stu.score2+ stu.score3; stu. aver /=3; printf("%5d%20s%8.2f\n", stu.num, stu.name, stu.aver); P 001 “zhang3” 80 88 75 p-> p-> p-> p-> (*p). p-> (*p). (*p). 1、结构体类指针变量的定义:结构体类型名称 *指针变量名 2、通过指针变量引用成员: 1) 结构体类指针变量名->成员名 (常用) 2) (*结构体类指针变量名).成员名
指向结构体数组的指针 A0901 :#include<stdio.h> struct student{ int num; char name[20]; float score1; float score2; float score3;float aver; }; stu[3]={{001,"zhang3",80,88,75},{002,"li4",90,83,84}, {003,"wang5",50,62,65}}; struct stud *p=stu; for(p=stu;p<stu+3; p++) { p->aver=p->score1+p->score2+p->score3; p->aver /=3; } for(p=stu;p<stu3; p++) printf("%5d%20s%8.2f\n", p->num, p->name, p->aver); 84 83 90 “li4” 002 75 88 80 “zhang3” 001 stu[0] stu[1] stu[2] P p++ 指向数组中的下一个元素
用指针构成链表 不行! 新 增加 一个学生? 数组不能动态定义!新增信息存储单元不连续 链表:可以使物理上不连续的存储单元在逻辑上连续访问 struct student{ int num; char name[20]; float score1; float score2; float score3; float aver; }; 链表:可以使物理上不连续的存储单元在逻辑上连续访问 81.3 75 88 80 “zhang3” 001 struct student *next; 1249 1356 1475 002 85.7 84 83 90 “li4” 指针 59 65 62 50 wang5 003 每个结构中的最后一个是指针, 指向下一个节点的首地址,形成链式结构
构建链表 head A0902例 建立如下链表,由3个学生数据的结点组成。输出各结点中的数据,并计算学生成绩的平均值。 next next 001 89.5 002 90 004 85 =NULL 链表的起始 struct student { int num; float score; struct student *next; }; 标记链表的结束
构建链表 void main() { struct student a,b,c,*head,*p; a.num=001; a.score=89.5; b.num=002; b.score=90; c.num=004; c.score=85; head=&a; a.next=&b; b.next=&c; c.next=NULL; p=head; while ( ) { printf(“%d % f \n”,p->num,p->score); p=p->next; } struct student { int num; float score; struct student *next; }; a b c next head P next P P 001 89.5 next 002 90 next 004 85 p!=NULL NULL P
链表操作:插入、删除 1. malloc 函数: 内存动态存储区中分配一个长度为size的连续空间 2. free函数 释放空间 //动态申请一个节点空间 struct student *d; int len=sizeof(struct student); d=(struct student *) malloc(len); //为节点赋值 scanf("%d",&(d->num)); scanf("%f",&(d->score)); //将节点插入链表 d->next=b.next; b.next=d; //链表删除元素d b.next=d->next free(d); //释放空间 next 003 78 d--> next 001 89.5 a 002 90 next b head 004 85 next =NULL c next
结构体数组练习 A0903:有10人投票,对3个候选人得票进行统计。每此输入一个候选人的名字,要求输出最后统计结果。 【程序思路分析】 将输入的后选人的名字与结构体中的初始名字比较,若两者相等,则将该后选人的票数加1; 投票人数通过循环方式进行控制;有多少人就循环多少次,但每次只能投一个人的票。 结构定义: struct person{ char name[20]; int count; }pers[3]={{"Zhang",0},{"Wang",0},{"Li",0}};
printf("\n"); main(){ struct person{ char name[20]; int count; }pers[3]={{"Zhang",0},{"Wang",0},{"Li",0}}; int i=0,j=0; char nam[20]; for (;i<10;i++){ /*控制投票人数*/ scanf(“%s”,nam); /*输入候选人姓名*/ for(j=0;j<3;j++) /*控制候选人数*/ if(strcmp(nam,pers[j].name)==0) pers[j].count++; } printf("\n"); for(i=0;i<3;i++) printf("%6s %d",pers[i].name,pers[i].count); }
结构体变量嵌套 today.year=2004; today.time.second=15; nextday=today; 成员也可以是一个结构变量。 struct clock { int hour, minute, second;}; struct date { int year, month, day; struct clock time; } today,nextday ; 1. 单独引用结构体变量的成员 today.year=2004; today.time.second=15; 2. 结构体变量作为一个整体引用 nextday=today;
共用体 union data{ 共用体类型定义 int i; 使几种不同类型的变量存放到同一内存单元中,相互覆盖。 char ch; float f; }; 共用体变量所占内存长度 等于最长的成员的长度 共用体类型定义 使几种不同类型的变量存放到同一内存单元中,相互覆盖。 union 类型名称{ 成员表列 }; 变量定义:方法同结构体 变量引用 共用体变量名.成员名称 a,b,c; 地址 1000 例:a.i=1; a.ch=‘A’; a.f=10.50; 完成上述赋值操作后,有效的成员是a.f 整形 i 变量 字符变量ch 实 f 型 变 量
枚举类型 一、枚举类型的定义[格式]: enum 枚举类型名称 {枚举类成员名} 例:enum weekday{sun,mon,tue,wed,thu,fri,sat}; 0 1 2 3 4 5 6 枚举元素从数值0开始编号,按常量处理 例: main(){ enum weekday{sun,mon,tue,wed,thu,fri,sat}; enum weekday today=mon; printf(“today=%d ",today); } 运行结果: today=1
小结——自定义数据类型 结构体: 共用体 枚举 struct student{ int num; char name[20]; float score1; float score2; float score3; float aver; }stu,s[3]; 结构体: 结构体变量的引用 结构体数组 用指针访问结构体 构建链表 共用体 枚举 next 001 89.5 002 90 004 85
习 题 B0901(习题9.1) 定义一个结构体变量(包括年、月、日)。计算该日在本年中是第几天,注意闰年的问题 (该程序可扩展为对任意一个班的学生)