C语言程序设计(第7章).ppt_第1页
C语言程序设计(第7章).ppt_第2页
C语言程序设计(第7章).ppt_第3页
C语言程序设计(第7章).ppt_第4页
C语言程序设计(第7章).ppt_第5页
已阅读5页,还剩51页未读 继续免费阅读

下载本文档

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

文档简介

第七章 结构体与共用体 高级语言程序设计 计算机基础教研室 本章主要内容 本章介绍:如何自己构造数据类型(构造型数据) l结构体 l内存分配函数 l共用体 l枚举类型 l类型定义 l教学目的与要求 n掌握结构体和共同体类型的说明 n结构体和共用体变量的定义及初始化方法 n掌握结构体与共用体变量成员的引用 n领会存储动态分配和释放 n领会链表的基本概念和基本操作 n领会枚举类型变量的定义 n了解Typedef的作用 l重点与难点 n结构体的基本概念 n结构体类型及变量的定义 n结构数组 n用指针处理链表 n共用体及枚举类型的基本概念 nTypedef的基本概念 C(C+)数据类型 一、结构体 1概述 l 数 组 是构造类数据,其数组元素必须是同一数据类型的 。 l 结构体 也是构造类数据,但其成员可以是任何类型的。 构造类型使用户可以象处理单个变量一样来处理 复杂的数据结构。 诸如学生花名册、通讯录之类的数据,最适合用结构体 来处理。因为这类数据具有如下特点: 每个人信息都是一个复合的构造数据,如由姓名、学号 、性别、年龄、家庭住址、联系电话等“成员”组成。 不同的人,数据的值不同,但都有共同的成员组成。 使用结构体的一般步骤 l根据问题的要求定义一个结构体类型 l用自己定义的结构体类型定义结构体变量 l在程序中使用结构体变量处理问题 比较普通变量的情况: l用系统给定的数据类型定义变量 l在程序中使用变量处理问题 如何定义结构体类型? struct 结构体名 类型标识符 成员名; ; 关键字 用户指定 /*struct 结构体名合称“结构类型标识符”*/ /*成员表列*/ /*此处分号不能省略*/ 一个示例 【例一】 main() struct student int number; char name6; char sex; int age; char address20; ; 本质上,它定义了一个名 为”student”的“结构体类 型”(表头)。 numberName6sexageAddress20 小结:什么是“结构体类型”? l用户自己定义的构造型数据类型 l由若干数据项(成员)组成 l同一结构体中的成员可以具有不同的数据 类型 l注意成员定义与普通变量定义的区别: 成员定义时不为其分配内存 变量定义时为其分配内存 结构体类型的特点: l 组成结构体的成员本身必须是一种已有定义的数据: n基本类型成员(整型/字符型/实型) n指针类型成员 n数组类成员 n其他构造类成员(包括已定义的另一种结构体 ) n 注意:成员变量,故成员名可与变量名同名 n结构体类型可以有千千万万种,表示由若干不同数据项 组 成的复合类型。 l 定义结构体类型时,系统不会为该结构体分配内存(只 是定义类型,而非变量声明) 2、结构体类型变量的定义 定义了以上结构体类型后,struct student 相当于标准数据 类型关键字char, int ,float我们可以用它来定义“结构体 变量”。 在结构体类型定义后,用 struct 结构体名 复合词定义 struct 结构体名 ; struct 结构体名 变量名1,变量名2, 变量名n; 如:struct student a,b30,*p; a 为struct student类型的变量 b 为struct student类型的数组(每个元素都是一个结构 体变量,都有众成员) p 为指向struct student类型的指针变量 还有两种合二为一方法 在定义结构体类型的同时定义结构体类型变量 struct 结构体名 变量名1,变量名2, 变量名n; 直接定义结构体类型变量 struct 变量名1,变量名2, 变量名n; 实际使用中,还可以使用以下形式: 先定义 #define STU struct student 尔后 STU student1,student2; 【例二】定义结构体类 型的同时定义结构体 类型变量。 main() struct student int number; char name6; char sex; int age; char address20; a,b30,*p; 【例三】不定义结构体类 型,直接定义结构体类型 变量。 main() struct int number; char name6; char sex; int age; char address20; a,b30,*p; 其他有关知识 l 实际使用中,还可以使用以下形式: #define STU struct student STU stu1,stu2; l 比较一下两种变量定义方式的异同: l int a,b,c; 定义三个整型变量,每个变量占二个字节,可 单独赋值。 l struct student a,b,c; 定义三个结构体类型变量,每个变量下有若干“ 成员”。其占用的内存长度等于各成员项长度之 和。 示例 【例四】 main() struct student int number; char name6; char sex; int age; char address20; ; printf(“%dn “,sizeof(struct student); 结果: 31 示例 【例五】若有以下定义,则正确的赋值语句为 。 struct complex float real; float image; ; struct value int no; struct complex com; val1; A) com.real=1; B) plex.real=1; C) .real=1; D) val1.real=1; 答案:C).real=1 3、结构体变量的初始化和赋值 l使一个结构体变量获得数据“值”(实际 上是给其各个成员赋值)有三种方法: n 定义时初始化之 n 用赋值语句对各成员分别赋值 n 同类型的结构体变量间相互赋值 如 student1=student2 示例: 定义时初始化之 【例六】 main() struct char name15; char class12; long num; stu=“Wenli“,“Computer“,200113; printf(“%sn%sn%ldn“,,stu.class,stu.num); 结果:结果:WenliWenli Computer 1Computer 1 200113 200113 示例: 用赋值语句对各成员分别赋值 【例七】 main() struct char name15; char class12; long num; stu=“Wenli“,“Computer“,200113; 0=1; stu.class2=A; stu.num=1111; printf(“%s,%s,%dn“,,stu.class,stu.num); 结果:结果: 1 1enlienli, ,CoAputerCoAputer,1111,1111 示例: 用赋值语句对各成员分别赋值 【例七】 main() struct char name15; char class12; long num; stu=“Wenli“,“Computer 1“,200113; 0=1; stu.class2=A; stu.num=1111; printf(“%s,%s,%dn“,,stu.class,stu.num); 结果:结果: 1 1enlienli, ,CoAputerCoAputer,1111,1111 进行所谓“结构体变量赋值”只能逐个成 员进行,不能将结构体变量作为一个整体 进行输入和输出。如对结构体变量stu, 以下语句是错误的: scanf(“%s,%s,%ld”,stu); printf(“%s,%s,%ld”,stu); 正确编程: main() struct char name15; char class12; long num; stu; scanf(“%s“,); scanf(“%s“,stu.class); scanf(“%ld“, printf(“%s,%s,%ldn“,,stu.class,stu.num); 亦可用以下赋值语句: strcpy(,”wenli”); strcpy(stu.class, “Computer”); stu.num=200113; 为什么 啊? 但是如果改为 =”wenli ”是错误的。 4、结构体变量的引用 l 只能引用其成员变量 用圆点(成员运算符)优先级最高 如 val1.no+ sum=.real+.image l 可以将成员变量按普通变量运算方式处理,包 括取地址: ; unsigned months =0,31,28,31,30,31,30,31,31,30,31,30,31; main() struct datetp d; printf(“请输入年 月 日:“); scanf(“%u%u%u“, if (d.year%4=0 printf(“%d年%d月%d日是该年的第%d天。n“, d.year,d.month, d.day, getdays(d); getdays(【2】date) unsigned days=0,i; for(i=1;iage (指针变量名.成员名) 此时: p-age+ 等效于(p-age)+ 先得 到成员值,再使它加1; +p-age 等效于 +(p-age) 先使成 员 值加1,再使用之。 struct tm int hours,minutes,seconds; main() struct tm time; time.hours=time.minutes=time.seconds=0; clrscr(); printf(“Now, press any key to begin my clock.“); getch(); for(;) update( display( update(struct tm *t) (*t).seconds+; if (*t).seconds=60) (*t).seconds=0; (*t).minutes+; if (*t).minutes=60) (*t).minutes=0; (*t).hours+; if(*t).hours=24) (*t).hours=0; delay(); display(struct tm *t) clrscr(); printf(“%d:“,(*t).hours); printf(“%d:“,(*t).minutes); printf(“%dn“,(*t).seconds); delay() long int t; for(t=1;t 结果有什么变化? 7、链表 特点: 按需分配内存 不连续存放 有一个“头指针”(head)变量 每个结点中应包括一个指针变量,用它存放下一结点的 地址。 最后一个结点的地址部分存放一个“NULL” (空地址)。 链表结点定义形式 l 定义形式: struct student int number; char name6; struct student *next; ; 链表操作常用技术语句 l p=p-next 在链表结点间顺序移动指针 将p原来所指结点中next的值赋给p,而p-next值即下一 结点起始地址,故p=p-next 的作用是使p指向下一结点起始 地址。 l p2-next=p1 将新结点添加到现在链表中 如果p2是链表中的末结点,p1指新建结点,此句的功能是 使p1所指新结点变成链表中的新的末结点。 l p2-next=NULL 让p2所在结点成为链表中最后结点 示例 若已建立下面的链表结构,指针p 指向某单向链表的首结点,如下图 所示。 struct node int data; struct node *next; *p; 以下语句能正确输出该链表所有结 点的数据成员data的是 。 A) for ( ;p!=NULL;p+) printf(“%7d,”,p-data); B) for ( ;!p;p=p-next) printf(“%7d,”,(*p).data); C) while (p) printf(“%7d,”,(*p).data); p=p-next; D) while (p!=NULL) printf(“%7d,”, p-data); p+; 答案:C 链表指针p+表示什么? main() struct stu int num; char *name; int age; st=12,“ABC“,100,*p= clrscr(); printf(“%pn“,p+); printf(“%pn“,p+); printf(“%pn“,p+); printf(“%pn“,p+); printf(“%dn“,sizeof(st); 结果: FFD2 FFD8 FFDE FFE4 6 结论: 若p指向某个结构体变量, 则 p+ 的功能是将指针 p 移到本结点后的存储单 元,而不是本结点的下一 个成员处。 所以链表中不能用p+进 行结点间的跳转。 静态链表 的建立 P274 例11.7 #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,%.1fn“,p-num,p-score); p=p-next; while(p!=NULL); 注意有关技巧: 结点是如何定义的? 结点是如何建立的? 如何使诸结点形成链 表? 最后一个结点如何建 立? 如何从一个结点转到 下一结点? 如何遍历所有结点? 二、内存分配函数 1、“动态内存分配”的概念 使用户程序能在运行期间动态地申请和释放内存空间 ,从而更有效地利用内存并提高程序设计的灵活性。 如,为了保证程序的通用性,最大需要建立一个 1000个元素的字符数组,每个数组元素占30个字符,共 需30000个字节存储空间。但程序某次运行时,可能只使 用30个数组元素,于是就有29100个字节的已分配存储空 间被浪费。 此时,可通过动态内存分配技术,将程序设计成运行 时才向计算机申请内存,并在用完时立即释放占用的内存 空间。 使用动态内存分配技术建立的链表称为“动态链表”。 2、动态内存分配函数 P275/P387 以下函数在malloc.h或stdlib.h中定义(n,x为无符号整数 ,p为指针变量): l void *malloc(x) 分配一个长度为x字节的连续空间,分配成功返回起始 地址指针,分配失败(内存不足)返回NULL l void *calloc(n,x) 分配n个长度为x字节的连续空间(成败结果同上) l void *realloc(p,x) 将p所指的已分配空间大小调整为x个字节 l void free(p) 将由以上各函数申请的以p为首地址的内存空间全部释放 动态内存分配 函数使用示例 #include “stdlib.h“ main( ) char *p; p=(char *)malloc(17); if (!p) printf(“内存分配出错“); exit(1); strcpy(p,“This is 16 chars“); /*如果超过16个字符,可能破坏程序其他部分*/ p=(char *)realloc(p,18); if (p=NULL) printf(“内存分配出错“); exit(1); strcat(p,“.“); printf(p); free(p); 结果:结果:This is 16 chars.This is 16 chars. 动态链表的建立和遍历示例 (后进先出的数据结构,即所谓“栈”) #define NULL 0 struct info int data; struct info *next; ; main() struct info *base,*p; int n; base=NULL; for(n=0;ndata=n+1; p-data=n+1; p-next=base; p-next=base; base=p; base=p; while (p!=NULL) while (p!=NULL) printf printf(“%4d“,p-data);(“%4d“,p-data); p=p-next; p=p-next; 结果:10 9 8 7 6 5 4 3 2 1 动态链表的建 立和遍历示例 (以建立P274链表为例) #define NULL 0 struct info long num; int score; struct info *next; ; main() struct info *head,*p1,*p2; int n=1; clrscr(); head=p1=p2=(head=p1=p2=(structstruct info *) info *)mallocmalloc( (sizeofsizeof( (struct struct info); info); printf printf(“ (“请输入第请输入第%d d个同学的学号和成绩个同学的学号和成绩:“,:“,n+);n+); scanf scanf(“%ld,%d“,(“%ld,%d“, while(p1-num!=0) while(p1-num!=0) p1=( p1=(structstruct info *) info *)mallocmalloc( (sizeofsizeof( (structstruct info); info); if(!p1) if(!p1) printf printf(“ (“内存分配出错内存分配出错! “); ! “); exit();exit(); printf printf(“ (“请输入第请输入第%d d个同学的学号和成绩个同学的学号和成绩:“,:“,n+);n+); scanf scanf(“%ld,%d“,(“%ld,%d“, p2-next=p1; p2-next=p1; p2=p1; p2=p1; p2-next=NULL; p2-next=NULL; p1=head; p1=head; while(p1-next!=NULL) while(p1-next!=NULL) printf printf(“%ld,%dn“,p1-num,p1-score);(“%ld,%dn“,p1-num,p1-score); p1=p1-next; p1=p1-next; 三、共用体(联合体) l1、概述 P287 与结构体相似,共用体也是一种用户 自己定义的构造型数据,其成员也可以具 有不同的数据类型,但共用体将几种不同 的数据项存放在同一段内存单元中。所以 ,每一时刻只能有一个成员存在占用 分配给该共用体的内存空间(新进旧出) 。该共用体的数据长度等于最长的成员长 度。 如何定义共用体类型? union 共用体名 类型标识符 成员名; ; 关键字 用户指定 /*union 共用体名合称“共用类型标识符”*/ /*成员表列*/ /*此处分号不能省略*/ 示例 union data int i; char ch; float p; ; 3、共用体变量的声明 用union 共用体名 复合词声明 union 共用体名 ; union 共用体名 变量名1,变量名2, 变量名n; 在定义共用体类型的同时声明 union 共用体名 变量名1,变量名2, 变量名n; 直接声明共用体类型变量 union 变量名1,变量名2, 变量名n; 共用体变量的引用 l 共用体变量的引用与结构体相似 只能引用其成员变量,不能引用共用体变量本 身 正确:printf(“%d”,data.i); 错误:printf(“%d”,data); 不能对共用体变量赋值,不能初始化,不能作 为 函数参数! 见P289示例 允许两个同类型共用体之间相互赋值。 可通过指针引用。 示例 main() union u_type int i; char ch6; long s; ; struct st_type union u_type u; float score3; ; printf(“%dn“,sizeof(struct st_type); 结果:18 示例 main() union example struct int x; int y; in; int a2; e=0,0; e.a0=1; e.a1=2; printf(“%d,%dn“,e.in.x,e.in.y); 结果:1,2 四、枚举类型 l1、概述 P291 所谓“枚举”,是指将变量的值一一列举出来, 变量的值只限于列举出来的值的范围内。 枚举类型也是用户自定义的数据类型,用此 种类型声明的变量只能取指定的若干值之一 。 2、定义枚举类型 一般形式 enum cnred,yellow,blue,while,black; enum daysun,mon,tue,wed,thu,fri,sat; 0 , 1 , 2 , 3, 4, 5 (有值常量) 花括号中间的数据项称“枚举元素”或“枚举常 量”,是用户定义的标识符。 3、枚举型变量的声明 enum cn a,b,c; enum day x,y,z; 亦可在定义类型时同时声明枚举型变量: enum cnred,yellow,blue,white,black a,b,c; 【注意】枚举元素为有值常量,默认为0,1,2,3 但定义时不能将 enum cnred,yellow,blue,while,black; 写成 enum cn0,1,2,3,4; 也不能对元素直接赋值,如red=3; 应先进行强制类型转

温馨提示

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

评论

0/150

提交评论