day13: 结构体,位域,共用体,枚举,链表操作
This commit is contained in:
parent
9e1c7ca87f
commit
7b504aa38b
|
@ -17,3 +17,5 @@
|
||||||
#### day11: 动态内存申请,内存泄漏,字符串处理函数
|
#### day11: 动态内存申请,内存泄漏,字符串处理函数
|
||||||
|
|
||||||
#### day12: 字符串处理函数,const,结构体
|
#### day12: 字符串处理函数,const,结构体
|
||||||
|
|
||||||
|
#### day13: 结构体,位域,共用体,枚举,链表操作
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
ANSI转义序列可以用来设置终端中文本的颜色、背景色和其他属性。以下是一些常见的ANSI颜色代码及其对应的颜色值:
|
||||||
|
|
||||||
|
- 前景色(文本颜色):
|
||||||
|
|
||||||
|
- 黑色:`\033[30m`
|
||||||
|
- 红色:`\033[31m`
|
||||||
|
- 绿色:`\033[32m`
|
||||||
|
- 黄色:`\033[33m`
|
||||||
|
- 蓝色:`\033[34m`
|
||||||
|
- 紫色:`\033[35m`
|
||||||
|
- 青色:`\033[36m`
|
||||||
|
- 白色:`\033[37m`
|
||||||
|
|
||||||
|
- 背景色:
|
||||||
|
|
||||||
|
- 黑色:`\033[40m`
|
||||||
|
- 红色:`\033[41m`
|
||||||
|
- 绿色:`\033[42m`
|
||||||
|
- 黄色:`\033[43m`
|
||||||
|
- 蓝色:`\033[44m`
|
||||||
|
- 紫色:`\033[45m`
|
||||||
|
- 青色:`\033[46m`
|
||||||
|
- 白色:`\033[47m`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
除了前景色和背景色,ANSI转义序列还可以用来设置其他文本属性,例如加粗、下划线、闪烁等。以下是一些常见的ANSI属性代码及其对应的属性:
|
||||||
|
|
||||||
|
- 加粗:`\033[1m`
|
||||||
|
- 下划线:`\033[4m`
|
||||||
|
- 闪烁:`\033[5m`
|
||||||
|
- 反显(交换前景色和背景色):`\033[7m`
|
||||||
|
- 隐藏(使文本不可见):`\033[8m`
|
||||||
|
|
||||||
|
你可以将这些属性代码与前景色、背景色代码组合使用,以实现更多的效果。例如,要设置红色加粗文本,可以使用`\033[31;1m`。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
除了设置文本颜色、背景色和其他属性,ANSI转义序列还可以用来控制终端的显示,例如清空屏幕、移动光标等。以下是一些常见的ANSI控制代码及其对应的操作:
|
||||||
|
|
||||||
|
- 清空屏幕:`\033[2J`
|
||||||
|
- 将光标移动到屏幕左上角:`\033[H` 或 `\033[1;1H`
|
||||||
|
- 将光标向上移动n行:`\033[nA`
|
||||||
|
- 将光标向下移动n行:`\033[nB`
|
||||||
|
- 将光标向右移动n列:`\033[nC`
|
||||||
|
- 将光标向左移动n列:`\033[nD`
|
||||||
|
- 隐藏光标:`\033[?25l`
|
||||||
|
- 显示光标:`\033[?25h`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
除了常见的ANSI转义序列,还有一些特殊的控制代码,可以用来实现一些高级的终端操作。以下是一些常见的特殊控制代码及其对应的操作:
|
||||||
|
|
||||||
|
- BEL(响铃):`\a`
|
||||||
|
- ESC(转义字符):`\e` 或 `\033`
|
||||||
|
- CSI(控制序列引导):`\033[`
|
||||||
|
- OSC(操作系统命令):`\033]`
|
||||||
|
|
||||||
|
这些特殊控制代码通常用于与终端外部环境进行交互,例如向终端发送提示音、设置终端标题等。其中,OSC代码可以用来向终端发送自定义的命令,以实现一些特殊的功能。例如,可以使用OSC代码设置终端的图标、背景图片等。
|
||||||
|
|
||||||
|
需要注意的是,这些特殊控制代码可能在不同的终端程序或操作系统中有所不同。如果你想要在程序中使用这些代码,最好先查看终端程序或操作系统的文档,确保代码的兼容性和正确性。
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef enum front_color_e
|
||||||
|
{
|
||||||
|
BLACK = 30, // 黑色
|
||||||
|
RED, // 红色
|
||||||
|
GREEN, // 绿色
|
||||||
|
YELLOW, // 黄色
|
||||||
|
BLUE, // 蓝色
|
||||||
|
PURPLE, // 紫色
|
||||||
|
CYAN, // 青色
|
||||||
|
WHITE, // 白色
|
||||||
|
} Front_Color; // 前景色
|
||||||
|
|
||||||
|
typedef enum back_color_e
|
||||||
|
{
|
||||||
|
BLACK_B = 40, // 黑色
|
||||||
|
RED_B, // 红色
|
||||||
|
GREEN_B, // 绿色
|
||||||
|
YELLOW_B, // 黄色
|
||||||
|
BLUE_B, // 蓝色
|
||||||
|
PURPLE_B, // 紫色
|
||||||
|
CYAN_B, // 青色
|
||||||
|
WHITE_B, // 白色
|
||||||
|
} Back_Color; // 背景色
|
||||||
|
|
||||||
|
typedef enum attr_e
|
||||||
|
{
|
||||||
|
BOLD = 1, // 加粗
|
||||||
|
UNDERLINE = 4, // 下划线
|
||||||
|
BLINK, // 闪烁
|
||||||
|
REVERSE = 7, // 反显
|
||||||
|
HIDE, // 隐藏
|
||||||
|
} Attr; // 文本属性
|
|
@ -0,0 +1,19 @@
|
||||||
|
// 结构体内存分配
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct stu
|
||||||
|
{
|
||||||
|
char sex;
|
||||||
|
int age;
|
||||||
|
} lucy;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// 是 8 而不是 5,因为结构体内存分配是按照最大的数据类型来分配的
|
||||||
|
// 即使是 char 类型,也会分配 4 个字节
|
||||||
|
// 但是如果是数组,就会按照数组的大小来分配
|
||||||
|
// 例如:char name[10],那么就会分配 10 个字节
|
||||||
|
// 本题中,8 = 4 + 4
|
||||||
|
printf("lucy size: %lu\n", sizeof(lucy));
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
// short m;
|
||||||
|
char c[13];
|
||||||
|
int x[4];
|
||||||
|
// long y[10];
|
||||||
|
// int y;
|
||||||
|
// short c;
|
||||||
|
// char x;
|
||||||
|
} p1;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("p1 size: %lu B\n", sizeof(p1));
|
||||||
|
printf("%p %p\n", &p1.c, &p1.x);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#pragma pack(1) // 手动指定内存对齐,优点:可以减少内存的浪费,缺点:会降低内存的读取速度
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
char a;
|
||||||
|
short b;
|
||||||
|
int c;
|
||||||
|
} p1;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("p1 size: %lu B\n", sizeof(p1));
|
||||||
|
printf("%p %p %p\n", &p1.a, &p1.b, &p1.c);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
// 位段: 是啥? 为啥要用?
|
||||||
|
// 位段: 用来节省内存空间的
|
||||||
|
// 位段: 用来存储多个不同的数据
|
||||||
|
// 位段: 用来存储多个不同的数据, 但是这些数据的取值范围都比较小
|
||||||
|
// 位段的定义: struct 结构体名
|
||||||
|
// {
|
||||||
|
// 数据类型 变量名: 位数;
|
||||||
|
// 数据类型 变量名: 位数;
|
||||||
|
// };
|
||||||
|
// 位段的使用: 位段的使用和结构体的使用是一样的
|
||||||
|
// 位段的注意事项: 位段的位数不能超过数据类型的位数
|
||||||
|
#include <stdio.h>
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
char a : 3;
|
||||||
|
short b : 9;
|
||||||
|
short : 1; // 下一个变量的位段从新的存储单元开始
|
||||||
|
int c : 19;
|
||||||
|
} p1;
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("p1 size: %lu B\n", sizeof(p1));
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned char a : 2;
|
||||||
|
unsigned char : 1; // 占位符
|
||||||
|
unsigned char b : 2;
|
||||||
|
unsigned char : 1; // 占位符
|
||||||
|
unsigned char c : 2;
|
||||||
|
} REG;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
REG.a = 3;
|
||||||
|
REG.b = 1;
|
||||||
|
REG.c = 2;
|
||||||
|
|
||||||
|
printf("%ld B\n", sizeof(REG)); // 1 B
|
||||||
|
char reg = *((char *)®); // 原理: 位段的内存存储是从低位到高位的
|
||||||
|
printf("%#hhx\n", reg); // 0x11
|
||||||
|
|
||||||
|
// 打印二进制
|
||||||
|
printf("reg = 0b");
|
||||||
|
for (int i = 7; i >= 0; i--)
|
||||||
|
{
|
||||||
|
printf("%d", (reg >> i) & 1);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
// 共用体
|
||||||
|
// 特点:
|
||||||
|
// 1. 共用体中的所有成员共用一块内存空间
|
||||||
|
// 2. 共用体的大小是最大成员的大小
|
||||||
|
// 3. 共用体的成员可以是不同的数据类型
|
||||||
|
// 只初始化第一个成员
|
||||||
|
// 不能同时使用其他的成员
|
||||||
|
// 变量中起作用的只有最后一次赋值
|
||||||
|
// 在存入一个新的值之前, 会把上一个值覆盖掉
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
union data1_uni
|
||||||
|
{
|
||||||
|
unsigned char a;
|
||||||
|
short b;
|
||||||
|
int c;
|
||||||
|
} data1, data2;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
printf("%ld\n", sizeof(union data1_uni));
|
||||||
|
data1.a = 10;
|
||||||
|
data1.c = 20;
|
||||||
|
printf("a = %d, b = %d, c = %d\n", data1.a, data1.b, data1.c);
|
||||||
|
union data1_uni data2 = {14};
|
||||||
|
printf("a = %d, b = %d, c = %d\n", data2.a, data2.b, data2.c);
|
||||||
|
union data1_uni data3 = {257};
|
||||||
|
printf("a = %d, b = %d, c = %d\n", data3.a, data3.b, data3.c);
|
||||||
|
|
||||||
|
union data1_uni data4;
|
||||||
|
data4.b = 300;
|
||||||
|
printf("a = %d, b = %d, c = %d\n", data4.a, data4.b, data4.c);
|
||||||
|
|
||||||
|
union data1_uni data5;
|
||||||
|
data5.c = 32769;
|
||||||
|
printf("a = %d, b = %d, c = %d\n", data5.a, data5.b, data5.c);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
// 共用体和结构体结合使用
|
||||||
|
// 可以解决不同类型的数据在内存中的存储问题
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct REG
|
||||||
|
{
|
||||||
|
unsigned char a : 1; // 低位
|
||||||
|
unsigned char b : 1;
|
||||||
|
unsigned char c : 1;
|
||||||
|
unsigned char d : 1;
|
||||||
|
unsigned char e : 1;
|
||||||
|
unsigned char f : 1;
|
||||||
|
unsigned char g : 1;
|
||||||
|
unsigned char h : 1; // 高位
|
||||||
|
};
|
||||||
|
|
||||||
|
union REG_UNI
|
||||||
|
{
|
||||||
|
struct REG reg;
|
||||||
|
unsigned char ch;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
union REG_UNI reg1 = {{1, 0, 0, 0, 1, 0, 0, 0}};
|
||||||
|
// reg1.ch 可以把每一位的值都取出来,但是不能修改,读取顺序是从低位到高位,倒序读取 0b00001001
|
||||||
|
printf("%#x\n", reg1.ch); // 0x11
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
// 枚举 enum
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
typedef enum front_color_e
|
||||||
|
{
|
||||||
|
BLACK = 30, // 黑色
|
||||||
|
RED, // 红色
|
||||||
|
GREEN, // 绿色
|
||||||
|
YELLOW, // 黄色
|
||||||
|
BLUE, // 蓝色
|
||||||
|
PURPLE, // 紫色
|
||||||
|
CYAN, // 青色
|
||||||
|
WHITE, // 白色
|
||||||
|
} Front_Color; // 前景色
|
||||||
|
|
||||||
|
typedef enum back_color_e
|
||||||
|
{
|
||||||
|
BLACK_B = 40, // 黑色
|
||||||
|
RED_B, // 红色
|
||||||
|
GREEN_B, // 绿色
|
||||||
|
YELLOW_B, // 黄色
|
||||||
|
BLUE_B, // 蓝色
|
||||||
|
PURPLE_B, // 紫色
|
||||||
|
CYAN_B, // 青色
|
||||||
|
WHITE_B, // 白色
|
||||||
|
} Back_Color; // 背景色
|
||||||
|
|
||||||
|
typedef enum attr_e
|
||||||
|
{
|
||||||
|
BOLD = 1, // 加粗
|
||||||
|
UNDERLINE = 4, // 下划线
|
||||||
|
BLINK, // 闪烁
|
||||||
|
REVERSE = 7, // 反显
|
||||||
|
HIDE, // 隐藏
|
||||||
|
} Attr; // 文本属性
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// 彩色字体测试
|
||||||
|
printf("\033[%d;%d;%dmHello, \033[0m\033[%d;%d;%dmworld!\033[0m \n", BOLD, RED, CYAN_B, GREEN, WHITE_B, UNDERLINE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// 定义学生信息的数据结构,链表的节点
|
||||||
|
typedef struct stu_s
|
||||||
|
{
|
||||||
|
char sid;
|
||||||
|
char name[32];
|
||||||
|
int age;
|
||||||
|
|
||||||
|
struct stu_s *next;
|
||||||
|
} STU;
|
||||||
|
|
||||||
|
void shows(STU *head)
|
||||||
|
{
|
||||||
|
STU *pi = head;
|
||||||
|
printf("学号\t姓名\t年龄\n");
|
||||||
|
|
||||||
|
while (NULL != pi)
|
||||||
|
{
|
||||||
|
printf("%d\t%s\t%d\n", pi->sid, pi->name, pi->age);
|
||||||
|
pi = pi->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STU *insert_head(STU *head, STU *item)
|
||||||
|
{
|
||||||
|
printf("2 %p\n", head);
|
||||||
|
|
||||||
|
// 实现头部插入
|
||||||
|
if (NULL == head) // 如果是第一个节点(空链表)
|
||||||
|
{
|
||||||
|
head = item;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item->next = head; // 新节点指向原来的头节点
|
||||||
|
head = item; // item 变成新的头节点
|
||||||
|
}
|
||||||
|
printf("3 %p\n", head);
|
||||||
|
|
||||||
|
return head; // 返回头节点,头指针不能改变
|
||||||
|
}
|
||||||
|
|
||||||
|
STU *insert_end(STU *head, STU *item)
|
||||||
|
{
|
||||||
|
// 实现尾部插入
|
||||||
|
if (NULL == head) // 如果是第一个节点(空链表)
|
||||||
|
{
|
||||||
|
head = item;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
STU *pi = head;
|
||||||
|
while (NULL != pi->next)
|
||||||
|
{
|
||||||
|
pi = pi->next;
|
||||||
|
}
|
||||||
|
pi->next = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return head; // 返回头节点,头指针不能改变
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// 静态生成学生信息的链表
|
||||||
|
STU s1 = {1, "张三", 18, NULL}; // 头节点: 参数说明: 学号, 姓名, 年龄, 下一个节点的地址
|
||||||
|
STU s2 = {2, "李四", 19, NULL};
|
||||||
|
STU s3 = {3, "王五", 20, NULL};
|
||||||
|
|
||||||
|
STU *head = &s1; // 头节点
|
||||||
|
s1.next = &s2; // 头节点指向第二个节点
|
||||||
|
s2.next = &s3; // 第二个节点指向第三个节点
|
||||||
|
s3.next = NULL; // 第三个节点指向空
|
||||||
|
|
||||||
|
STU s4 = {4, "赵六", 21};
|
||||||
|
head = insert_head(head, &s4); // 头插法,地址会改变,需要返回头节点,主函数需要接收
|
||||||
|
|
||||||
|
printf("1 %p\n", head);
|
||||||
|
|
||||||
|
shows(head);
|
||||||
|
|
||||||
|
// insert_end(head, &(STU){5, "孙七", 22, NULL});
|
||||||
|
head = insert_head(head, &(STU){5, "孙七", 22, NULL}); // 临时变量,存在栈中,函数结束后会被释放,需要返回头节点,主函数需要接收
|
||||||
|
|
||||||
|
printf("1 %p\n", head);
|
||||||
|
|
||||||
|
shows(head);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// 定义学生信息的数据结构,链表的节点
|
||||||
|
typedef struct stu_s
|
||||||
|
{
|
||||||
|
char sid;
|
||||||
|
char name[32];
|
||||||
|
int age;
|
||||||
|
|
||||||
|
struct stu_s *next;
|
||||||
|
} STU;
|
||||||
|
|
||||||
|
void shows(STU *head)
|
||||||
|
{
|
||||||
|
STU *pi = head;
|
||||||
|
printf("学号\t姓名\t年龄\n");
|
||||||
|
|
||||||
|
while (NULL != pi)
|
||||||
|
{
|
||||||
|
printf("%d\t%s\t%d\n", pi->sid, pi->name, pi->age);
|
||||||
|
pi = pi->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STU *insert_head(STU *head, STU new_stu)
|
||||||
|
{
|
||||||
|
// 动态创建新节点
|
||||||
|
STU *new_node = (STU *)malloc(sizeof(STU));
|
||||||
|
*new_node = new_stu;
|
||||||
|
|
||||||
|
// 实现头部插入
|
||||||
|
if (NULL == head) // 如果是第一个节点(空链表)
|
||||||
|
{
|
||||||
|
head = new_node;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 头结点变第二个节点,新节点变头结点
|
||||||
|
new_node->next = head; // 新节点指向头节点
|
||||||
|
head = new_node; // 头指针指向新节点
|
||||||
|
}
|
||||||
|
|
||||||
|
return head; // 返回头节点,头指针不能改变
|
||||||
|
}
|
||||||
|
|
||||||
|
STU *insert_end(STU *head, STU *item)
|
||||||
|
{
|
||||||
|
// 实现尾部插入
|
||||||
|
if (NULL == head) // 如果是第一个节点(空链表)
|
||||||
|
{
|
||||||
|
head = item;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
STU *pi = head;
|
||||||
|
while (NULL != pi->next)
|
||||||
|
{
|
||||||
|
pi = pi->next;
|
||||||
|
}
|
||||||
|
pi->next = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return head; // 返回头节点,头指针不能改变
|
||||||
|
}
|
||||||
|
|
||||||
|
STU *insert_sort(STU *head, STU *item)
|
||||||
|
{
|
||||||
|
if (NULL == head)
|
||||||
|
return item;
|
||||||
|
|
||||||
|
if (head->age > item->age)
|
||||||
|
{
|
||||||
|
item->next = head;
|
||||||
|
head = item;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
STU *pi = head;
|
||||||
|
while (NULL != pi->next && pi->next->age < item->age)
|
||||||
|
{
|
||||||
|
pi = pi->next;
|
||||||
|
}
|
||||||
|
item->next = pi->next;
|
||||||
|
pi->next = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// 静态生成学生信息的链表
|
||||||
|
STU s1 = {1, "张三", 18, NULL}; // 头节点: 参数说明: 学号, 姓名, 年龄, 下一个节点的地址
|
||||||
|
STU s2 = {2, "李四", 19, NULL};
|
||||||
|
STU s3 = {3, "王五", 20, NULL};
|
||||||
|
|
||||||
|
STU *head = NULL; // 头节点
|
||||||
|
head = insert_sort(head, &s1);
|
||||||
|
head = insert_sort(head, &s2);
|
||||||
|
head = insert_sort(head, &s3);
|
||||||
|
head = insert_sort(head, &(STU){4, "赵六", 17, NULL});
|
||||||
|
|
||||||
|
shows(head);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// 定义学生信息的数据结构,链表的节点
|
||||||
|
typedef struct stu_s
|
||||||
|
{
|
||||||
|
char sid;
|
||||||
|
char name[32];
|
||||||
|
int age;
|
||||||
|
|
||||||
|
struct stu_s *next;
|
||||||
|
} STU;
|
||||||
|
|
||||||
|
void shows(STU *head)
|
||||||
|
{
|
||||||
|
STU *pi = head;
|
||||||
|
printf("学号\t姓名\t年龄\n");
|
||||||
|
|
||||||
|
while (NULL != pi)
|
||||||
|
{
|
||||||
|
printf("%d\t%s\t%d\n", pi->sid, pi->name, pi->age);
|
||||||
|
pi = pi->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STU *delete_stu(STU *head, char sid)
|
||||||
|
{
|
||||||
|
if (NULL == head)
|
||||||
|
{
|
||||||
|
printf("链表为空,无法删除\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (head->sid == sid)
|
||||||
|
{
|
||||||
|
// 如果 head 节点的内存是在堆区分配的,那么需要释放
|
||||||
|
// STU *tmp = head;
|
||||||
|
head = head->next;
|
||||||
|
// free(tmp);
|
||||||
|
// return head;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
STU *pi = head;
|
||||||
|
while (NULL != pi->next && pi->next->sid != sid)
|
||||||
|
{
|
||||||
|
pi = pi->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有找到删除的节点
|
||||||
|
if (NULL == pi->next)
|
||||||
|
{
|
||||||
|
printf("没有找到要删除的节点\n");
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
// 找到了要删除的节点
|
||||||
|
STU *pn = pi->next; // 要删除的节点
|
||||||
|
pi->next = pn->next; // 要删除的节点的前一个节点指向要删除的节点的后一个节点
|
||||||
|
free(pn); // 释放要删除的节点
|
||||||
|
|
||||||
|
printf("删除成功\n");
|
||||||
|
// return head;
|
||||||
|
}
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// 静态生成学生信息的链表
|
||||||
|
STU s1 = {1, "张三", 18, NULL}; // 头节点: 参数说明: 学号, 姓名, 年龄, 下一个节点的地址
|
||||||
|
STU s2 = {2, "李四", 19, NULL};
|
||||||
|
STU s3 = {3, "王五", 20, NULL};
|
||||||
|
|
||||||
|
STU *head = &s1; // 头节点
|
||||||
|
s1.next = &s2; // 头节点指向第二个节点
|
||||||
|
s2.next = &s3; // 第二个节点指向第三个节点
|
||||||
|
s3.next = NULL; // 第三个节点指向空
|
||||||
|
|
||||||
|
printf("1 %p\n", head);
|
||||||
|
shows(head);
|
||||||
|
|
||||||
|
head = delete_stu(head, 1);
|
||||||
|
|
||||||
|
printf("1 %p\n", head);
|
||||||
|
shows(head);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// 定义学生信息的数据结构,链表的节点
|
||||||
|
typedef struct stu_s
|
||||||
|
{
|
||||||
|
char sid;
|
||||||
|
char name[32];
|
||||||
|
int age;
|
||||||
|
|
||||||
|
struct stu_s *next;
|
||||||
|
} STU;
|
||||||
|
|
||||||
|
void shows(STU *head)
|
||||||
|
{
|
||||||
|
STU *pi = head;
|
||||||
|
printf("学号\t姓名\t年龄\n");
|
||||||
|
|
||||||
|
while (NULL != pi)
|
||||||
|
{
|
||||||
|
printf("%d\t%s\t%d\n", pi->sid, pi->name, pi->age);
|
||||||
|
pi = pi->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STU *find_stu(STU *head, char sid)
|
||||||
|
{
|
||||||
|
if (NULL == head)
|
||||||
|
{
|
||||||
|
printf("链表为空,无法查找\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (head->sid == sid)
|
||||||
|
{
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
STU *pi = head;
|
||||||
|
while (NULL != pi->next && pi->next->sid != sid)
|
||||||
|
{
|
||||||
|
pi = pi->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有找到删除的节点
|
||||||
|
if (NULL == pi->next)
|
||||||
|
{
|
||||||
|
printf("没有找到要查找的节点\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// 找到了要删除的节点
|
||||||
|
STU *pn = pi->next; // 要删除的节点
|
||||||
|
return pn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// 静态生成学生信息的链表
|
||||||
|
STU s1 = {1, "张三", 18, NULL}; // 头节点: 参数说明: 学号, 姓名, 年龄, 下一个节点的地址
|
||||||
|
STU s2 = {2, "李四", 19, NULL};
|
||||||
|
STU s3 = {3, "王五", 20, NULL};
|
||||||
|
|
||||||
|
STU *head = &s1; // 头节点
|
||||||
|
s1.next = &s2; // 头节点指向第二个节点
|
||||||
|
s2.next = &s3; // 第二个节点指向第三个节点
|
||||||
|
s3.next = NULL; // 第三个节点指向空
|
||||||
|
|
||||||
|
shows(head);
|
||||||
|
|
||||||
|
STU *item = find_stu(head, 2);
|
||||||
|
if (NULL != item)
|
||||||
|
{
|
||||||
|
printf("找到了\n");
|
||||||
|
printf("%d\t%s\t%d\n", item->sid, item->name, item->age);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("没有找到\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// shows(head);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue