结构体、共用休和用户定义类型.ppt_第1页
结构体、共用休和用户定义类型.ppt_第2页
结构体、共用休和用户定义类型.ppt_第3页
结构体、共用休和用户定义类型.ppt_第4页
结构体、共用休和用户定义类型.ppt_第5页
已阅读5页,还剩42页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

全国计算机等级考试 2C课程,第十一讲 结构体、共用体和用户定义类型,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,2,结构体的概念,与数组相比,结构体是一种功能更为强大的构造类型数据。结构体类型可以把不同类型的数据组合成一个整体。 定义方法: struct 结构体名 数据类型1 成员名1; 数据类型2 成员名2; 数据类型n 成员名n; ;,说明: struct是定义结构体类型的关键字; 结构体名、成员名是合法的用户标识符,结构体名可省略(无名结构体) 数据类型n 成员名n 可以是基本类型也可以是其他构造类型; 同一结构体中成员名不可同名; 结构定义语句的分号不可省略; 结构体类型定义只是规定了该结构体类型的组成形式,编译程序并不会给结构体类型分配存储空间。,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,3,结构体类型和结构体变量的定义,应先定义结构体类型,再定义结构体变量,如: struct student int num; char name20; char sex; int age; float score; char addr30; ; struct student stu1,stu2;,又如: #define STUDENT struct student STUDENT int num; char name20; char sex; int age; float score; char addr30; ; STUDENT stu1,stu2;,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,4,结构体类型和结构体变量的定义,也可以直接定义结构体变量。 一般形式: struct 类型标识符 成员名; 类型标识符 成员名; 变量名表列;,如:struct int num; char name20; char sex; int age; float score; char addr30; stu1,stu2;,本例中,结构体类型没有被命名,这称为无名结构体。无名结构体可以用来直接定义变量,但本类型只能使用一次,后面无法再用。,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,5,结构指针变量的定义,结构指针变量说明的一般形式为: struct 结构名 *结构指针变量名 例如,在前面的例题中定义了stu这个结构,如要说明一个指向stu的指针变量pstu,可写为: struct stu *pstu; 当然也可在定义stu结构时同时说明pstu。 结构指针变量也必须要先赋值后才能使用。赋值是把结构变量的首地址赋予该指针变量。 要特别注意的是,不能把结构类型名赋予一个指针变量。如果boy是被说明为stu类型的结构变量,则: pstu=&boy 是正确的; pstu=&stu 是错误的。,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,6,结构体类型和结构体变量的定义,说明 结构体的成员名可以与程序中的变量名相同,二者不代表同一对象。 需要特别说明的是,结构体类型与结构体变量不是一个概念 结构体类型是用户自定义的结构型数据类型,它在定义时并不需要分配内存。你不能给一种结构体类型赋值,当然也不能对它存取和运算。 结构体变量就是具有特定结构体类型的变量,编译时系统将为其分配相应的存储空间。可以对其赋值、存取以及运算。,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,7,结构体类型和结构体变量的定义,例: struct student int num; char name20; char sex; int age; float score; char addr30; ;,注意:这是结构体定义,只描述结构的组织形式,student是结构体类型名,编译时并不为它分配内存,结构体只有在实例化时才为每个结构体成员分配内存。,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,8,结构体类型和结构体变量的定义,结构体中的成员(即“域”),可以是普通变量也可以是一个结构体变量。也就是说结构体可以嵌套使用。,如:struct date int month; int day; int year; ; struct student int num; char name20; struct date birthday; stu;,或:struct student int num; char name20; struct date int month; int day; int year; birthday; stu;,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,9,结构体变量的初始化,形式一: struct 结构体名 类型标识符 成员名; 类型标识符 成员名; . ; struct 结构体名 结构体变量=初始数据;,例: struct student int num; char name20; char sex; int age; char addr30; ; struct student stu1=112,“Wang Lin”,M,19, “200 Beijing Road”;,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,10,结构体变量的初始化,形式二: struct 结构体名 类型标识符 成员名; 类型标识符 成员名; . 结构体变量=初始数据;,例 struct student int num; char name20; char sex; int age; char addr30; stu1=112,“Wang Lin”,M,19, “200 Beijing Road”;,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,11,结构体变量的初始化,形式三: struct 类型标识符 成员名; 类型标识符 成员名; . 结构体变量=初始数据;,例: struct int num; char name20; char sex; int age; char addr30; stu1=112,“Wang Lin”,M,19, “200 Beijing Road”;,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,12,结构体变量的引用,在定义了结构体变量以后,当然可以引用这个变量。 引用规则: 结构体中的成员只能单独使用,它的作用与地位相当于普通变量。 引用方式有三种: 结构体变量名.成员 指针变量名-成员 (*指针变量名).成员 其中成员(分量)运算符“.”,结构指向运算符“-”,与前面已经接触过的下标运算符、圆括号运算符()的优先级均为 1,结合性从左向右,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,13,结构体变量的引用,使用成员(分量)运算符“.”引用结构体成员,如:struct student int num; char name20; char sex; int age; float score; char addr30; stu1,stu2; stu1.score=85.5; stu1.num=10; stu1.score+=stu2.score; stu1.age+;,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,14,结构体变量的引用,使用结构指针变量,往往能更方便地访问结构变量的各个成员,其访问的一般形式为: (*结构指针变量).成员名 或为: 结构指针变量-成员名 例如:(*pstu).num 或者:pstu-num 应该注意,(*pstu)两侧的括号不可少,因为成员符“.”的优先级高于“*”。如去掉括号写作*pstu.num则等效于*(pstu.num),这样,意义就完全不对了。,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,15,结构体变量的引用,示例:结构指针变量的具体说明和使用方法,struct stu int num; char *name; char sex; float score; boy1=102,“Zhang ping“,M,78.5,*pstu; main() pstu= ,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,16,结构体变量的引用,例中, printf语句试图整体引用结构体变量stu1的用法是不可行的。,举例: struct student int num; char name20; char sex; int age; float score; char addr30; stu1,stu2; printf(“%d,%s,%c,%d, %f,%sn”,stu1);,说明: (1)不能将一个结构体变量作为一个整体进行输入和输出。,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,17,结构体变量的引用,说明: (2)但是,将一个结构体变量赋值给另一个结构体变量是允许的,如:struct student int num; char name20; char sex; int age; float score; char addr30; stu1,stu2; stu1=stu2;,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,18,结构体变量的引用,说明: (3)对于嵌套的结构体,内部成员可以逐级引用,例:struct student int num; char name20; struct date int month; int day; int year; birthday; stu1,stu2; stu1.birthday.month=12;,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,19,结构体变量的引用,说明: (4)不能对结构体变量做关系运算,例:struct student int num; char name20; char sex; int age; float score; char addr30; stu1,stu2; if(stu1=stu2) ,例中, 语句if(stu1=stu2) 是错误的,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,20,函数之间结构体变量的数据传递,函数之间结构体变量的数据传递分以下几种情况 (1)向函数传递结构体变量的成员 (2)向函数传递结构体变量 (3)向函数传递结构体的指针 例如:通过函数给结构体成员赋值,#include “stdio.h“ struct AB char a10; int b; ; getdata(struct AB *p) scanf(“%s%d“, ,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,21,动态存储分配,动态存储分配的概念 变量、数组一旦定义,其存储长度在整个程序中是固定不变的,因此被称为“静态存储分配”。然而,实际编程中,有时候所需的内存空间取决于实际输入的数据,无法预先确定。 为了解决上述问题,语言提供了一些内存管理函数,可以按需要动态地分配内存空间,也可把不再使用的空间回收(释放),这种机制称为“动态存储分配”。 常用的动态存储分配函数有以下三个: 分配内存空间函数 malloc 分配内存空间函数 calloc 释放内存空间函数 free 使用以上函数必须有文件包含命令:#include “stdlib.h“,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,22,动态存储分配,分配内存空间函数malloc 调用形式: (类型说明符*)malloc(size) 功能:在内存的动态存储区中分配一块长度为“size“字节的连续区域。函数的返回值为该区域的首地址。 其中“类型说明符”表示把该区域用于何种数据类型。 (类型说明符*)表示把返回值强制转换为该类型指针。 “size”是一个无符号数。 例如:char *pc; pc=(char *)malloc(100); 表示动态分配100个字节的内存空间,并强制转换为字符数组类型,函数的返回值为指向该字符数组的指针,把该指针赋予指针变量pc。,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,23,动态存储分配,分配内存空间函数 calloc calloc 也用于分配内存空间。 调用形式: (类型说明符*)calloc(n,size) 功能:在内存动态存储区中分配n块长度为“size”字节的连续区域。函数的返回值为该区域的首地址。 (类型说明符*)用于强制类型转换。 calloc函数与malloc 函数的区别仅在于一次可以分配n块区域。 例如:struct stu *ps=(struet stu*)calloc(2,sizeof(struct stu); 其中的sizeof(struct stu)是求stu的结构长度。因此该语句的意思是:按stu的长度分配2块连续区域,强制转换为stu类型,并把其首地址赋予指针变量ps。,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,24,动态存储分配,释放内存空间函数free 调用形式: free(void*ptr); 功能:释放ptr所指向的一块内存空间,ptr是一个任意类型的指针变量,它指向被释放区域的首地址。被释放区应是由malloc或calloc函数所分配的区域。 例如:free(pc); free(ps);,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,25,动态链表的概念,如果采用动态分配的办法存储学生记录,一次为一条记录分配一块空间(我们称之为结点),这样就无须预先确定学生的准确人数。如果某学生退学,也可删去该结点,并释放该结点占用的存储空间。 每个结点之间物理上可以是不连续的。结点之间的联系用指针实现,即在结点结构中定义一个成员项存放下一结点的首地址,这个成员,称为指针域。 在第一个结点的指针域内存入第二个结点的首地址,在第二个结点的指针域内又存放第三个结点的首地址,如此串连下去直到最后一个结点。最后一个结点因无后续结点连接,其指针域置为空(NULL) 。这样一种连接方式,在数据结构中称为“链表”。,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,26,动态链表的概念,链表的组成: 链表中的所有结点都是同一种结构类型。包括一个头指针,是一个结构类型的指针变量,用来存放链表第一个结点的首地址; 若干个结点,用来存放用户需要的实际数据以及链接节点的指针。 下图为一简单链表的示意图,头结点head没有数据域,只负责存放第一个结点的首地址。 除head外,每个结点都分为两个域,其中数据域存放各种实际的数据,如学号、姓名等;指针域存放下一结点的首地址。,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,27,动态链表的概念,链表的结点 链表的结点都是结构体类型,如 struct student int num; float score; struct student *next ; ; 其中 成员num和score用来存放结点中用户需要用到的数据; next是指针类型的成员,它指向struct student类型数据(也就是next所在的结构体类型),2019/7/23,作者:张旭仟 版权所有 欢迎盗版,28,链表操作的建立与操作实例,定义链表的结点结构,typedef struct node char name20; struct node *link; stud;,这样就定义了一个单链表的结构,其中char name20是一个用来存储姓名的字符型数组,指针*link是一个用来存储其直接后继的指针。 定义好了链表的结构之后,就可以在数据域中存储适当的数据,如有后继结点,则把链域指向其直接后继,若没有,则置为NULL。,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,29,链表的建立与操作实例,创建链表,stud * creat(int n) stud *p,*h,*s; int i; if(h = (stud *)malloc(sizeof(stud) = NULL) printf(“不能分配内存空间!“); return NULL; h-name0=0; /*把表头结点的数据域置空*/ h-link=NULL; /*把表头结点的链域置空*/ p=h; /*p指向表头结点*/ for(i=0;ilink=s; printf(“请输入第%d个人的姓名“,i+1); scanf(“%s“,s-name); s-link=NULL; p=s; return(h); ,注意:由于用到malloc函数,所以在程序的开始部分应有如下包含命令: #include ,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,30,链表的建立与操作实例,创建遍历链表的函数,main() stud *head; head =creat(3); list(head ); ,void list(stud *head) stud *p,*q; p=head; while(p-link!=NULL) q=p-link; printf(“%sn“,q-name); p=q; ,调用创建和输出链表的主函数,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,31,链表的建立与操作实例,根据数据项的值检索链表中的结点 思路:对单链表的结点依次扫描,检测其数据域是否是我们所要查好的值,若是返回该结点的指针,否则返回NULL。,stud * search( stud *head, char *x) stud *p; char *y; p= head -link; while(p!=NULL) y=p-name; if(strcmp(y,x)=0) return(p); else p=p-link; if(p=NULL) printf(“没有查找到该数据!“); return NULL; ,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,32,链表的建立与操作实例,测试结点检索函数的主函数,main() char fullname20; stud *head,*searchpoint; head=creat(3); printf(“请输入你要查找的人的姓名:“); scanf(“%s“,fullname); searchpoint=search(head,fullname); printf(“你要查找的人的姓名:%sn“,searchpoint-name); ,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,33,链表的建立与操作实例,在单向链表中插入新结点 在单向链表中插入新结点的步骤如下: (1)先创建一个新结点,并用指针p指向该结点。 (2)将q指向的结点的next域的值(即q的后继结点的指针)赋值给p指向结点的next域。 (3)将p的值赋值给q的next域。 通过以上3步就可以实现在链表中由指针q指向的结点后面插入p所指向的结点。可以通过图1-5形象地展示出这一过程。,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,34,链表的建立与操作实例,在单向链表中插入新结点,void insert(stud *p) char stuname20; stud *s; if(s= (stud *) malloc(sizeof(stud)=NULL) printf(“不能分配内存空间!“); exit(0); printf(“输入要插入学生结点的姓名:“); scanf(“%s“,stuname); strcpy(s-name,stuname); s-link=p-link; p-link=s; ,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,35,链表的建立与操作实例,测试插入结点函数的主函数,main() char fullname20; stud *head,*searchpoint; head=creat(2); printf(“输入要在他之后添加结点的那个人的姓名:“); scanf(“%s“,fullname); searchpoint=search(head,fullname); insert(searchpoint); list(head); ,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,36,链表的建立与操作实例,删除单向链表中的结点 在链表内删除节点又三种不同的情形: 1删除第一个节点:只需要将head指向第二个节点 2删除最后一个节点,只需要将指向最后一个节点的指针(引用)指向NULL 3删除中间节点,只要将需要删除节点的指针指向需要删除节点的下一个节点。,stud *del(stud *head,stud *x) stud *p; if(head=x) return head-link; else p=head; while(p-link!=x) p=p-link; if(x-link=NULL) p-link=NULL; else p-link=x-link; return head; ,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,37,链表的建立与操作实例,测试删除结点函数的主函数,main() char fullname20; stud *head,*searchpoint; head=creat(3); printf(“请输入要删除的学生的姓名:“); scanf(“%s“,fullname); searchpoint=search(head,fullname); del(head,searchpoint); ,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,38,链表的建立与操作实例,销毁一个链表 链表使用完毕后建议销毁它,因为链表本身会占用内存空间。如果一个系统中使用了很多链表,而使用完毕后又不及时销毁它,那么这些垃圾空间积累过多,最终可能导致内存泄漏甚至程序崩溃。,void destroy(stud *head) stud *p,*q; p=head; while(p!=NULL) q=p-link; free(p); p=q; head=NULL; ,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,39,共用体的定义,共用体也叫联合体,也是一种构造数据类型。共用体可以使几个不同类型的变量共占同一段内存。 定义形式: union 共用体名 类型标识符 成员名; 类型标识符 成员名; . ; 其中union 是关键字,共用体名是用户自定义标示符。,例:union data int i; char ch; float f; ;,注意:这里的类型定义在编译时也是不分配内存的。,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,40,共用体变量的定义,形式一: union data int i; char ch; float f; ; union data a,b; 形式二: union data int i; char ch; float f; a,b;,共用体变量任何时刻只有一个成员存在。共用体变量在编译时被分配内存, 长度=最长成员所占字节数。,形式三: union int i; char ch; float f; a,b;,2019/7/23,作者:张旭仟 版权所有 欢迎盗版,41,共用体变量的引用,引用方式: 共用体变量名.成员名 共用体指针名-成员名 (*共用体指针名).成员名,例:如有以下定义 union data int i; char ch; float f; ; union data a,b,c,*p,d3;,a.i、a.ch、a.f p-i、p-ch、p-f (*p).i 、(*p).ch、(*p).f d0.i、d0.ch、d0.f,则可以如下方式加以引用

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论