Presentation is loading. Please wait.

Presentation is loading. Please wait.

程序设计基础.

Similar presentations


Presentation on theme: "程序设计基础."— Presentation transcript:

1 程序设计基础

2 第十一章 结构体与共用体 概述 定义结构体类型变量的方法 结构体变量的引用 结构体变量的初始化 结构体数组 指向结构体类型数据的指针
用指针处理链表 共用体 枚举类型 用typedef定义类型

3 11.1 概述 结构体 是这样的一种数据结构,将不同类型的数据组合成一个有机的整体以便引用。 声明一个结构体类型的一般形式
struct 结构体名 {成员列表}; num name sex age score addr 10010 LI Fun M 18 87.5 Beijing struct student {int num; char name[20]; char sex; int age; float score; char addr[30]; } 返回主菜单

4 11.2 定义结构体类型变量的方法 先声明结构体类型再定义变量名 在声明类型的同时定义变量 直接定义结构体类型变量 说明
struct 结构体名 { 成员表列};变量名表列; 直接定义结构体类型变量 struct { 成员表列}变量名表列; 说明 struct student {int num; char name[20]; char sex; int age; float score; char addr[30];}student1,student2; 说明 返回主菜单

5 关于先声明结构体类型再定义变量名的说明 举例说明: struct student {int num; char name[20];
char sex; int age; float score; char addr[30];}; struct student student1,student2; 注意: 将一个变量定义为标准 类型与定义为结构体类型 不同之处在于后者不仅要 求指定变量为结构体类型, 而且要求指定为某一特定 的结构体类型。

6 直接定义结构体类型变量的说明 1)类型与变量是不同的概念,不要混同。只能对变量赋值、存取或运算,而不能对一个类型赋值、存取或运算。在编译时,对类型是不分配空间的,只对变量分配空间。 2)对结构体中的成员(即“域”),可以单独使用,它的作用与地位相当于普通变量。 3)成员也可以是一个结构体变量。 如:struct data struct student; {int month; {int num; int day; char sex; int year; int age; }; struct data birthday; char addr[30];}student1,student2; 4)成员名可以与程序中的变量名相同,二者不代表同一对象。 name sex age birthday month num day year addr

7 student1.birthday.month
11.3 结构体变量的引用 1)不能将一个结构体变量作为一个整体进行输入和输出。 如:printf(“%d.%s,%c,%d,%f,%s\n”,student1); X 只能对结构体变量中的各个成员分别进行输入和输出。 应用结构体成员的方式:结构体变量名.成员名 2)如果成员本身又属于一个结构体类型,则要用若干个成员运算符,一级一级地找到最低的一级的成员。只能对最低级的成员进行赋值或存取以及运算。 3)对结构体变量的成员可以像普通变量一样进行各种运算(根据其类型决定可以进行的运算)。 4)可以引用结构体变量成员的地址,也可以引用结构体变量的地址。 但不能用以下语句整体读入结构体变量. student1.num=10010; student2.score=student1.score; sum=student1.score+student2.score; student1.age++; ++student1.age; student1.birthday.month scanf(“%d”,&student1.num); printf(“%o”,&student1); 返回主菜单 scanf(“%d,%s,%c,%d,%f,%f,%s”,&student1);

8 11.4 结构体变量的初始化 和其他类型变量一样,对结构体变量可以在定义时指定初始值。 例11.1 返回主菜单

9 例11.1 对结构体变量初始化 运行程序 程序设计基础 第十一章 结构体与共用体 main() {struct student
程序设计基础 第十一章 结构体与共用体 例11.1 对结构体变量初始化 main() {struct student {long int num; char name[20]; char sex; char addr[20]; }a={89031,"Li Lin",'M',"123 Beijing Road"}; printf("NO.:%ld\nname:%s\nsex:%c\naddress:%s\n",a.num,a.name,a.sex,a.addr); } 运行程序

10 11.5 结构体数组 定义结构体数组 结构体数组的初始化 结构体数组应用举例 例11.2 返回主菜单

11 关于定义结构体数组的说明 和定义结构体变量的方法相仿, 只需说明其为数组即可。 直接定义一个结构体数组 struct student
{int num; …… }stu[3]; struct ….. struct student {int num; char name[20]; char sex; int age; float score; char addr[30]; }; struct student stu[3];

12 10101 LiLin M 18 27.5 103 Beijing Road 10102 ZhangFun 19 99 130Shanghai 10104 Wang Min F 20 78.5 1010 Zhongshan stu[0] stu[1] stu[2]

13 结构数组初始化说明 定义数组stu时,元素 struct student 个数可以不指定,即可以 {int num; 写成以下形式:
char name[20]; char sex; int age; float score; char add[30];}stu[3]={{1001,”Li Lin”, ‘M’,18,87.5,”103Beijin Road”},{10102, “Zhang Fun”,’M’,19,99,”130 Shanghai Road”},{10104,”Wang Min”,’F’,20, 78.5,”1010 Zhongshan Road”}}; 定义数组stu时,元素 个数可以不指定,即可以 写成以下形式: stu[]={{…},{…},{…}}; 数组的初始化也可以用 以下形式: struct student {int num; …}; struct student stu[]={{…}} ;

14 例 11.2 对候选人得票的统计程序 设有3个候选人,每次输入一个得票的候选人的名字,要求最后输出各人得票结果。 运行程序
程序设计基础 第十一章 结构体与共用体 例 11.2 对候选人得票的统计程序 设有3个候选人,每次输入一个得票的候选人的名字,要求最后输出各人得票结果。 输入:Li Li Fun Zhang LI #include "string.h" struct person {char name[20]; int count; }leader[3]={"Li",0,"Zhang",0,"Fun",0}; main() { int i,j; char leader_name[20]; for(i=1;i<=10;i++) { scanf("%s",leader_name); for(j=0;j<3;j++) if(strcmp(leader_name,leader[j].name)==0) leader[j].count++; } for(i=0;i<3;i++) printf("%5s:%d\n",leader[i].name,leader[i].count); 运行程序

15 11.6 指向结构体类型数据的指针 11.6.1 指向结构体变量的指针 11.6.2 指向结构体数组的指针
用结构体变量和指向结构体的指针作 函数参数 例11.3 例11.4 说明 例11.5 例11.6 返回主菜单

16 用结构体变量和指向结构体的指针作函数参数
将一个结构体变量的值传递给另一个函数,有3个办法: 1)用结构体变量的成员作参数。例如,用stu[1].num或stu[2].name作函数实参,将实参传给形参。用法和用普通变量作实参是一样的,属于“值传递”方式。应当注意实参与形参的类型保持一致。 2)用结构体变量作实参。用结构体变量作实参时,采取的是“值传递”的方式,将结构体变量所占的内存单元的内容全部顺序传递给形参。形参也必须是同类型的结构体变量。在函数调用期间形参也要占用内存单元。这种传递方式在空间和时间上开销较大,如果结构体的规模很大时,开销是很可观的。此外,由于采用值传递方式,如果在执行被调用函数期间改变了形参的值,该值不能返回主调用函数,这往往造成使用上的不便。因此一般较少用这种方法。 3)用指向结构体变量(或数组)的指针作实参,将结构体变量(或数组)的地址传给形参。

17 例11.3指向结构体变量的指针的应用 说明 运行程序 程序设计基础 第十一章 结构体与共用体 #include "string.h"
程序设计基础 第十一章 结构体与共用体 例11.3指向结构体变量的指针的应用 #include "string.h" main() { struct student {long int num; char name[20]; char sex; float score; }stu_1,*p; p=&stu_1; stu_1.num=89101; strcpy(stu_1.name,"Li Lin"); p->sex='M'; p->score=89.5; printf("\nNo:%ld\nname:%s\nsex:%c\nscore:%f\n", stu_1.num,stu_1.name,stu_1.sex,stu_1.score); (*p).num,(*p).name,(*p).sex,p->score); } 说明 运行程序

18 关于指向结构体变量的指针说明 在C语言中,为了使用方便和使之直观,可以把(*p).num改用
p→num来代替,它表示p所指向的结构体变量中的num成员。同 样,(*p).name等价于p→name。 以下三种形式等价: 结构体变量.成员名 (*p).成员名 p→成员名 如p→num,其中→称为指向运算符。 请分析以下几种运算: p→n 得到p指向的结构体变量中的成员n的值

19 p→n++ 得到p指向的结构体变量中的成员n的值,用完该 值后, 使它加1。

20 例11.4 指向结构体数组的指针的应用 程序设计基础 第十一章 结构体与共用体 struct student { int num;
程序设计基础 第十一章 结构体与共用体 例11.4 指向结构体数组的指针的应用 struct student { int num; char name[20]; char sex; int age; }stu[3]={{10101,"Li Lin",'M',18}, {10102,"Zhang Fun",'M',19}, {10104,"Wang Min",'F',20}}; main() { struct student *p; printf("No. Name Sex Age\n"); for(p=stu;p<stu+3;p++) printf("%5d %-20s %2c %4d\n",p->num,p->name,p->sex,p->age); }

21 例11.4 指向结构体数组的指针的应用 p→ stu[0] p’→ 注意 stu[1] p’’→ 运行程序 stu[2]
程序设计基础 第十一章 结构体与共用体 例11.4 指向结构体数组的指针的应用 p→ 10101 Li Lin M 18 10102 Zhang Fun 19 10104 Wang Min F 20 stu[0] p’→ 注意 stu[1] p’’→ 运行程序 stu[2]

22 注意事项 1)如果p的初值为stu,即指向第一个元素,则p加1后p就指向下 一个元素的起始地址。 例如:
(++p) →num先使p加1,然后得到它指向的元素中的num成员值 (即10102), (p++) →num先得到p→num的值(即10101),然后使p自加1, 指向stu[1]。 2)程序已定义了p是一个指向struct student类型数据的指针变量, 它用来指向一个struct student型的数据,不应用来指向stu数组元 素中的某一成员。 例如:p=stu[1].name;X 编译时将给出“警告”信息,表示地址的类型不匹配。如果要将某一 成员的地址赋给p,可以用强制类型转换,先将成员地址转换成p的 类型。 例如:p=(struct student *)stu[0].name;

23 例11.5用结构体变量和指向结构体的指针作函数参数
程序设计基础 第十一章 结构体与共用体 例11.5用结构体变量和指向结构体的指针作函数参数 有一个结构体变量stu,内含学生学号、姓名和3门课的成绩。要求在main函数中赋以值,在另一函数print中将它们打印输出。 #include<string.h> #define FORMAT”%d\n%s\n%f\n%f\n%f\n” struct student {int num; char name[20]; float score[3]; };

24 例11.5用结构体变量和指向结构体的指针作函数参数
程序设计基础 第十一章 结构体与共用体 例11.5用结构体变量和指向结构体的指针作函数参数 #include "string.h" #define FORMAT "%d\n%s\n%f\n%f\n%f\n" struct student {int num; char name[20]; float score[3]; }; main() {void print(struct student); struct student stu; stu.num=12345; strcpy(stu.name,"Li Li"); stu.score[0]=67.5; stu.score[1]=89; stu.score[2]=78.6; print(stu); } void print(struct student stu) {printf(FORMAT,stu.num,stu.name,stu.score[0],stu.score[1],stu.score[2]); printf("\n"); 运行程序

25 例11.6将例11.5改用指向结构体变量的指针作实参 num name stu score[0] p score[1] score[2]
程序设计基础 第十一章 结构体与共用体 例11.6将例11.5改用指向结构体变量的指针作实参 #define FORMAT "%d\n%s\n%f\n%f\n%f\n" struct student {int num; char name[20]; float score[3]; }stu={12345,"Li Li",67.5,89,78.6}; main() {void print(struct student *); print(&stu); } void print(struct student *p) {printf(FORMAT,p->num,p->name, p->score[0],p->score[1],p->score[2]); printf("\n"); stu num name score[0] score[1] score[2] p 运行程序

26 11.7 用指针处理链表 11.7.1 链表概述 11.7.2 简单链表 11.7.3处理动态链表所需的函数 11.7.4建立动态链表
11.7.5输出链表 11.7.6对链表的删除操作 11.7.7对链表的插入操作 11.7.8对链表的综合操作 返回主菜单

27 11.7.1 链表概述 链表是一种常见的重要的数据结构。它是动态地进行存储分配的 一种结构。 1021 1249 1356 1475
head C D A B 1249 1356 说明 1475 1021 NULL

28 链表概述 1)链表有一个“头指针”变量,存放一个地址。该地址指向一个元 素。 2)链表中每一个元素称为“结点”,每个结点都应该包括两个部分:
一为用户需要用的实际数据; 二为下一个结点的地址。 3)链表中各元素在内存中可以不是连续存放的。要找某一元素, 必须先找到上一个元素,根据它提供的下一元素地址才能找到下 一元素。 4)链表的数据结构,必须利用指针变量才能实现。即:一个结点 中应包含一个指针变量,用它存放下一结点的地址。

29 例11.7建立一个简单链表 建立一个简单链表,它由三个学生数据的结点组成。输出各结点中 的数据。 #define NULL 0
程序设计基础 第十一章 结构体与共用体 例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;

30 例11.7 简单链表(续) a.next=&b; b.next=&c; c.next=NULL; p=head; do
程序设计基础 第十一章 结构体与共用体 例11.7 简单链表(续) a.next=&b; b.next=&c; c.next=NULL; p=head; do {printf(“%ld%5.1f\n”,p->num,p->score); p=p->next; }while(p!=NULL); } 运行程序

31 处理动态链表所需的函数 1.malloc函数 void *malloc(unsigned int size);
此函数的值(即“返回值”)是一个指向分配域起始地址的指针。 如果此函数未能成功地执行(如内存空间不足),则返回空指针。 2.calloc函数 void *calloc(unsigned n,unsigned size); 其作用是在内存的动态区存储中分配n个长度为size的连续空间。 函数返回一个指向分配域起始地址的指针;如分配不成功,返回 NULL。 3.free函数 void free(void *p); 其作用是释放由p指向的内存区,使这部分内存区能被其他变量 使用。p是最近一次调用calloc或malloc函数时返回的值。free函数 无返回值。

32 11.7.4建立动态链表 建立动态链表是指在程序执行过程中从无到有地建立起一个链表,
即一个一个地开辟结点和输入各结点数据,并建立起前后相链的 关系。 例11.8

33 例11.8 写一函数建立一个有3名学生数据的单向动态链表。
程序设计基础 第十一章 结构体与共用体 例11.8 写一函数建立一个有3名学生数据的单向动态链表。 算法: 开辟一个新结点,并使 p1,p2指向它 读入一个学生数据给p1所指的结点 Head=NULL,n=0 当读入的p1->num不是零 n=n+1 n等于1? 真 假 head=p1 (把p1所指的结点作为第一个结点) p2->next=p1 (把p1所指的 结点连接到表尾) p2=p1(p2移到表尾) 再开辟一个新结点,使p1指向它 读入一个学生数据给p1所指结点 表尾结点的指针变量置NULL

34 例11.8 写一函数建立一个有3名学生数据的单向动态链表。
程序设计基础 第十一章 结构体与共用体 例11.8 写一函数建立一个有3名学生数据的单向动态链表。 #include<malloc.h> #define NULL 0 #define LEN sizeof(struct student) struct student {long num; float score; struct student *next; }; int n; struct student *creat(void) {struct student *head; struct student *p1,*p2; n=0;

35 例11.8 写一函数建立一个有3名学生数据的单向动态链表。
程序设计基础 第十一章 结构体与共用体 例11.8 写一函数建立一个有3名学生数据的单向动态链表。 p1=p2=(struct student*)malloc(LEN) scanf(“%ld,%f”,&p1->num,&p1->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); } p2->next=NULL; return(head);

36 11.7.5 输出链表 首先,知道链表第一个结点的地址,也就是要知道head的值; 然后,设一个指针变量p,先指向第一个结点,输出p所指向的
结点; 而后,使p后移 一个结点,再输出。 直到链表的尾点。 例11.9

37 例11.9 编写一个输出链表的函数print p=head,使p指向第一结点 p指向的不是尾结点 真 假 输出p所指向的结点 p指向下一结点
程序设计基础 第十一章 结构体与共用体 例11.9 编写一个输出链表的函数print p=head,使p指向第一结点 p指向的不是尾结点 真 假 输出p所指向的结点 p指向下一结点 当p指的不是尾表

38 例11.9 编写一个输出链表的函数print 图示说明 p’ p head 程序设计基础 第十一章 结构体与共用体
程序设计基础 第十一章 结构体与共用体 例11.9 编写一个输出链表的函数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.1f\n”,p->num,p->score); p=p->next; }while(p!=NULL); } p’ p head NULL

39 11.7.6 对链表的删除操作 举例: 一队小孩(A、B、C、D、E)手拉手,如果某一小孩(C)想离队
有事,而队形保持不变。只要将C的手从两边脱开,B改为与D拉手 即可。 A B C D E B 例11.10 A C D E

40 例11.10写一函数以删除动态链表中指定的结点 以指定的学号作为删除结点的标志。例如,输入99103表示要求 删除学号为99103的结点。
程序设计基础 第十一章 结构体与共用体 例11.10写一函数以删除动态链表中指定的结点 以指定的学号作为删除结点的标志。例如,输入99103表示要求 删除学号为99103的结点。 解题思路: 从p指向的第一个结点开始,检查该结点中的num值是否等于输入 的要求删除的那个学号。如果相等就将该结点删除,如不相等, 就将p后移一个结点,再如此进行下去,直到遇到表尾为止。 步骤: 1)设两指针变量p1和p2,先使p1指向第一个结点。如果要删除的 不是第一个结点,则使p1后指向下一个结点。如此一次一次地使p后 移,直到找到所要删除的结点或检查完全部链表都找不到要删除的 结点为止。

41 例11.10写一函数以删除动态链表中指定的结点 2)要区分两种情况: 一、要删除的是第一个节点。这时须将头指针指向原有链表的第 二个元素。
程序设计基础 第十一章 结构体与共用体 例11.10写一函数以删除动态链表中指定的结点 2)要区分两种情况: 一、要删除的是第一个节点。这时须将头指针指向原有链表的第 二个元素。 如下图: p1 head 99101 99103 99107 NULL p1 head 99107 NULL 99101 99103

42 例11.10写一函数以删除动态链表中指定的结点 二、要删除不是第一个结点 p1 head 99107 p2 p1 head 99107 p2
程序设计基础 第十一章 结构体与共用体 例11.10写一函数以删除动态链表中指定的结点 二、要删除不是第一个结点 p1 head 99101 99103 99107 NULL p2 p1 head 99107 NULL 99101 99103 p2

43 链表是一个空表 输出“空表” p1=head p1所指是头结点 输出“找不到”的信息 算法 p2=p1(p2后移一个位置)
程序设计基础 第十一章 结构体与共用体 算法 链表是一个空表 输出“空表” p1=head 当num=p1->num以及p1所指的结点不是表尾结点 p2=p1(p2后移一个位置) P1=p1->next (p1后移一个位置) p1所指是头结点 输出“找不到”的信息 head=p1->next (删除头结点) p2->next= p1->next (删除一个结点) p1是要删除的结点

44 程序设计基础 第十一章 结构体与共用体 例11.10写一函数以删除动态链表中指定的结点 struct student *del(struct student *head,long num) {struct student *p1,*p2; if(head==NULL){printf(“\nlist null! \n”);} 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->next; printf(“delete :%ld\n”,num); n=n-1; } else printf(“%ld not been found! \n”,num); return(head);

45 11.7.7 对链表的插入操作 对链表的插入是指将一个结点插入到一个已有的链表中。 为了能做到正确插入,必须解决两个问题:
怎样找到插入的位置; 怎样实现插入。 例11.11

46 例11.11 插入结点的函数 应用题目: 如果有一群小学生,按身高顺序(由低到高)手拉手排好队。现在
程序设计基础 第十一章 结构体与共用体 例11.11 插入结点的函数 应用题目: 如果有一群小学生,按身高顺序(由低到高)手拉手排好队。现在 来了一名新同学,要求按身高顺序插入队中。 分析: 首先,要确定插到什么位置。 其次,进行插入。 再次,确定插入的位置是否在第一个结点之前,或是链表之尾。

47 例11.11 插入结点的函数 (a) (b) 99107 99107 程序设计基础 第十一章 结构体与共用体 p1 head 99103
程序设计基础 第十一章 结构体与共用体 例11.11 插入结点的函数 p1 head 99101 99107 NULL 99103 99102 p0 (a) p1 head 99107 NULL 99101 99103 p2 (b)

48 例11.11 插入结点的函数 (c) (d) 99107 程序设计基础 第十一章 结构体与共用体 p1 head NULL 99103 p0
程序设计基础 第十一章 结构体与共用体 例11.11 插入结点的函数 p1 head 99101 99102 99107 NULL 99103 p0 p2 (c) head p1 99101 99103 99103 p0 99100 (d)

49 例11.11 插入结点的函数 (d) 99109 程序设计基础 第十一章 结构体与共用体 p1 head 99107 p0 NULL
程序设计基础 第十一章 结构体与共用体 例11.11 插入结点的函数 p1 head 99101 99103 99107 p0 99109 NULL (d)

50 例11.11 插入结点的函数 是 否 p1=head,p0=stud 原来的链表是空表 是 否 将p0所指的结点作为唯一结点
程序设计基础 第十一章 结构体与共用体 例11.11 插入结点的函数 p1=head,p0=stud 原来的链表是空表 是 否 将p0所指的结点作为唯一结点 当p0->num>p1->num以及p1所指的不是表尾结点 p2指向p1位置,p1向后移一个结点 p1->next=p0 p0->next=NULL p2->next =p0 p0->next=p1 n=n+1 p0->num<=p1->num p1指向头结点 head=p0 p0->next =p1

51 程序设计基础 第十一章 结构体与共用体 例11.11 插入结点的函数 struct 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;} else {while((p0->num>p1->num)&&(p1->next!=NULL)) {p2=p1; p1=p1->next;} if(p0->num<=p1->num) {if(head==p1) head=p0; else p2->next=p0; p0->next=p1;} else {p1->next=p0;p0->next=NULL;}} n=n+1; return(head);}

52 11.7.8 对链表的综合操作 将例11.8~11.11中的四个函数顺序排列,用main函数作主调函数。 jiang 运行程序 main()
{struct student *head,stu; long del_num; printf("input Record:\n"); head=creat(); print(head); printf("\ninput the deleted number:"); scanf("%ld",&del_num); head=del(head,del_num); printf("\ninput the inserted record:"); scanf("%ld,%f",&stu.num,&stu.score); head=insert(head,&stu); } 运行程序

53 11.8 共用体 共用体的概念 共用体变量的引用方式 共用体类型数据的特点 特点 例11.12 返回主菜单

54 11.8.1 共用体的概念 有时需要使几种不同类型的变量存放到同一段内存单元中。变量在
内存中占的字节数不同,但都从同一地址开始存放。也就是使用覆 盖技术,几个变量互相覆盖。这种使几个不同的变量共占同一段内 存的结构,称为“共用体”类型的结构。 1000地址 整型 变量 字符变 量ch 实 型变 量 f

55 11.8.1 共用体的概念 定义共用体类型变量的一般形式为 union data union 共用体名
{成员表列}变量表列; 也可以将类型声明与变量定义分开; 也可以直接定义共用体变量 结构体变量所占内存长度是各成员占的内存长度之和。每个成员 分别占有其自己的内存单元。 union data {int i;char ch; float f;}a,b,c; union data {int i;char ch; float f;}; union data a,b,c; union {int i;char ch;float f;}a,b,c;

56 11.8.2 共用体变量的引用方式 只有定义了共用体变量才能引用它。不能引用共用体变量,而只能 引用共用体变量中的成员。 例如:
a.i (引用共用体变量中的整型变量i) a.ch (引用共用体变量中的字符变量ch) a.f (引用共用体变量中的实型变量f) 不能引用共用体变量。 printf(“%d”,a)

57 共用体类型的特点 1)同一个内存段可以用来存放几种不同类型的成员,但在每一瞬 时只能存放其中一种,而不是同时存放几种。也就是说,每一瞬时
只有一个成员起作用,其他的成员不起作用,即不是同时都存在和 起作用。 2)共用体变量中起作用的成员是最后一次存放的成员,在存入一 个新的成员后原有的成员就失去作用。 3)共用体变量的地址和它的成员的地址是同一地址。 4)不能对共用体变量名赋值,也不能企图引用变量名来得到一个 值,又不能在定义共用体变量时对它初始化。 5)不能用共用体变量作为函数参数,也不能使函数带回共用体变量, 但可以使用指向共用体变量的指针。 6)共用体类型可以出现在结构体类型定义中,也可以定义共用体数 组。反之,结构体也可以出现在共用体类型定义中,数组也可以 作为共用体的成员。 例如:&a,&a.i, &a.c,&a.f是同一 地址。 下列是不对的: 1)union {int i;char ch; float f; }a={1,’a’,1.5}; 2)a=1;3) m=a;

58 例11.12共用体举例 设有若干个人员的数据,其中有学生数据和教师。学生的数据中 包括:姓名、号码、性别、职业、班级。教师的数据包括:姓名、
程序设计基础 第十一章 结构体与共用体 例11.12共用体举例 设有若干个人员的数据,其中有学生数据和教师。学生的数据中 包括:姓名、号码、性别、职业、班级。教师的数据包括:姓名、 号码、性别、职业、职务。 num name sex job class position 101 Li f s 501 102 Wang m t prof

59 例11.12共用体举例 循环n次 读入号码、姓名、性别、职业 职业job等于‘s’? 读入class 读入position 输出“输入错”
程序设计基础 第十一章 结构体与共用体 例11.12共用体举例 循环n次 读入号码、姓名、性别、职业 职业job等于‘s’? 读入class 读入position 输出“输入错” 输出:号码、姓名、性别、职业、班级 输出:号码、姓名、性别、职业、职务 job等于’t’? job等于’s’?

60 例11.12共用体举例 运行程序 程序设计基础 第十一章 结构体与共用体 struct
程序设计基础 第十一章 结构体与共用体 例11.12共用体举例 struct {int num;char name[10];char sex;char job; union {int class;char position[10];}category;}person[2]; main() {int n,i; for(i=0;i<2;i++) {scanf(“%d%s%c%c”,&person[i].num,person[i].name,&person[i].sex,&person[i].job); if(person[i].job==‘s’) scanf(“%d”,&person[i].category.class); else if(person[i].job==‘t’) scanf(“%s”,person[i].category.position); else printf(“input error”);} printf(“\n”);printf(“NO. Name sex job class/position\n”); {if(person[i].job==‘s’) printf(“%-6d%-10s%-3c%-3c%-6d\n”,person[i].num,person[i].num,person[i].name, person[i].sex,person[i].job,person[i].category.class); else printf(“%-6d%-10s%-3c%-3c%-6s\n”,person[i].num,person[i].name,person[i].sex, person[i].sex,person[i].job,person[i].category.position);}} 运行程序

61 11.9 枚举类型 枚举是指将变量的值一一列举出来,变量的值只限于列举出来的值 的范围内。 声明枚举类型用enum开头。
11.9 枚举类型 枚举是指将变量的值一一列举出来,变量的值只限于列举出来的值 的范围内。 声明枚举类型用enum开头。 例如:enum weekday{sun,mon,tue,wed,thu,fri,sat}; enum weekday workday,week_end; workday和week_end被定义为枚举变量,它们的值只能是sun到sat 之一。 例如:weekday=mon; week_end=sun; 也可以直接定义枚举变量。 例如:enum{sum,mon,tue,wed,thu,fri,sat}workday,week_end; 说明 例11.13 返回主菜单

62 关于枚举类型的说明 1)在C编译中,对枚举元素按常量处理,故称枚举变量。它们不是 变量,不能对它们赋值。
例如:sun=0;mon=1;是错误的。 2)枚举元素作为常量,是有值的,C语言编译按定义时的顺序使 它们的值为0,1,2, … 在上面定义中,sun的值为0,mon的值为1……sat为6。如果有赋 值语句: workday=mon; workday变量的值为1。这个整数是可以输出的。如: printf(“%d”,workday);将输出整数1。 也可以改变枚举元素的值,在定义时由程序员指定,如: enum weekday{sun=7,mon=1,tue,wed,thu,fri,sat}workday,week_end;定义sun 为7,mon=1,以后顺序加1,sat为6。 3)枚举值可以用来做判断比较。如 if(workday==mon)... if(workday>sun)… 枚举值的比较规则是按其在定义时的顺序号比较。如果定义时未人为指定,则 第一个枚举元素的值认作0。故mon>sun,sat>fri. 下一页

63 关于枚举类型的说明 4)一个整数不能直接赋给一个枚举变量。 例如:workday=2;是不对的。它们属于不同的类型。应先进行强制类型才能
赋值。 workday=(enum weekday)2; 相当于将顺序号为2的枚举元素赋给workday,相当于 workday=tue; 甚至可以是表达式。如: workday=(enum weekday)(5-3);

64 例11.13 枚举类型举例 口袋中有红、黄、蓝、白、黑5种颜色的球若干个。每次从口袋中
程序设计基础 第十一章 结构体与共用体 例11.13 枚举类型举例 口袋中有红、黄、蓝、白、黑5种颜色的球若干个。每次从口袋中 先后取出3个球,问得到3种不同色的球的可能取法,输出每种排 列的情况。 分析: 球只能是5中色之一,而且要判断各球是否同色,应该用枚举类型 变量处理。 设取出的球为i,j,k。i,j,k为5种色球之一,应该用枚举类型变量处 理。

65 例11.13 枚举类型举例 n=0 i从red到black j从red到black k从red变到black 输出一种取法 n=n+1
程序设计基础 第十一章 结构体与共用体 例11.13 枚举类型举例 n=0 i从red到black j从red到black k从red变到black 输出一种取法 n=n+1 输出取法的总数n i!=j k!=i&&k!=j

66 例11.13 枚举类型举例 程序设计基础 第十一章 结构体与共用体 main()
程序设计基础 第十一章 结构体与共用体 例11.13 枚举类型举例 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!=j)&&(k!=j)) {n=n+1;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;} switch(pri) {case red:printf(“%-10s”,”red”);break; case yellow:printf(“%-10s”,”yellow”);break;

67 例11.13 枚举类型举例 loop由1到3 i→pri j→pri k→pri 运行程序 输出 “red” “yellow” “blue”
程序设计基础 第十一章 结构体与共用体 例11.13 枚举类型举例 case blue:printf(“%-10s”,”blue”);break; case white:printf(“%-10s”,”white”);break; case black:printf(“%-10s”,”black”);break; default:break;}} printf(“\n”);}} printf(“\ntotal:%5d\n”,n);} 运行程序 loop由1到3 loop的值 i→pri j→pri k→pri pri的值 red yellow blue white black 输出 “red” “yellow” “blue” “white” “black”

68 11.10 用typedef定义类型 可以用typedet声明新的类型名来代替已有的类型名。 例如:
typedef int INTEGER; typedef float REAL; 以下两句是等价的: int i,j;float a,b; INTEGER i,j;FLOAT a,b; 声明一个新的类型名的方法是: 先按 定义变量的方法写出定义体(如:int i;)。 将变量名换成新类型名(如:将i换成COUNT)。 在最前面加typedef(如:typedef int COUNT)。 然后可以用新类型名去定义变量。

69 11.10 用typedef定义类型 举例说明:(对数组类型的定义类型) 先按定义数组变量形式书写:int n[100];
将变量名n换成自己指定的类型名:int NUM[100]; 在前面加上typedef,得到typedef int NUM[100]; 用来定义变量:NUM n; 习惯上,把用typedef声明的类型名用大写字母标示,以便与系统 提供的标准类型标识符区别。 说明 返回主菜单

70 用typedef定义类型 1)用typedef可以声明各种类型名,但不能定义变量。用typedef
可以声明数组类型、字符串类型,使用比较方便。 例如:int a[10],b[10],c[10]; 使用typedef, typedef int ARR[10]; ARR a,b,c,d; 可以看到,用typedef可以将数组类型和数组变量分离开来,利用 数组类型可以定义多个数组变量。 2)用typedef只是对已经存在的类型增加一个类型名,而没有创 造新的类型。 如:typedef int NUM[10]; 3)typedef与#define有相似之处, 如:typedef int COUNT 和#define COUNT int的作用都是用COUNT 代表int。 事实二者不同: #define是在预编译时处理的,只能做简单的字符串替换; 而typedef是在编译时处理。

71 用typedef定义类型 4)当不同源文件中用到同一类型数据时,常用typedef声明一些数
据类型,把它们单独放在一个文件中,然后在需要用到它们的文 件中用#include命令把它们包含进来。 5)使用typedef有利于程序的通用与移植。有时程序会依赖于硬件 特性,用typedef便于移植。 例如:有的计算机系统int型数据用两个字节,数值范围为-32768~ 32767,而另外一些 机器则以4字节存放一个整数,数值范围为+21 亿。如果把一个C程序从一个以4个字节存放整数的计算机系统移植 到以2个字节存放整数的系统,按一般办法需要将定义变量中的每 个int改为long。将“int a,b,c;”改为“long a,b,c;”,如果程序中有多处 用int定义变量,则要动多处。但用typedef 可以如下改变: typedef int INTEGER; typedef long INTEGER;

72 The end 本章结束


Download ppt "程序设计基础."

Similar presentations


Ads by Google