C语言 第九章 结构体

第九章 结构体

自定义类型 – 结构体

结构体类型,不占内存,不能保存数据;

内存空间,可以保存数据

1
2
3
4
5
6
7
8
9
struct stu
{
int num;
char name[10];
char sex;
float score;
};
struct stu boy1;

sizeof对类型和变量均可使用

1
2
sizeof(boy1);
sizeof(struct stu);

结构体类型变量的定义方式

先定义类型,再定义变量

1
2
3
4
5
6
7
8
struct stu
{
int num;
char name[10];
char sex;
float score;
};
struct stu boy1,boy2;

定义类型的同时,定义变量

1
2
3
4
5
6
7
8
9
struct stu
{
int num;
char name[10];
char sex;
float score;
}boy1, boy2;

struct stu boy3;

定义类型的同时定义变量,但省略类型名

因无类型名,无法再重新定义其他变量

1
2
3
4
5
6
7
struct
{
int num;
char name[10];
char sex;
float score;
}boy1, boy2;

结构体类型变量的初始化

1
2
3
4
5
6
7
8
9
10
11
12
struct stu
{
int num;
char name[10];
char sex;
float score;
};

struct stu boy1,boy2 = {1001, "zhao", 'M', 85.5};

// 可以整体赋值,直接将boy2的值直接赋给boy1
boy1 = boy2;

结构体类型的数组

1
2
3
4
5
struct stu ss[3];

ss[0].num = 1001;
strcpy(ss[1].name, "Qian");
ss[2].score=92.0;

结构指针变量

结构体变量用 .

结构体指针变量用 ->

(*结构体指针变量)用.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct stu boy1;
struct stu *p;
p=&boy1;

p -> num=100;
// 相当于
boy1.num=1001;

strcpy(p->name, "Zhang");
// 相当于
strcpy(boy1.name, "Zhang");

// 此处()不可省略,点和->的优先级都最该(与括号相当)
(*p).score=92.0;
// 相当于
boy1.score=92.0;

结构体类型数据做函数参数

用法与传普通变量类似,

结构体类型变量做函数参数,不会改变原来的实参的值。

结构体指针做函数参数,可以修改原来实参的值。

结构体类型的嵌套

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct date
{
int year;
int month;
int day;
};
struct stu
{
int num;
char name[10];
char sex;
struct date birthday;
float score;
};

第二种

1
2
3
4
5
6
7
8
9
10
11
12
13
struct stu
{
int num;
char name[10];
char sex;
struct
{
int year;
int month;
int day;
} birthday;
float score;
};

类型定义语句typedef

为类型起“绰号”,并不产生新的数据类型,只是给已有的类型增加新名

1
2
3
4
5
typedef double real;

real a,b;
// 相当于
double a,b;

C语言常用内存管理库函数(包含stdlib.h

函数名介绍备注
malloc分配1块长度为size字节的连续内存空间(不清零),函数返回该空间的首地址;如分配失败函数返回0(类型说明符*)malloc(size)
calloc分配n块、每块长度为size字节的连续内存空间(共size×n字节),并将该空间中的内容全部清零,函数返回该空间的首地址;如分配失败函数返回0(类型说明符*)calloc(n,size)
free释放ptr所指向的一块内存空间,ptr是由malloc或calloc函数所分配空间的地址,即是这两个函数的返回值(或类型转换后的返回值)free(ptr)(ptr为任意基类型的指针)

链表

以链接方式存储的线性表,链表各元素的逻辑结构与存储结构一般不一致。

链表类型:单向链表,双向链表,循环链表。。。

链表介绍

单向链表

一个单向链表的节点分为两个部分,第一部分保存或者显示节点的相关信息,第二部分存储下一个节点的地址。单向链表只向一个方向遍历。

单向链表

链表的一种,特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始;列表有节点构成,head指针指向第一个称为表头节点,而终止于最后一个指向NULL的指针。

双向链表

比单向链表多一个的是,双向链表每个节点有两个链接,一个指向前一个节点,而另一个指向下一个节点,当为最后一个节点时,指向空值或空列表。

双向链表

循环链表

在一个循环链表中,首节点和末节点被连接在一起。这种方式,单向和双向都可实现。

循环链表

链表的创建与输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 结构体
struct nodelist
{
// 数据
int score;
// 指向下一个链表的指针
struct nodelist *next;
};

// 自定义结构体类型
typedef struct nodelist SNODE;

// 创建链表
SNODE *create_list(int data)
{
SNODE *head=NULL, *node=NULL, *end=NULL;
int i;

head = (SNODE *)malloc(sizeof(SNODE));
end = head;

for(i=0; i<data; i++)
{
node = (SNODE *)malloc(sizeof(SNODE));
node->score = i;
end->next = node;
end = node;
}
end->next = NULL;

return head;
}

// 输出链表
void out_list(SNODE *h)
{
SNODE *p;
p = h->next;
while(p)
{
printf("%d\n", p->score);
p = p->next;
}
}




int main()
{
int data = 3;
SNODE *head;
head = create_list(data);
out_list(head);

system("pause");
}

链表节点的插入和删除

节点的插入
1
2
3
4
p = new struct node;
p->data = 95.5;
p->next = q->next;
q->next = p;
节点的删除
1
2
q->next = p->next;
delete p;