《第11章_结构体---《C语言程序设计》实验指导》由会员分享,可在线阅读,更多相关《第11章_结构体---《C语言程序设计》实验指导(53页珍藏版)》请在金锄头文库上搜索。
1、,第十一章,结构体与共用体,主要内容,11.1 概述11.2 定义结构体类型变量的方法11.3 结构体变量的引用11.4 结构体变量的初始化11.5 结构体数组 11.指向结构体类型数据的指针 11.7 用指针处理链表11.8 共用体 11.9 枚举类型 11.10 用typedef定义类型,11.1 概述,声明一个结构体类型的一般形式为: struct 结构体名 成员表列;如:struct student int num;char name20;char sex; int age;float score;char addr30; ,结构体名,类型名,成员名,11.2 定义结构体类型变量的方法
2、,(2)在声明类型的同时定义变量 这种形式的定义的一般形式为: struct结构体名 成员表列 变量名表列;,11.3结构体变量的引用,在定义了结构体变量以后,当然可以引用这个变量。但应遵守以下规则: (1)不能将一个结构体变量作为一个整体进行输入和输出。例如: 已定义student1和student2为结构体变量并且它们已有值。printf(%d,%s,%c,%d,%f,%n,student1);,11.3结构体变量的引用,引用结构体变量中成员的方式为结构体变量名.成员名例如, student1.num表示student1变量中的num成员,即student1的num(学号)项。可以对变量的
3、成员赋值,例如:student1.num=10010;“.”是成员(分量)运算符,它在所有的运算符中优先级最高,因此可以把student1.num作为一个整体来看待。上面赋值语句的作用是将整数10010赋给student1变量中的成员num。,11.3结构体变量的引用,(4) 可以引用结构体变量成员的地址,也可以引用结构体变量的地址。例如: scanf(%d,&student1.num); (输入student1.num的值) printf(%o,student1); (输出student1的首地址),11.3结构体变量的引用,但不能用以下语句整体读入结构体变量,例如: scanf(%d,s,
4、c,d,f,s,student1); 结构体变量的地址主要用作函数参数,传递结构体变量的地址。,11.5 结构体数组,一个结构体变量中可以存放一组数据(如一个学生的学号、姓名、成绩等数据)。如果有个学生的数据需要参加运算,显然应该用数组,这就是结构体数组。结构体数组与以前介绍过的数值型数组不同之处在于每个数组元素都是一个结构体类型的数据,它们都分别包括各个成员(分量)项。,11.5 结构体数组,11.5.3 结构体数组应用举例,例11.2对候选人得票的统计程序。设有3个候选人,每次输入一个得票的候选人的名字,要求最后输出各人得票结果。#include #include struct perso
5、n char name20;in count; ;leader3=“Li”,0, “ Zhang”,0, “ Fun”,0,11.6 指向结构体类型数据的指针,一个结构体变量的指针就是该变量所占据的内存段的起始地址。可以设一个指针变量,用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。指针变量也可以用来指向结构体数组中的元素。11.6.1 指向结构体变量的指针 下面通过一个简单例子来说明指向结构体变量的指针变量的应用。,11.6 指向结构体类型数据的指针,11.6.3 用结构体变量和指向结构体的指针 作函数参数 将一个结构体变量的值传递给另一个函数,有3个方法:用结构体变量的成
6、员作参数。(2) 用结构体变量作实参。(3) 用指向结构体变量(或数组)的指针作实参,将结构体变量(或数组)的地址传给形参。,11.6 指向结构体类型数据的指针,11.6.2 指向结构体数组的指针,例11.5 有一个结构体变量stu,内含学生学号、姓名和3门课程的成绩。要求在main函数中赋予值,在另一函数print中将它们输出。今用结构体变量作函数参数。,#include struct student int num; char name20; float score3;,11.7 用指针处理链表,11.7.3处理动态链表所需的函数 库函数提供动态地开辟和释放存储单元的有关函数:malloc
7、函数其函数原型为void *malloc(unsigned int size);其作用是在内存的动态存储区中分配一个长度为size的连续空间。此函数的值(即“返回值”)是一个指向分配域起始地址的指针(类型为void)。如果此函数未能成功地执行(例如内存空间不足),则返回空指针(NULL)。,11.7 用指针处理链表,(2) calloc函数 其函数原型为void *calloc(unsigned ,unsigned size);其作用是在内存的动态存储区中分配个长度为size的连续空间。函数返回一个指向分配域起始地址的指针;如果分配不成功,返回NULL。 用calloc函数可以为一维数组开辟动
8、态存储空间,n为数组元素个数,每个元素长度为Size。,11.7 用指针处理链表,(3) free函数 其函数原型为void free(void *p);其作用是释放由指向的内存区,使这部分内存区能被其他变量使用。是最近一次调用calloc或malloc函数时返回的值。free函数无返回值。 以前的版本提供的malloc和calloc函数得到的是指向字符型数据的指针。 ANSI 提供的malloc和calloc函数规定为void类型。,11.7 用指针处理链表,建立链表的函数如下: #include #include #define NULL 0 /令NULL代表,用它表示“空地址#defin
9、e LEN sizeof(struct student) /令LEN代表struct /student类型数据的长度 struct student long num; float score; struct student *next; ;int n; /n为全局变量,本文件模块中各函数均可使用它,11.7 用指针处理链表,struct student *creat() struct student *head; struct student *p1,*p2; n=0; p1=p2=( struct student*) malloc(LEN); scanf(%ld,%f,&p1-num,&p1
10、-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); scanf(%ld,%f,&p1-num,&p1-score); p2-next=NULL; return(head);,11.7 用指针处理链表,例19 编写一个输出链表的函数print. void print(struct student *head) struct student *p; printf(nNow,These %d records are:n,
11、n); p=head; if(head!=NULL) do printf(%ld %5.1fn,p-num,p-score); p=p-next; while(p!=NULL); ,11.7 用指针处理链表,例11.10写一函数以删除动态链表中指定的结点. 解题思路: 从p指向的第一个结点开始,检查该结点中的num值是否等于输入的要求删除的那个学号。如果相等就将该结点删除,如不相等,就将p后移一个结点,再如此进行下去,直到遇到表尾为止。,11.7 用指针处理链表,可以设两个指针变量p1和p2,先使p1指向第一个结点 。,如果要删除的不是第一个结点,则使p1后移指向下一个结点(将p1-next赋
12、给p1),在此之前应将p1的值赋给p2 ,使p2指向刚才检查过的那个结点 。,11.7 用指针处理链表,删除结点的函数del:struct student *del(struct student *head,long num) struct student *p1,*p2; if (head=NULL)printf(nlist null!n);goto end; p1=head; while(num!=p1-num & p1-next!=NULL) p2=p1;p1=p1-next;if(num=p1-num) if(p1=head) head=p1-next; else p2-next=p1
13、-next; printf(delete:%ldn,num); n=n-1; else printf(%ld not been found!n,num);end;return(head);,11.7 用指针处理链表,11.7.7对链表的插入操作 对链表的插入是指将一个结点插入到一个已有的链表中。为了能做到正确插入,必须解决两个问题: 怎样找到插入的位置; 怎样实现插入。,11.7 用指针处理链表,先用指针变量p0指向待插入的结点,p1指向第一个结点。,将p0-num与p1-num相比较,如果p0-nump1- num ,则待插入的结点不应插在p1所指的结点之前。此时将p1后移,并使p2指向刚才
14、p1所指的结点。,11.7 用指针处理链表,再将p1-num与p0-num比,如果仍然是p0-num大,则应使p1继续后移,直到p0-p1- num为止。这时将p0所指的结点插到p1所指结点之前。但是如果p1所指的已是表尾结点,则p1就不应后移了。如果p0- num比所有结点的num都大,则应将p0所指的结点插到链表末尾。,如果插入的位置既不在第一个结点之前,又不在表尾结点之后,则将p0的值赋给p2-next,使p2-next指向待插入的结点,然后将p1的值赋给p0-next,使得p0-next指向p1指向的变量。,11.7 用指针处理链表,例11.11插入结点的函数insert如下。 str
15、uct student *insert(struct student *head, struct student *stud)struct student *p0,*p1,*p2; p1=head;p0=stud;if(head=NULL) head=p0; p0-next=NULL;elsewhile(p0-nump1-num) & (p1-next!=NULL) p2=p1; p1=p1-next; if(p0-numnum) if(head=p1) head=p0; else p2-next=p0;p0-next=p1; else p1-next=p0; p0-next=NULL; n=n+1; return(head); ,