1.结构变量的定义
类型和变量是不同的概念,只能对变量进行赋值、存取或运算操作,而不能对一个类型进行这些操作。因此在声明了结构类型后,还需要定义结构变量,以便在程序中引用它。结构变量和其他变量一样,必须先定义后使用,定义方法有以下3种:
(1)先定义结构类型,再定义结构变量
(2)定义结构类型的同时定义结构变量
(3)直接定义结构变量
2.结构变量的初始化
同其他基本数据类型的变量一样,结构变量在定义的同时也可以进行初始化。结构变量初始化的一般形式是在定义变量的后面加上“={初值表列};”,即在一对花括号中分别列出结构变量中各成员的初始值,各初始值之间用逗号隔开。
注意:
(1)对结构变量初始化时,需要按照其成员出现的顺序对每个成员依次赋值,不能跳过前面的成员给后面的成员赋值。
(2)不能在结构内部给成员赋初值。
引用结构变量成员的方式为:
结构变量名.成员名
其中,“.”是成员运算符。
使用结构变量时需注意:
(1)可以引用结构变量成员的地址,也可以引用结构变量的地址。
(2)对结构中数组成员的引用也是通过逐个引用数组元素来实现的,如:bk1.bname[0]= 'a'。对于嵌套结构变量,要使用多个成员运算符引用其最低级的成员。
(3)相同类型的结构变量之间可以进行整体赋值,但是不能进行关系运算。
(4)结构变量可以作为函数的参数或返回值,以便在函数之间传递数据。结构变量作为参数传递的是实参结构变量的值,即把结构变量中的数据作为一个整体传递给相应的形参,形参要求是相同的结构类型。在被调用函数中对形参结构变量的成员的操作不会影响实参中成员的值。
1.结构数组的定义
在C语言中,可以将数组定义为结构类型,即结构数组,它与普通数组的不同之处是结构数组的每个数组元素都是一个结构类型的数据。在实际应用中,经常用结构数组来表示具有相同数据结构的一个群体,例如书店中的图书信息等等。用结构类型中不同类型的成员变量描述图书的具体属性,用数组描述书店中具有相同属性的图书信息,可以使用循环对数组元素进行统一处理,优化算法。例9.1是结构数组的典型应用。
与结构变量的定义方法类似,结构数组的定义也有三种形式。
(1)先声明结构类型,再定义结构数组,格式如下:
struct 结构名
{
成员列表;
};
struct 结构名 数组名[元素个数][,数组名[元素个数],……];
(2)声明结构类型的同时定义结构数组,格式如下:
struct 结构名
{
成员列表;
}数组名[元素个数][,数组名[元素个数],……];
(3)直接定义结构数组,格式如下:
struct
{
成员列表;
}数组名[元素个数][,数组名[元素个数],……];
2.结构数组的初始化
结构数组在定义的同时也可以初始化,可进行部分初始化或全部初始化。结构数组初始化的一般形式为:
struct 结构名 数组名[元素个数]={初值表列};
结构数组的使用也是通过引用结构数组元素的成员进行的。结构数组元素中成员的访问方法与结构变量成员的访问方法类似,通过成员运算符“.”来引用。另一方面,由于可以通过数组名以指针法形式来引用数组元素,因此对于结构数组元素成员的引用可以有如下几种形式:
(1)结构数组名[下标].成员名
(2)(*(结构数组名+下标)).成员名
(3)(结构数组名+下标)->成员名。
指针可以指向任何一种变量,因此也可以使指针指向结构变量。指向结构变量的指针叫做结构指针。结构指针变量的值是它所指向的结构变量所占用内存空间的起始地址。结构指针变量定义的形式为:
struct 结构名 *指针变量名;
结构指针也需要先赋值后使用,即把结构变量的首地址赋给结构指针,有了结构指针,就可以用它来访问结构变量的成员。下面三种访问结构变量的成员的形式等价:
(1)结构变量名.成员名
(2)(*结构指针变量名).成员名
(3)结构指针变量名->成员名
结构指针也可以用来指向一个结构数组,这时结构指针的值是结构数组的首地址。同样,结构指针变量也可以指向结构数组元素,此时结构指针变量的值是结构数组元素的地址。例如,结构数组与结构指针的定义如下:
struct
{ int a;
float b;
}a[3],*p;
p=a;
此时p指向数组a的第一个元素,“p=a;”等价于“p=&a[0];”,若执行“p++;”则此时指针变量p指向a[1],指针指向关系如图9.3所示。
将结构变量和结构数组作为函数参数进行数据传递时,由于要将全部成员逐个传送,特别是成员为数组时将会使传送的时间和空间开销很大,程序的效率很低。最好的办法是使用指针,即用结构指针变量作函数参数进行传送。
结构指针作为函数的参数,要求对应的形参是一个同类型的结构指针,此时实参向形参传递的是结构指针的值,系统会为形参指针分配一个内存单元来存放实参结构指针变量的内容。由于指针中存放的是地址,因此实参指针和形参指针实际指向同一个地址,则在被调用函数中对形参的修改会影响相应实参的值。这种函数参数形式执行效率高,可以完成比基本类型指针更为复杂的操作。
链表是一种动态数据结构,它使用随机分配的内存单元来存放数据,这些内存单元可以是连续的,也可以是不连续的。链表是由若干个相同结构类型的元素依次串接而成的,它使用指针来表示两个元素之间的前后关系。
根据结点之间的相互关系,链表分为:单链表、双链表、循环链表。本书只介绍单链表。
单链表的每个结点中只包含一个指针域,该指针域中存放的是其后继结点的地址,这样的链表称为单链表,如图9.2所示。
通常使用结构的嵌套来定义单链表结点的数据类型,定义形式如下:
struct 结构名
{ 类型名 成员名1;
类型名 成员名2;
……
类型名 成员名n;
struct 结构名 *指针名1,*指针名2, ……,*指针名n;
};
动态内存分配是指在程序运行时动态地分配或者回收内存空间的方法,其好处是能有效地使用内存,而且同一段内存可以有不同的用途,使用时申请,用完就释放。包括三个方面的内容:动态内存分配、动态内存调整和动态内存释放。使用动态内存分配函数需要包含头文件“stdlib.h”、“malloc.h”或者“alloc.h”。
(1)动态内存分配函数malloc()和calloc()
(2)动态内存释放函数free()
(3)动态内存分配调整函数realloc()
单链表的基本操作主要有:(1)创建链表;(2)输出链表;(3)查找结点;(4)插入结点;(5)删除结点;(6)重组链表。下面分别进行介绍。
1.创建链表
2.输出链表(链表的遍历)
3.查找结点
4.插入结点
5.删除结点
6.重组链表