第九章 结构体
自定义类型 -- 结构体
结构体类型,不占内存,不能保存数据;
内存空间,可以保存数据
struct stu
{
int num;
char name[10];
char sex;
float score;
};
struct stu boy1;
sizeof对类型和变量均可使用
sizeof(boy1);
sizeof(struct stu);结构体类型变量的定义方式
先定义类型,再定义变量
struct stu
{
int num;
char name[10];
char sex;
float score;
};
struct stu boy1,boy2;定义类型的同时,定义变量
struct stu
{
int num;
char name[10];
char sex;
float score;
}boy1, boy2;
struct stu boy3;定义类型的同时定义变量,但省略类型名
因无类型名,无法再重新定义其他变量
struct
{
int num;
char name[10];
char sex;
float score;
}boy1, boy2;结构体类型变量的初始化
struct stu
{
int num;
char name[10];
char sex;
float score;
};
struct stu boy1,boy2 = {1001, "zhao", 'M', 85.5};
// 可以整体赋值,直接将boy2的值直接赋给boy1
boy1 = boy2;结构体类型的数组
struct stu ss[3];
ss[0].num = 1001;
strcpy(ss[1].name, "Qian");
ss[2].score=92.0;结构指针变量
结构体变量用
.结构体指针变量用
->(
*结构体指针变量)用.
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;结构体类型数据做函数参数
用法与传普通变量类似,
结构体类型变量做函数参数,不会改变原来的实参的值。
结构体指针做函数参数,可以修改原来实参的值。
结构体类型的嵌套
struct date
{
int year;
int month;
int day;
};
struct stu
{
int num;
char name[10];
char sex;
struct date birthday;
float score;
};第二种
struct stu
{
int num;
char name[10];
char sex;
struct
{
int year;
int month;
int day;
} birthday;
float score;
};类型定义语句typedef
为类型起“绰号”,并不产生新的数据类型,只是给已有的类型增加新名
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的指针。
双向链表
比单向链表多一个的是,双向链表每个节点有两个链接,一个指向前一个节点,而另一个指向下一个节点,当为最后一个节点时,指向空值或空列表。
![]()
循环链表
在一个循环链表中,首节点和末节点被连接在一起。这种方式,单向和双向都可实现。
![]()
链表的创建与输出
#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");
}
链表节点的插入和删除
节点的插入
p = new struct node;
p->data = 95.5;
p->next = q->next;
q->next = p;节点的删除
q->next = p->next;
delete p;