C语言 结构体与链表

  • 格式:doc
  • 大小:1.14 MB
  • 文档页数:30

CHAPTER 10 第 10章

结构体与共用体

学习目标 本章主要介绍结构体的定义和使用方法,然后介绍链表的概念和相关操作,最后介绍两种新的数据类型——共用体和枚举。通过本章的学习,需要掌握结构体的概念与结构体类型的定义方法,熟练掌握结构体变量的定义、引用和初始化方法,掌握链表的概念,熟练掌握链表的相关操作,了解共用体和枚举的概念及其使用方法。

实际问题中,经常需要对一些类型不同但又相互关联的数据进行处理。比如,对一个学生而言,他的学号(num)、姓名(name)、性别(sex)、年龄(age)、成绩(score)等数据都与该学生有联系。如果将num、name、sex、age、score分别定义成相互独立的简单变量,则无法反映它们之间的内在联系;又因为这些数据彼此类型不同,而数组只能对同种类型的成批数据进行处理,所以,此时也无法使用数组。这就需要有一种新的数据类型,它能将具有内在联系的不同类型的数据组合成一个整体,在C语言里,这种数据类型就是“结构体”。

结构体属于构造数据类型,它由若干成员组成,成员的类型既可以是基本数据类型,也可以是构造数据类型,而且可以互不相同。由于不同问题需要定义的结构体中包含的成员可能互不相同,所以,C语言只提供定义结构体的一般方法,结构体中的具体成员由用户自己定义。这样,编程人员可以根据实际需要定义各种不同的结构体类型。

10.1 结 构 体

结构体遵循“先定义后使用”的原则,其定义包含两个方面,一是定义结构体类型;二是定义该结构体类型的变量。

10.1.1 结构体类型的定义

格式:struct 结构体类型名

{

类型1 成员名1; 第10章

结构体与共用体 2

类型2 成员名2;

类型n 成员名n;

};

功能:定义一种结构体类型。

例如,图10.1所示结构体类型可有如下定义:

num name sex birthday score year month day

图10.1 struct student结构体类型组织结构图

struct date

{

int year;

int month;

int day;

};

struct student

{

int num;

char name[20];

char sex;

struct date birthday;

float score;

};

【说明】① “结构体类型名”与“成员名”都遵循标识符命名规则。

② 成员类型可以是除本身所属结构体类型外的任何已有数据类型。

③ 在同一作用域内,结构体类型名不能与其它变量名或结构体类型名重名。

④ 同一个结构体各成员不能重名,但允许成员名与程序中的变量名、函数名或者不同结构体类型中的成员名相同。

⑤ 结构体类型的作用域与普通变量的作用域相同:在函数内定义,则仅在函数内部起作用;在函数外定义,则有全局作用域。

【注意】结构体类型定义的末尾必须有分号。

10.1.2 结构体变量的定义、引用和初始化

1.结构体变量的定义

(1)先定义结构体类型,再定义结构体变量。如

struct date

{

int year;

int month;

int day;

};

struct date date1,date2;

(2)定义结构体类型的同时定义结构体变量。如 第10章

结构体与共用体 3

struct student

{

int num;

char name[20];

char sex;

struct date birthday;

float score;

}stu1,stu2;

(3)直接定义结构体变量。如

struct

{

int num;

char name[20];

char sex;

struct date birthday;

float score;

}stu1,stu2;

【说明】① 结构体类型与结构体变量是两个不同的概念。前者只声明结构体的组织形式,本身不占用存储空间;后者是某种结构体类型的具体实例,编译系统只有定义了结构体变量后才为其分配内存空间。

② 结构体变量各成员存储在一片连续的内存单元中。

③ 可以用sizeof测出某种基本类型数据或构造类型数据在内存中所占用的字节数。如pirntf("%d",sizeof(struct student));

【思考】测试并分析struct student类型的结构体变量在内存所占用存储空间的长度。

2. 结构体变量的引用

(1)使用成员运算符引用结构体变量的成员。

格式:结构体变量名.成员名

功能:引用结构体变量中指定名称的成员变量。如

struct student stu1,stu2;

int age;

stu1.num=1001;

gets();

scanf("%d",&stu1.birthday.year);

age=2006-stu1.birthday.year;

(2)使用指针运算符和成员运算符引用结构体变量的成员。如

struct student stu,*p=&stu;

(*p).num=10001;

scanf("%s",(*p).name);

scanf("%f",&(*p).score);

(3)使用指向运算符“->”引用结构体变量的成员。如

struct student stu,*p=&stu;

p->num=10001;

scanf("%s", p->name);

scanf("%f",&p->score);

printf("age of %s is %d\n",,age); 第10章

结构体与共用体 4

(4)将结构体变量作为一个整体进行操作。如

struct student stu1,stu2,*p=&stu1;

stu2=stu1;

printf("the address of struct student variable stu2 is %x",

&stu2);

【说明】① “(*p).成员名”、“p->成员名”与“stu.成员名”等价,不过后两种方式更直观。

② 成员运算符“.”与指向运算符“->”的优先级相同,都高于指针运算符“*”。

【注意】不能将结构体变量当作一个整体进行输入、输出或赋值,如

struct date date1,date2;

date1={1988,8,5};

scanf("%d%d%d",&date2);

printf("%d%d%d",date2);

【思考】“(*p).成员名”中的圆括号能否省略?

3.结构体变量的初始化

在定义结构体变量的同时,按照所属结构体类型的组织形式依次写出全部或部分成员变量的初始值。如:

struct student stu1={1001,"Zhang San",'M',{1988,8,10},580};

struct student stu2={1002,"Li Ping",'F',1989,2,5,595};

struct student stu3={1002,"Li Ping",'F',1989};

【说明】① 初始化前,结构体变量各成员的取值是随机的。

② 花括号内初值的顺序、类型要与结构体成员的顺序和类型一致。

【注意】初始化时,花括号内的数据不能包含变量。如以下程序片段的最后一行不正确:

struct date

{

int year;

int month;

int day;

}date1={1988,8,10};

struct student

{

int num;

char name[20];

char sex;

struct date birthday;

float score;

}stu={10010,"zhangsan",'M',date1,580};

10.1.3 结构体程序举例

例10.1 输入一个学生的信息并显示。

程序的算法描述如图10.2所示,代码如下: 第10章

结构体与共用体 5

定义结构体变量stu输入学号stu.num输入姓名输入出生年月日输入学生成绩stu.score输出学生信息

图10.2 例10.1主函数N-S图

#include

void main()

{

struct date

{

int year;

int month;

int day;

};

struct student

{

int num;

char name[20];

char sex;

struct date birthday;

float score;

};

struct student stu;

printf("请输入学生学号:");

scanf("%d",&stu.num);

printf("请输入学生姓名:");

scanf("%s",);

printf("请输入学生性别:");

scanf(" %c",&stu.sex);

printf("请输入学生出生日期:");

scanf("%d%d%d",&stu.birthday.year,&stu.birthday.month,

&stu.birthday.day);

printf("请输入学生成绩:");

scanf("%f",&stu.score);

printf("学号:%d\n姓名:%s\n性别:%c\n出生日期:%d年%d月%d日\n成绩:%6.1f\n",

stu.num,,stu.sex,stu.birthday.year,stu.birthday.month,

stu.birthday.day,stu.score);

}

【注意】若连续输入两个字符或者先输入一个字符串后输入一个字符,则输入第二个字符的控制符%c前应加一个空格。如语句scanf(" %c",&stu.sex)中,格式控制符%c之前的空格不能省略,否则,两次输入之间的分隔符将被作为第二个字符的输入加以处理。

例10.2 在函数input中输入一个学生的信息,在函数list中显示。

程序的算法描述如图10.3所示,代码如下: