第9章 结构体、共用体和枚举类型
《C语言参悟之旅》第九章 结构体 共用体

2. 第二种形式
这种形式在声明类型的同时定义变量。其一般形式为:
struct 结构体类型名
{
数据类型名 1 成员名 1;
… 数据类型名 n
成员名 n;
} 变量名列表;
同样是定义两个 hero 类型变量 wusong 和 sunerniang,用此种形式定义如下:
struct hero {
int number; char sex; char star_name[20]; char name[20]; char nickname[20]; char position[20]; char weapon[20]; } wusong,sunerniang;
//绰号 //职业 //使用武器
} wusong={14,'m',"天伤星","武松","行者","步兵头领","2 把戒刀"}; //定义了结构体变量 wusong 并初始化
定义结构体变量 wusong 但没有初始化时,编译器会给每个成员一个默认值,初始化后 就赋予初始化时的赋值,如图 9.4 所示。
在现实生活中可以用结构体表示的事物比比皆是,例如,我国四大名著之一——《水浒
传》,其中包括性格各异的 108 个人物,如果现在要使用一种 C 语言的数据类型表示这些人 物,结构体无疑是最佳选择。下面用一个名为 hero 的结构体来表示:
struct hero {
int number; char sex; char star_name[20]; char name[20]; char nickname[20]; char position[20]; char weapon[20]; };
C语言数据结构-第9章 结构体共用体与枚举

"Shang Hai","13901000003"}}; int i; for(i=0;i<3;i++) { printf("%s,%d,%s,%s,",stud[i].name,stud[i].age,stud[i].sex,stud[i].xh); printf("%d,%d,%d,",stud[i].birthday.year,stud[i].birthday.month, stud[i].birthday.day); printf("%s,%s,%s\n",stud[i].nation,stud[i].address,stud[i].tel); } }
成员运算符“.”的优先级最高,在表达式中的结构体变量成员不 需要加括号。例如:
wang.age++;
相当于
(wang.age)++;
注意
13
结构体变量的成员名可以相同,但必须处在不同的层次。 例如:
sturct student { int no;
char name[20]; struct { int no; char classname[20]; }class; struct { int no; char groupname[20]; }group; }wang;
定义结构体类型名的同时定义结构体数组,例如:
struct student{…} stud[50];
C语言实验9~12答案

C语言实验9~12答案实验9 指针概念及指针与一维数组的关系任务一1.阅读分析下面程序,写出运行结果,理解指针概念及“*”与“&”的含义。
a=100,b+2=12*p1=100,*p2+2=122.上机验证下列程序的运行结果。
a=5,b=7,p1=1245052,p2=1245048&a=1245052,5,&b=1245048,b=73.分析下面程序,并运行,理解用指针变量进行输入、输出。
输入并验证输出结果即可4.编写程序,实现从键盘输入两个数,输出时从大到小排列(利用指针概念)。
5,9a=5,b=9max=9,min=5任务2 使用指针访问一维数组1.阅读分析下面程序,写出运行结果,理解指针与数组关系。
s=92.阅读下面程序,理解指针、数组的多种表示法。
a[0]=1p[0]=1*(p+0)=1*(a+0)=1a[1]=2p[1]=2*(p+1)=2*(a+1)=2a[2]=3p[2]=3*(p+2)=3*(a+2)=33.在空格中填上语句,以实现字符串复制的功能。
*p2=*p1;p2++;p1++;4.下面程序完成从键盘输入两个字符串a和b,再将a和b的对应位置字符中的较大者存放在数组c中,当一个字符串结束时停止比较,此时将另一个字符串剩下的字符直接放在数组c的后面,填空完成该程序。
#include#includevoid main( ){int k=0;char a[80],b[80],c[80]={'\0'},*p,*q;p=a;q=b;gets(a);gets(b);while(*p!='\0'&&*q!='\0'){if(*p>*q) c[k]=*p;else c[k]=*q;p++;q++;k++;}if(*p!= '\0') strcat(c,p);else strcat(c,q);puts(c );}5.指出下面程序的问题所在(输出a数组的10个元素),理解指针与数组下标的关系及指针变化情况。
实验9 结构体、共用体与枚举类型答案

率。 其次,结构体指针作为函数参数:可以在函数中通过该指针引用结 构体,当在函数中修改了结构体的成员变量后,指针所指向的结构体本 身也被改变了。而当结构体变量作为函数参数;在函数中可通过变量直 接使用结构体,但是,如果在函数中修改了结构体的成员变量后,结构 体本身并未发生变化,只是副本被改变。
} } average = s/5 ; printf("平均成绩:%.2f\n",average); }
4、5位职工的月收入如下表所示: 部门 月收入 工号 姓名 (char (float (int num) (char name) department) salary) 技术科 010002 张援朝 6800 生产科 020006 李明瑞 2600 检验科 030018 王国庆 4800 后勤部 040026 刘小兵 3700 经营科 050068 吴 伟 1900 试编程求这5位职工的平均月收入,并输出月收入小于3000元的职 工的部门、工号、姓名与月收入等信息。源程序以ex9_8.c命名,保存 在自己的文件夹内。
保存在自己的文件夹内。
解: #include <stdio.h> struct bookinfo { char isbn[20]; char title[50]; char author[20]; char publisher[50]; char pubdate[30]; float price; }book[5] = {{"7115177810","Java实用教程","李钟 尉","人民邮电出版社","2008年5月",32.00}, {"7113101015","汇编语言程序设计","白小明","中国铁 道出版社","2009年8月",35.00}, {"7302108535","C语言程序设计","谭浩强","清华大学 出版社","2005年7月",26.00}, {"7301123713","网络工程实用教程","汪新民","北京大 学出版社","2008年2月",34.00}, {"7111283812","软件工程概论","郑人杰","机械工业出 版社","2010年3月",28.00}}; main() { int i; float average, s=0; for(i=0; i<5; i++) { s += book[i].price; if(book[i].price<30.00) { printf("书号:%s ",book[i].isbn); printf("书名:%s ",book[i].title);
C语言各章节单元测试题及答案——结构体与共用体

第9章结构体与共用体9.1典型考试题剖析9.1.1选择题【例1】若指针p已经正确定义,要使p指向两个连续的整型动态存储单元,不正确的语句是。
A) p=2*(int *)malloc(sizeof(int)); B) p=(int*)malloc(2*sizeof(int));C) p=(int *)malloc(2*2); D) p=(int*)calloc(2,sizeof(int));✧考点:动态存储分配函数。
✧分析:根据动态存储分配函数malloc和calloc的函数原型可以知道,calloc函数的调用形式为:void * calloc(unsigned n,unsigned size);表示在动态存储区中分配n个长度为size的连续空间,函数返回一个指向分配域起始地址的指针,因此答案D是正确的。
malloc函数的调用形式为:void * malloc(unsigned int size);表示是在内存的动态存储区分配一个长度为size的连续空间,并返回一个指向分配域起始地址的指针,答案B和C中malloc的参数分别为:2*(sizeof(int))和2*2,都是整型数,因此调用形式正确。
答案A中(int *)malloc(sizeof(int))的返回值为一个地址值,将地址的值乘以2是没有意义的。
✧答案:A【例2】若有以下说明和定义:struct test{ int m1; char m2; float m3;union uu{ char u1[5]; int u2[2]; }ua;}myaa;则sizeof(struct test)的值是。
A) 12 B) 16 C) 14 D) 9✧考点:结构体类型和共用体类型所占内存的字节数。
✧分析:sizeof(struct test)的功能是求结构体类型test所占用的内存字节数。
它应该等于结构体每个成员所占的字节数之和。
m1为int型,占2字节,m2为char型,占1字节,m3为float型,占4字节,接下来是一个共用体类型uu,共用体所占的字节数应该等于成员中最长者所占的字节数,u1占5字节,u2占4字节,那么该共用体类型应该占用5字节,所以2+1+4+5=12。
结构体与共用体

4、共用体类型的变量如何赋初值,含义是什么?
不能对共用体变量名赋值,也不能在定义共用体变量时初始化。但可以用一个共用体变量为 另一个变量赋值
例:union
{ int i;
char ch;
double f;
}a={1,’a’,1.5}; ()
a=1;
()
m=a;
()
例:float x; union { int i; char ch; double f; }a,b; a.i=1; a.ch=‘a’; a.f=1.5; b=a; () x=a.f; ()
二. 枚举类型的应用
• 1.枚举类型变量的定义 ◆先定义枚举类型,再定义枚举类型变量
enum week{sun,mon,tue,wed,thu,fri,
sat};
enum week weekday,workday; ◆定义枚举类型的同时定义枚举变量 enum color {red,blue,green,black}a,b,c;
共用体类型的关键字
union 联合类型名 { 数据类型 成员名1 数据类型 成员名2
...........
数据类型 成员名n };
例:
union utype {
char ch; int i; float f; };
2、如何定义共用体类型的变量
(1)先定义类型,再定义变量,例如: union data /*共用体类型定义*/ { int i;
◆直接定义枚举变量 enum {male,female}sex1,sex2;
枚举类型变量的特点
例 enum DAY {
MON=1, TUE, WED, THU, FRI, SAT, SUN };
(1) 枚举型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,元素之间用逗号,隔开。
C语言第9章结构体、共用体、枚举

结构体变量.成员
struct date { int year;
int month; int day;
“.”是成员运算符, 优先级最高
printf("%d,%d,%d",birth);
printf("%d,%d,%d",birth.year,
}; struct date birth;
birth.month,birth.day);
scanf("%f",&student2.score[2])7; 8
student2
结构变量的整体赋值 student3 = student2;
02 Zhang Zi Liang 88 78
student3
02 Zhang Zi Liang 88 78
湖南工业大学计算机与通信学院
例9-1学生的基本信息包括学号、姓名、3门成绩、平均分、总分。输入一 个学生的前3项基本信息,计算平均分和总分并输出。
湖南工业大学计算机与通信学院
9.1 问题的提出
又如,在学生信息管理系统中填 加个属性:是否是中共党员,如 果不是属性的值为0(int),如
果是属性的值为入党的时间 (char)。在某一时间,属性只有 一种值,而且数据类型不同,这 种情况用什么数据类型描述呢?
对于这种应用,C语言引入了共用体类型。
共用体是一种同一存储区域由不同类型变量共享的数据 类型,它提供—种方法能在同一存储区中操作不同类型 的数据,也就是说共用体采用的是覆盖存储技术,准许 不同类型数据互相覆盖。
基本数据类型并不能方便地解决所有问题
❖ 复合数据类型是基本数据类型迭代派生而来
典型的代表就是“结构”,数组、指针也可算作此类
C语言知识总结——宏,枚举,结构体,共用体

C语言知识总结——宏,枚举,结构体,共用体1、define宏定义以#号开头的都是编译预处理指令,它们不是C语言的成分,但是C程序离不开它们,#define用来定义一个宏,程序在预处理阶段将用define定义的来内容进行了替换。
因此在程序运行时,常量表中并没有用define定义的常量,系统不为它分配内存。
define定义的常量,预处理时只是直接进行了替换,,它用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本。
,因此在编译时它不对宏的定义进行检查,作用域不影响对常量的访问。
它的常量值只能是字符串或数字。
该命令有两种格式:一种是简单的常量宏定义, 另一种是带参数的宏定义。
不带参数的宏:#define< 名字 >< 值 > 要注意,没有结尾的分号,因为不是C的语句,名字必须是一个单词,值可以是各种东西,宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单的代换,字符串中可以含任何字符,可以是常数,也可以是表达式,预处理程序对它不作任何检查。
如有错误,只能在编译已被宏展开后的源程序时发现。
注意.宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起置换。
宏定义其作用域为宏定义命令起到源程序结束。
如要终止其作用域可使用#undef命令带参数的宏:像函数的宏,一般的定义形式:带参宏定义的一般形式为:「#define 宏名」(形参表)字符串,也是没有结尾的分号,可以带多个参数,#define NB(a,b)((a)>(b)?(b):(a)), 也可以组合(嵌套)使用其他宏,注意带参数宏的原则一切都要有括号,参数出现的每个地方都要有括号。
带参数的宏在大型的程序的代码中使用非常普遍,在#和##这两个运算符的帮助下可以很复杂,如“产生函数”,但是有些宏会被inline函数代替(C++的函数)使用宏好处:“提高运行效”。
定义的标识符不占内存,只是一个临时的符号,预编译后这个符号就不存在了。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
9.1 结构体类型与结构体变量 9.2 结构体数组 9.3 向函数传递结构体型数据 9.4 链表 9.5 共用体 9.6 枚举类型 9.7 用户自定义类型
9.1 结构体类型与结构体变量
• 结构体类型的定义
–概述:
• 建立单链表的主要步骤为:
– 生成只含有头结点的空链表; – 然后读取数据信息,生成新结点,将数据存放于新结点中, 插入新结点到单链表中 – 重复第二步,直到输入结束。 根据新结点插入到链表的位置的不同,建立链表的方式, 分为在表尾插入的方法和在表头插入的方法。 •表尾插入: 例9.6 •表头插入: 例9.7
• 共用体变量的定义
–用已定义的共用体类型去定义共用体变量 –定义共用体类型的同时定义变量: –定义无名共用体类型的同时定义变量:
• 共用体变量的引用
–引用方式:共用体变量名.成员名 共用体变量名. 共用体变量名 –说明: 对于共用体变量,只能引用它的成员,而不能引用整个 共用体变量。若共用体的成员是构造类型的,则需要逐级引 用至最低级的成员。 –能通过定义指向共用体的指针变量来引用共用体变量。
在实际应用中,一组相关的数据可能是不同类型的。C语 言提供了包含不同类型成员的类型来定义这样的数据,这 种类型就是结构体类型 结构体类型。 结构体类型
– 定义形式:
struct 结构体名 类型名1 成员名1 {类型名1 成员名1; 类型名2 成员名2 类型名2 成员名2; …… 类型名n 成员名n 类型名n 成员名n; };
• 举例
例9.11 上一页
9.6 枚举类型
• 枚举类型的定义–定义来自式:enum 枚举类型名{枚举常量1,枚举常量2,……,枚举常量n}; •
枚举类型变量的定义和使用
– 定义方式:
• 用已定义的枚举类型去定义变量: • 也可以在定义枚举类型的同时定义变量: • 对于上种方式也可省略枚举类型名: – 引用: • 枚举类型变量的取值范围只能是其所枚举的各个常量。 • 枚举变量的比较相当于比较它们所隐含的整数值。 • 枚举类型变量的值是对应枚举常量所代表整数值。
上一页
• 在链表中插入结点
设指针变量s指向待插入结点,假设指定结点为p。 – 插入到指定结点之后: ① s−>next=p−>next; ② p−>next=s;
– 插入到指定结点之前:首先要找到p的前驱结点q。
例9.8
上一页
• 在链表中删除结点
在一个单链表中删除指定结点,首先要找到该结点的前驱结 点,然后修改前驱结点的指针域指向待删结点的后继结点,然 后释放被删结点。
上一页
9.4 链表
• 链表的特点
–链表是一种动态的进行存储分配的数据结构,程序执行中, 可以在需要时开辟存储单元,在不需要时释放存储单元。 –链表的结点包含数据域和链接域,数据域用来保存数据信 息,链接域用来保存该结点的后继结点或前驱结点的地址。 –一个链表用一个头指针来保存该链表的首地址,即第一个 结点的地址。头指针是一个链表的标志。
• 向函数传递结构体变量
函数调用时,形参也要占用内存空间,因此函数之间传递结 构体变量会带来时间和空间的巨大开销;而且,形参与实参之 间是“值传递”的方式,被调函数对形参结构体变量的修改并 不 能传递给实参,所以虽然语法上允许,但一般很少采用这种传 递方式。 首页 上一页
• 向函数传递结构体变量的地址
• 一个单链表的逻辑示意图
首页 上一页
• 创建链表
– 相关函数:
• malloc函数 1.原型:void *malloc(unsigned int size); 2.功能:在内存的动态存储区中分配size个字节的连续空间, 它的返回值是所分配的那一段空间的起始地址,若分配失 败,则返回一个空指针(0)。 • calloc函数 1.原型:void *calloc(unsigned int n,unsigned int size); 2.功能:内存的动态存储区中分配n个长度为size个字节的 连续空间,它的返回值是指向所分配空间的起始地址,若 分配失败,则返回一个空指针(0)。 • free函数 1.原型:void free(void *p); 2.功能:释放p所指向的内存区,该函数没有返回值。一般 p是调用malloc函数或calloc函数的返回值。 上一页
• 举例
例9.12 上一页
9.7 用户自定义类型
• 用户自定义类型的含义和格式
–含义:用户自定义类型是对已存在的标准类型或已定义
了的类型起一个新名字,而不是去定义原来没有的类型。
–步骤:
• 定义相应类型的变量; • 将变量名用新类型名替换; • 在最前面加上 typedef。 这样,一个新类型就声明了,可以用其去定义变量。
• 举例
例9.1 上一页
9.2 结构体数组
• 结构体数组的定义、初始化
– 结构体数组的定义: • 可以定义结构体类型后再定义数组; • 也可以在定义结构体类型的同时定义数组。 例如:struct student {int number; char name[8]; float score[3]; float ave; }stu[3]={{1001,"zhang",{80,78,67}}, {1002, "wang",{98,78,86}}, {1003, "li",{79,89,68}} }; 首页 上一页
• 结构体数组的引用
–引用形式1: 数组名[下标 成员名 数组名 下标].成员名 下标
• stu[1].number; 表示第1个学生的学号 • stu[0].score[2] ; 表示第0个学生的第2门课的成绩 –引用形式2: 通过指针引用结构体数组的元素及其成员 若已有前面的定义,ps指向stu[0],那么: • (*ps).number; 表示第0个学生的学号 • ps−>name; 表示第0个学生的姓名 • (++ps)−>ave; 表示先将指针ps向后移动,指向stu[1], 即该式表示第1个学生的平均成绩
– 注意:
• typedef只能声明类型名,不能用于定义变量。 • typedef和#define的区别: – 一是#define在预编译时处理,只是一种简单的替换; 而typedef在编译的时候处理,它并不是替换,是用 新类型名去定义变量。 – 二是#define是预处理命令,不能加分号;而typedef 是类型声明语句,以分号结束。 上一页
• 用typedef声明基本类型
– 形式: typedef 基本类型名 新类型名; 新类型名; 首页 上一页
• 用typedef声明构造类型
– 数组类型的声明
typedef 数据类型名 数组类型名[数组长度];
– 结构体类型的声明
typedef struct {类型名 成员名1; 类型名 成员名2; …… 类型名 成员名n; }结构体类型名;
– 注意
指向结构体变量的指针,与指向结构体变量的成员地指 针是不同类型的,它们之间不能直接相互赋值,则必须先进 行强制类型转换,转换为需要的类型,再赋值。
• 举例
例9.2 上一页
9.3 向函数传递结构体型数据
• 向函数传递结构体变量的成员
用结构体变量的成员作函数的实参,要注意作为实参的结构 体变量的成员的类型要与形参的类型相匹配。形参与实参之间 是“值传递”的方式。
例9.9
• 举例
例9.10
上一页
9.5 共用体
• 共用体类型的定义
–概述
共用体类型是由类型不同的、固定个数的成员所组成;所 有的共用体成员共占同一段内存,在微观上看,某一时刻 只能有某一个成员起作用,其它成员是不存在的。
– 定义形式:
union 共用体名 {类型名 成员名 ; 类型名1 类型名 成员名1; 类型名2 成员名2; 类型名 成员名 ; …… 类型名n 成员名n; 类型名 成员名 ; }; ; 首页 上一页
向函数传递结构体变量的地址是地址传递方式,被调函数中 可以通过实参传来的结构体变量的地址引用结构体变量,从而 在被调函数中对结构体变量的修改,也就间接的达到了改变主 调函数中的结构体变量的值的目的。 例9.3
• 向函数传递结构体数组
向函数传递结构体数组与传递其它的数组一样,实质上传递 的是数组的首地址,形参数组与实参数组共占内存单元。 例9.4
– 共用体类型的声明
typedef union {类型名 成员名1; 类型名 成员名2; …… 类型名 成员名n; }共用体类型名;
上一页
• 用户自定义类型的应用
– 应用:
• 对比较复杂且使用比较频繁的类型,可以用typedef声明 来简化程序的书写。 • 用typedef声明类型有助于提高程序的可移植性。
结构体数组stu的逻辑示意图为:
对于结构体类型的一维数组、二维数组,也可以定义指向 它们的指针变量,例如: struct student *ps=stu; 表示指针变量ps指向结构体数组stu的第0个元素,那么, ps+1表示stu[1]的地址,ps++表示指针向后移动一个元素的空 间,指向下一个元素。 上一页
首页 上一页
• 结构体变量的定义和初始化
– 结构体类型变量的定义方式:
• 用已经定义的结构体类型去定义结构体变量; • 定义结构体类型的同时定义结构体变量; • 定义无名结构体类型的同时定义结构体变量。
– 初始化:
可以在定义结构体变量的同时初始化。
– 说明:
• 定义结构体类型是说明一种由一些特定成员组成的模型。 模型并不是实体,变量才是占用内存的实体。 • 结构体变量的地址是结构体变量在内存的首地址,用来 存放结构体变量地址的变量是指向结构体的指针变量。 上一页
• 结构体变量的引用