1. 结构体类型
(1)构造结构体类型
- 定义成员变量的方式与普通变量的定义一样。
- 成员列表必须用一对中括号 “{}” 括起。
- 结构体类型名可以省略不写,但中括号 “{}”后面的分号 “;” 必不可少,分号 “;” 与中括号 “{}” 之间可以插入用来指定同一结构体类型的变量。
/* 结构体类型的构造方法
struct 结构体类型名
{
//成员列表
成员变量 1 ;
成员变量 2 ;
......
};
*/
struct student
{
//成员列表
char name[10] ;
char sex[2] ;
int age ;
};
//或者
struct student
{
//成员列表
char name[10] ;
char sex[2] ;
int age ;
}stu[10];
(2)定义结构体变量
- 先定义结构体类型名,再定义结构体变量。
- 在定义结构体类型的同时可以定义结构体变量。
- 类型、变量可同时定义,结构体类型名可以省略,但该定义结构体变量方法不建议使用。
注意:结构体变量在内存中占用字节数为各成员变量占用字节数的总和。
(3)引用结构体成员变量的方法
- 引用方法:结构体变量名 . 成员变量名(“ . ” 为成员运算符),例如:stu[1].name,stu[1].sex,stu[1].age。
- 注意:a.b = “xiangjiang”,字符串的赋值运算错误,需要使用 strcpy 进行字符串的赋值,例如:strcpy(a.b,xingjiang)。
- 几种引用结构体成员变量的方法:当指针变量 p 指向结构体变量 aa 时,引用 aa 中成员变量 num 的几种方法如下所示:aa.num 等价于 p->num 等价于 (*p).num,其中 “->” 为指向运算符。
- 访问结构体中数据的三种方式,以 student 结构体为例,比如访问第二行的 “sex” 有如下:stu[1].sex 等价于 (p+1)->sex 等价于 (*(p+1)).sex。
//引用结构体成员变量的三种方法
struct student
{
//成员列表
char name[10] ;
char sex[2] ;
int age ;
}stu[10];
struct student *p; //定义一个指向 student 结构体数组的指针
//第一种方法
stu[1].name ;
stu[1].sex ;
stu[1].age ;
//第二种方法
(p+1)->name ;
(p+1)->sex ;
(p+1)->age ;
//第三种方法
(*(p+1)).name ;
(*(p+1)).sex ;
(*(p+1)).age ;
结构体类型的使用流程:第一步,先构造结构体类型;第二步,定义结构体类型中的成员变量;第三步,可以使用三种方法来引用结构体中的成员变量。
2. 链表类型(重点)
(1)存放数据的两种方法:定义数组和定义链表(以单链表为例)。
(2)链表的定义:链表是一种线性的数据结构,采用动态分配存储方式,能够有效节省存储空间,链表由数据域和指针域两部分组成。
(3)链表的分类:单链表、双链表、循环单链表、循环双链表、双向链表,在这里简单介绍单链表。
//链表的格式(以单链表为例)
struct 结构体名
{
定义数据成员 ;
......
struct 结构体名 *指针变量名 ;
}单链表别名;
//以学生信息为例,建立单链表
struct student
{
//数据域
char name[10] ;
char sex[2] ;
int age ;
//指针域
struct student *next ;
}Student_Lnode ;
(4)链表的使用
- 利用 struct 定义链表的结点(数据域和指针域),链表所占用的空间不必连续。
- 通过 malloc 函数来动态分配链表结点存储空间。
- 可以使用链表对数据进行增加、删除、修改、查询等操作。
- 链表使用完后,通过 free 函数释放链表所占用的存储空间。
(5)使用链表的注意事项
- 链表的访问都是通过指针变量从头结点开始访问。
- 链表的“头结点”变量(head)指向链表的第一个元素。
- 链表中的所有结点都是结构体类型,且同一链表中的结点都是同一结构体类型。
- 链表的最后一个结点称为链尾,不再指向其他结点(即该结点的指针域为 NULL)。
注意:链表的结点由数据域和指针域组成。根据链表的格式而言,由结构体 struct 和指向自身的指针构成。
(6)动态分配存储函数
- malloc 函数,格式:malloc(size)
- 作用:在内存的动态存储区中分配一个长度为 size 个字节的连续空间,函数返回值为一个指向分配域起始地址的指针,若分配失败,则返回 NULL。
//示例代码
struct student
{
char name[10] ;
char sex[2] ;
struct student *next ;
}Lnode;
struct Lnode *p ;
//在内存中动态分配链表的存储空间
//强制类型转换,转换成结构体类型,sizeof 函数计算全部成员变量的字节数
p = (struct Lnode *)malloc(sizeof(struct Lnode));
- free 函数,格式:free§
- 作用:释放 malloc 函数分配的链表存储空间
//示例代码
free(p);
(7)链表的操作
- 创建一个链表
- 访问链表中的数据
- 链表中结点的添加
- 链表中结点的删除
- 删除第一个结点时,head 头结点下移一个结点。
- 删除中间结点和尾部结点时,需知被删除结点的前一个结点。
3. 共用体类型
(1)共用体类型的定义
//共用体类型定义格式
union 共用体名
{
成员列表 ;
}共用体别名;
//示例代码
union student
{
char name[10];
char sex[2];
char phone[11];
}stuLnode;
注意:共用体类型的注意事项和结构体类型的注意事项一样。
(2)共用体中所有成员共用同一段内存(所有成员的起始地址一样),所以共用体类型变量所占的字节数等于该共用体类型中所占字节数最多的成员所占的字节数。
- 整型( int 型)占 2 个字节
- 单精度浮点型 ( float 型)占 4 个字节
- 双精度浮点型 ( double 型)占 8 个字节
- 字符型( char 型)占 1 个字节
//共用体类型所占字节数为 11 个字节
union student
{
char name[10]; //占 10 个字节
char sex[2]; //占 2 个字节
char phone[11]; //占11个字节
}stuLnode;
sizeof(stuLonde); //字节数为 11 个字节
(4)typedef (取别名):给已有类型取别名
- 用 typedef 定义新类型名,在编程时可使用 typedef 定义新的类型来代替已有的类型名。
//使用格式
typedef 已有类型名 新的类型名;
//示例代码
typedef int INTEGER; //INTEGER 与 int 等价
INTEGER a[10]; //等价于 int a[10];
- typedef 可用于定义各种类型名,但不能定义变量,见到 typedef 则该语句最后的标识符必定是一个类型名而不是一个变量名。
- typedef 只能对已经存在的类型新增一个别名,而不是创造一个类型,即在 typedef 后必须是一个已有的类型。即不能定义变量,不能造类型。
//示例代码
typedef int ARR[10];
ARR a,b[2];
//等价于
int a[10],b[2][10];
typedef char *POINT ;
POINT p1,*p2;
//等价于
char *p1,**p2;