提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
提示:这里可以添加本文要记录的大概内容:
这里面有10个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie树;10个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法。。
1、时间复杂度(最好情况时间复杂度、最坏情况时间复杂度、平均时间复杂度)
2、空间复杂度
2.1 数据结构的逻辑结构
数据结构中的逻辑结构(附上c++中的常见数据结构的逻辑结构)_数据结构的逻辑结构有哪些-CSDN博客
数据结构的逻辑结构包括四种逻辑结构
1、集合结构
2、线性结构:一一对应
3、树形结构
4、图形结构

看了一个抖音,里面讲了静态链表和动态链表。之前看的静态链表讲的蛮好的。觉得还挺简单的。今天又看到了讲动态链表的。当时就有个疑问。new出来的stu_new的next指针不需要值NULL吗?一直带着这个疑问。还评论了一下,想看看别人是怎么说的。然后回工位还在想这件事情。然后就觉得写一下吧,感觉不是很难,然后就写下了下面的代码。
下面的代码基本实现了视频里的效果。后面还要跟视频的作下对比。
- #include
- #include
- #include "string.h"
-
- //动态指针
- //①枚举类型不会写(成员不会写)
- //②结构体指针写法不会写
- //scanf循环
-
-
- //性别
- typedef enum Gender
- {
- male,
- female,
- middle
- }Gend;
-
- //结构体
- typedef struct stu
- {
- char name[10];
- int age;
- Gend gender;
- int score;
- struct stu* next;
- }Stu;
-
- Stu stuDynamic;
-
- int stuAdd(Stu* stu)
- {
- if(NULL == stu)
- {
- return -1;
- }
-
- Stu *stuTemp = &stuDynamic;
-
- while(stuTemp->next)
- {
- stuTemp = stuTemp->next;
- }
-
- stuTemp->next = stu;
-
- return 1;
- }
-
- void printStu(Stu* stu)
- {
- Stu* temp = stu->next;
- printf("打印学生信息\n");
- while(temp)
- {
- printf("姓名:%s, 年龄:%d, 性别:%d, 成绩:%d\n", temp->name, temp->age, temp->gender, temp->score);
- temp = temp->next;
- }
- }
-
- int main()
- {
- char name[10] = {'\0'};
- int age = -1;
- int score;
- Gend gender;
- printf("输入姓名, 年龄, 性别, 分数\n");
- // gets("%s", name);
- // scanf("%d", &age);
- // scanf("%d", &score);
- // scanf("%d", &gender);
-
- while(age != 0)
- {
- scanf("%s %d %d %d", name, &age, &gender, &score);
- Stu *stu_new = (Stu*)malloc(sizeof(Stu));
- if(NULL == stu_new)
- {
- printf("malloc fail");
- continue;
- }
-
- memcpy(stu_new->name, name, 10);
- stu_new->age = age;
- stu_new->score = score;
- stu_new->gender = gender;
- stu_new->next = NULL;
-
-
- stuAdd(stu_new);
-
- printStu(&stuDynamic);
- }
-
- return 0;
- }
但是其中还是有一个问题。就是我一开始写的代码是没有将stu_new的next指针置空的。那个代码就异常了。体现在没有让我继续输入数据,然后也打印了,打印后就退出了。 然后调试的时候发现程序在print里面会异常退出。
现在来看就是因为stu_new没有置为NULL。所以我之前的考虑是对的。那么视频里的程序是怎么写的呢,需要在会看一下视频代码。下面就把之前写的代码贴出来。
- #include
- #include
- #include "string.h"
-
- //动态指针
- //①枚举类型不会写(成员不会写)
- //②结构体指针写法不会写
- //scanf循环
-
-
- //性别
- typedef enum Gender
- {
- male,
- female,
- middle
- }Gend;
-
- //结构体
- typedef struct stu
- {
- char name[10];
- int age;
- Gend gender;
- int score;
- struct stu* next;
- }Stu;
-
- Stu stuDynamic;
-
- int stuAdd(Stu* stu)
- {
- if(NULL == stu)
- {
- return -1;
- }
-
- Stu *stuTemp = &stuDynamic;
-
- while(stuTemp->next)
- {
- stuTemp = stuTemp->next;
- }
-
- stuTemp->next = stu;
-
- return 1;
- }
-
- void printStu(Stu* stu)
- {
- Stu* temp = stu;
- printf("打印学生信息\n");
- while(temp)
- {
- printf("姓名:%s, 年龄:%d, 性别:%d, 成绩:%d\n", temp->name, temp->age, temp->gender, temp->score);
- temp = temp->next;
- }
- }
-
- int main()
- {
- char name[10] = {'\0'};
- int age = -1;
- int score;
- Gend gender;
- printf("输入姓名, 年龄, 性别, 分数\n");
- // gets("%s", name);
- // scanf("%d", &age);
- // scanf("%d", &score);
- // scanf("%d", &gender);
-
- while(age != 0)
- {
- scanf("%s %d %d %d", name, &age, &gender, &score);
- Stu *stu_new = (Stu*)malloc(sizeof(Stu));
- if(NULL == stu_new)
- {
- printf("malloc fail");
- continue;
- }
-
- memcpy(stu_new->name, name, 10);
- stu_new->age = age;
- stu_new->score = score;
- stu_new->gender = gender;
-
- stuAdd(stu_new);
-
- printStu(&stuDynamic);
- }
-
- return 0;
- }
所以当stu_new的next指针没有置为NULL的时候,程序会越界访问。导致程序崩溃结束。看起来的效果就像是程序执行完了一样。
随后还有个问题,就是全局变量stuDynamic的next指针时NULL吗?
自己写了代码验证
- #include
- #include
- #include "string.h"
-
- Stu stuDynamic;
-
- int main()
- {
- if(NULL == stuDynamic.next)
- {
- printf("stuDynamic->next:%p\n", stuDynamic.next);
- printf("stuDynamic->next is NULL\n");
- }
- }
-
- //stuDynamic->next:00000000
- //stuDynamic->next is NULL
查了一个帖子:全局变量和局部变量初始化问题_全局变量需要初始化吗-CSDN博客
里面这么表述:这里需要分清一个事实,是变量系统都会默认给初始化,只不过全局变量默认初始化为0,而局部变量被初始化为随机数,这个随机数用不了,后面会验证
看了视频代码,有以下几点需要说明下
①全局变量没有写成g_xxx
②视频代码重复输入是因为用了while(1)
③视频的打印也是从g_stu开始打印,所以有全是0的输出,name是空
后面可以优化代码。
下面是优化代码,下面的代码实现了修改和查询
- #include
- #include
- #include "string.h"
- #include "stdbool.h"
-
- //动态指针
- //①枚举类型不会写(成员不会写)
- //②结构体指针写法不会写
- //③scanf循环
- //④scanf用法
- //⑤switch-case写法
- //⑥strcpy == 0,没有判断是否==0,导致直接打印0
- //⑦解决scanf读单个字符会把换行符\n读取,且字符变量中只存了\n
- //⑧将strcmp用错成strcpy,导致出现修改时所有数据都被改了
-
-
- //性别
- typedef enum Gender
- {
- male,
- female,
- middle
- }Gend;
-
- //结构体
- typedef struct stu
- {
- char name[10];
- int age;
- Gend gender;
- int score;
- struct stu* next;
- }Stu;
-
- Stu g_stuDaynamic;
-
- //增加
- int stu_add(Stu* stu)
- {
- if(NULL == stu)
- {
- return -1;
- }
-
- Stu *stuTemp = &g_stuDaynamic;
-
- while(stuTemp->next)
- {
- stuTemp = stuTemp->next;
- }
-
- stuTemp->next = stu;
-
- return 1;
- }
-
- //查询
- int stu_find(Stu* stu, char* name)
- {
- Stu *temp = stu;
- while(NULL == temp)
- {
- return -1;
- }
-
- while(temp)
- {
- if( strcmp(temp->name, name) == 0)
- {
- printf("find the record");
- printf("姓名:%s, 年龄:%d, 性别:%d, 成绩:%d\n", temp->name, temp->age, temp->gender, temp->score);
-
- return 1;
- }
- temp = temp->next;
- }
-
- printf("find the record Empty!");
- }
-
- //修改
- int stu_modify(const Stu* stu, Stu* stu_modify)
- {
- if(NULL == stu)
- {
- return -1;
- }
-
- Stu* temp = stu;
- while(temp)
- {
- if(strcmp(temp->name, stu_modify->name) == 0)
- {
- (*temp).age = stu_modify->age;
- (*temp).gender = stu_modify->gender;
- (*temp).score = stu_modify->score;
-
- return 1;
- }
- temp = temp->next;
- }
- }
-
- void printStu(Stu* stu)
- {
- Stu* temp = stu->next;
- printf("打印学生信息\n");
- while(temp)
- {
- printf("姓名:%s, 年龄:%d, 性别:%d, 成绩:%d\n", temp->name, temp->age, temp->gender, temp->score);
- temp = temp->next;
- }
- }
-
- int action_add()
- {
- char name[10] = {'\0'};
- int age;
- int score;
- Gend gender;
-
- printf("输入姓名, 年龄, 性别, 分数\n");
- scanf("%s %d %d %d", name, &age, &gender, &score);
- Stu* stu_new = (Stu*)malloc(sizeof(Stu));
- if(NULL == stu_new)
- {
- printf("malloc fail");
- return -1;
- }
-
- memcpy(stu_new->name, name, 10);
- stu_new->age = age;
- stu_new->score = score;
- stu_new->gender = gender;
- stu_new->next = NULL;
-
- stu_add(stu_new);
-
- printStu(&g_stuDaynamic);
- }
-
- int action_find(char* name)
- {
- stu_find(&g_stuDaynamic, name);
- return 0;
- }
-
- int action_modify()
- {
- char name[10] = {'\0'};
- int age;
- int score;
- Gend gender;
-
- Stu *stu_modify_new = (Stu*)malloc(sizeof(Stu));
- if(NULL == stu_modify_new)
- {
- printf("malloc fail");
- return -1;
- }
-
- printf("输入修改的姓名, 年龄, 性别, 分数\n");
- scanf("%s %d %d %d", name, &age, &gender, &score);
-
- memcpy(stu_modify_new->name, name, 10);
- stu_modify_new->age = age;
- stu_modify_new->score = score;
- stu_modify_new->gender = gender;
-
- stu_modify(&g_stuDaynamic, stu_modify_new);
-
- free(stu_modify_new);
-
- printStu(&g_stuDaynamic);
-
- return 1;
- }
-
- int main()
- {
- bool m_flag = true;
- if(NULL == g_stuDaynamic.next)
- {
- printf("g_stuDaynamic->next:%p\n", g_stuDaynamic.next);
- printf("g_stuDaynamic->next is NULL\n");
- }
-
- while(m_flag)
- {
- printf("选择操作(A:增加、D:删除、C:更改、F:查找、其他:退出):\n");
- char action[2];
- scanf("%s", action);
- switch(action[0])
- {
- case 'A':
- {
- action_add();
- break;
- }
-
- case 'F':
- {
- printf("输入查询的姓名:\n");
- char name[100];
- scanf("%s", name);
- action_find(name);
- break;
- }
-
- case 'C':
- {
- action_modify();
- break;
- }
-
- default:
- {
- m_flag = false;
- break;
- }
- }
- }
-
- return 0;
- }
-
-
-
这个代码还在编译时出现一个警告:
warning:initialization discards ‘const’ qualifier from pointer target type
那么就存在一个问题,就是我不想函数更改g_stuDaynamic变量。所以用const限定为只读变量。但是在函数中还要遍历链表,temp又不能增加const修饰。但是赋值时就出现这个告警。下次看看教科书别人是怎么处理的。
还有一个删除的功能没有实现,这个会涉及到链表头、尾的问题,先阶段性提交一次。
下面是增加删除的代码
- #include
- #include
- #include "string.h"
- #include "stdbool.h"
- #include "ctype.h"
-
- //动态指针
- //①枚举类型不会写(成员不会写)
- //②结构体指针写法不会写
- //③scanf循环
- //④scanf用法
- //⑤switch-case写法
- //⑥strcpy == 0,没有判断是否==0,导致直接打印0
- //⑦解决scanf读单个字符会把换行符\n读取,且字符变量中只存了\n
-
-
- //性别
- typedef enum Gender
- {
- male,
- female,
- middle
- }Gend;
-
- //结构体
- typedef struct stu
- {
- char name[10];
- int age;
- Gend gender;
- int score;
- struct stu* next;
- }Stu;
-
- Stu g_stuDaynamic;
-
- int stu_add(Stu* stu)
- {
- if(NULL == stu)
- {
- return -1;
- }
-
- Stu *stuTemp = &g_stuDaynamic;
-
- while(stuTemp->next)
- {
- stuTemp = stuTemp->next;
- }
-
- stuTemp->next = stu;
-
- return 1;
- }
-
- int stu_find(Stu* stu, char* name)
- {
- Stu *temp = stu;
- while(NULL == temp)
- {
- return -1;
- }
-
- while(temp)
- {
- if( strcmp(temp->name, name) == 0)
- {
- printf("find the record");
- printf("姓名:%s, 年龄:%d, 性别:%d, 成绩:%d\n", temp->name, temp->age, temp->gender, temp->score);
-
- return 1;
- }
- temp = temp->next;
- }
-
- printf("find the record Empty!");
- }
-
- int stu_modify(const Stu* stu, Stu* stu_modify)
- {
- if(NULL == stu)
- {
- return -1;
- }
-
- Stu* temp = stu;
- while(temp)
- {
- if(strcmp(temp->name, stu_modify->name) == 0)
- {
- (*temp).age = stu_modify->age;
- (*temp).gender = stu_modify->gender;
- (*temp).score = stu_modify->score;
-
- return 1;
- }
- temp = temp->next;
- }
- }
-
- //删除
- int stu_delete(Stu* stu, char* name)
- {
- if (NULL == stu)
- {
- return -1;
- }
-
- Stu* temp = stu;
- while (temp)
- {
- if(NULL != temp->next && strcmp(temp->next->name, name) == 0)
- {
- //目标节点在重点
- Stu* traget = temp->next;
- Stu* tragetNext = traget->next;
- temp->next = tragetNext;
- free(traget);
-
- printf("已找到记录并删除\n");
- return 1;
- }
- temp = temp->next;
- }
-
- printf("未找到可删除记录\n");
- return 0;
- }
-
- void printStu(Stu* stu)
- {
- Stu* temp = stu->next;
- printf("打印学生信息\n");
- while(temp)
- {
- printf("姓名:%s, 年龄:%d, 性别:%d, 成绩:%d\n", temp->name, temp->age, temp->gender, temp->score);
- temp = temp->next;
- }
- }
-
- int action_add()
- {
- char name[10] = {'\0'};
- int age;
- int score;
- Gend gender;
-
- printf("输入姓名, 年龄, 性别, 分数\n");
- scanf("%s %d %d %d", name, &age, &gender, &score);
- Stu* stu_new = (Stu*)malloc(sizeof(Stu));
- if(NULL == stu_new)
- {
- printf("malloc fail");
- return -1;
- }
-
- memcpy(stu_new->name, name, 10);
- stu_new->age = age;
- stu_new->score = score;
- stu_new->gender = gender;
- stu_new->next = NULL;
-
- stu_add(stu_new);
-
- printStu(&g_stuDaynamic);
- }
-
- int action_find(char* name)
- {
- stu_find(&g_stuDaynamic, name);
- return 0;
- }
-
- int action_modify()
- {
- char name[10] = {'\0'};
- int age;
- int score;
- Gend gender;
-
- Stu *stu_modify_new = (Stu*)malloc(sizeof(Stu));
- if(NULL == stu_modify_new)
- {
- printf("malloc fail");
- return -1;
- }
-
- printf("输入修改的姓名, 年龄, 性别, 分数\n");
- scanf("%s %d %d %d", name, &age, &gender, &score);
-
- memcpy(stu_modify_new->name, name, 10);
- stu_modify_new->age = age;
- stu_modify_new->score = score;
- stu_modify_new->gender = gender;
-
- stu_modify(&g_stuDaynamic, stu_modify_new);
-
- free(stu_modify_new);
-
- printStu(&g_stuDaynamic);
-
- return 1;
- }
-
- int action_delete()
- {
- printf("输入需要删除的记录:\n");
- char* name[100];
- scanf("%s", name);
- stu_delete(&g_stuDaynamic, name);
- printStu(&g_stuDaynamic);
- return 0;
- }
-
- bool isTargetAlpha(char c)
- {
- if(toupper(c) == 'A' || toupper(c) == 'D' || toupper(c) == 'C' || toupper(c) == 'F' || toupper(c) == 'Q')
- {
- return true;
- }
-
- return false;
- }
-
- int main()
- {
- bool m_flag = true;
- if(NULL == g_stuDaynamic.next)
- {
- printf("g_stuDaynamic->next:%p\n", g_stuDaynamic.next);
- printf("g_stuDaynamic->next is NULL\n");
- }
-
- while(m_flag)
- {
- printf("选择操作(A:增加、D:删除、C:更改、F:查找、Q:退出):\n");
- char action[2];
- scanf("%s", action);
- if(!isTargetAlpha(action[0]))
- {
- continue;
- }
- switch(toupper(action[0]))
- {
- case 'A':
- {
- action_add();
- break;
- }
-
- case 'F':
- {
- printf("输入查询的姓名:\n");
- char name[100];
- scanf("%s", name);
- action_find(name);
- break;
- }
-
- case 'C':
- {
- action_modify();
- break;
- }
-
- case 'D':
- {
- action_delete();
- break;
- }
-
- case 'Q':
- {
- m_flag = false;
- printf("退出\n");
- break;
- }
-
- default:
- {
- printf("操作有误,请重新输入\n");
- break;
- }
- }
- }
-
- return 0;
- }
-
-
-
感觉比想象的简单,没有之前那么复杂啊。
反正自验证实现了功能,目前还遗留的就是输错信息,程序直接退出了。需要优化下。
另外印象中删除好像还挺复杂呢?
2024年1月11日20:01:11
下面就是所谓的复杂的。现在写的是插入。好像删除也不复杂,之前印象中复杂的只有插入。不然链表也太难了吧。同时参考C和指针的书籍。其实这个代码一直你有一个问题,就是我在函数里把g_stuDaynamic写死了,不能处理其他的链表,没有通用性。这个也是看C和指针的书才发现的啊!!
-
-
- #include "test.h"
-
- //动态指针
- //①枚举类型不会写(成员不会写)
- //②结构体指针写法不会写
- //③scanf循环
- //④scanf用法
- //⑤switch-case写法
- //⑥strcpy == 0,没有判断是否==0,导致直接打印0
- //⑦解决scanf读单个字符会把换行符\n读取,且字符变量中只存了\n
-
-
- //性别
- typedef enum Gender
- {
- male,
- female,
- middle
- }Gend;
-
- //结构体
- typedef struct stu
- {
- char name[10];
- int age;
- Gend gender;
- int score;
- struct stu* next;
- }Stu;
-
- Stu g_stuDaynamic;
-
- int stu_add(Stu* stu)
- {
- if(NULL == stu)
- {
- return -1;
- }
-
- Stu *stuTemp = &g_stuDaynamic;
-
- while(stuTemp->next)
- {
- stuTemp = stuTemp->next;
- }
-
- stuTemp->next = stu;
-
- return 1;
- }
-
- //插入数据有序排列
- void stu_insert(Stu* new)
- {
- Stu* previous;
- Stu* current;
- Stu* next;
-
- previous = &g_stuDaynamic;
- current = g_stuDaynamic.next;
-
- while(current->next != NULL && current->score <= new->score )
- {
- previous = current;
- current = current->next;
- }
-
- if(current->next == NULL)
- {
- current->next = new;
- }
- else
- {
- previous->next = new;
- new->next = current;
- }
- }
-
- int stu_find(Stu* stu, char* name)
- {
- Stu *temp = stu;
- while(NULL == temp)
- {
- return -1;
- }
-
- while(temp)
- {
- if( strcmp(temp->name, name) == 0)
- {
- printf("find the record");
- printf("姓名:%s, 年龄:%d, 性别:%d, 成绩:%d\n", temp->name, temp->age, temp->gender, temp->score);
-
- return 1;
- }
- temp = temp->next;
- }
-
- printf("find the record Empty!");
- }
-
- int stu_modify(const Stu* stu, Stu* stu_modify)
- {
- if(NULL == stu)
- {
- return -1;
- }
-
- Stu* temp = stu;
- while(temp)
- {
- if(strcmp(temp->name, stu_modify->name) == 0)
- {
- (*temp).age = stu_modify->age;
- (*temp).gender = stu_modify->gender;
- (*temp).score = stu_modify->score;
-
- return 1;
- }
- temp = temp->next;
- }
- }
-
- //删除
- int stu_delete(Stu* stu, char* name)
- {
- if (NULL == stu)
- {
- return -1;
- }
-
- Stu* temp = stu;
- while (temp)
- {
- if(NULL != temp->next && strcmp(temp->next->name, name) == 0)
- {
- //目标节点在重点
- Stu* traget = temp->next;
- Stu* tragetNext = traget->next;
- temp->next = tragetNext;
- free(traget);
-
- printf("已找到记录并删除\n");
- return 1;
- }
- temp = temp->next;
- }
-
- printf("未找到可删除记录\n");
- return 0;
- }
-
- void printStu(Stu* stu)
- {
- Stu* temp = stu->next;
- printf("打印学生信息\n");
- while(temp)
- {
- printf("姓名:%s, 年龄:%d, 性别:%d, 成绩:%d\n", temp->name, temp->age, temp->gender, temp->score);
- temp = temp->next;
- }
- }
-
- int action_add()
- {
- char name[10] = {'\0'};
- int age;
- int score;
- Gend gender;
-
- printf("输入姓名, 年龄, 性别, 分数\n");
- scanf("%s %d %d %d", name, &age, &gender, &score);
- Stu* stu_new = (Stu*)malloc(sizeof(Stu));
- if(NULL == stu_new)
- {
- printf("malloc fail");
- return -1;
- }
-
- memcpy(stu_new->name, name, 10);
- stu_new->age = age;
- stu_new->score = score;
- stu_new->gender = gender;
- stu_new->next = NULL;
-
- stu_add(stu_new);
-
- printStu(&g_stuDaynamic);
- }
-
- //插入数据进行有序排列
- int action_insert()
- {
- char name[10] = {'\0'};
- int age;
- int score;
- Gend gender;
-
- printf("输入姓名、年龄、性别、分数\n");
- scanf("%s %d %d %d", name, &age, &gender, &score);
- Stu* stu_new = (Stu*)malloc(sizeof(Stu));
- if(NULL == stu_new)
- {
- printf("malloc fail");
- return -1;
- }
-
- memcpy(stu_new->name, name, 10);
- stu_new->age = age;
- stu_new->score = score;
- stu_new->gender = gender;
- stu_new->next = NULL;
-
- stu_insert(stu_new);
-
- printStu(&g_stuDaynamic);
- }
-
- int action_find(char* name)
- {
- stu_find(&g_stuDaynamic, name);
- return 0;
- }
-
- int action_modify()
- {
- char name[10] = {'\0'};
- int age;
- int score;
- Gend gender;
-
- Stu *stu_modify_new = (Stu*)malloc(sizeof(Stu));
- if(NULL == stu_modify_new)
- {
- printf("malloc fail");
- return -1;
- }
-
- printf("输入修改的姓名, 年龄, 性别, 分数\n");
- scanf("%s %d %d %d", name, &age, &gender, &score);
-
- memcpy(stu_modify_new->name, name, 10);
- stu_modify_new->age = age;
- stu_modify_new->score = score;
- stu_modify_new->gender = gender;
-
- stu_modify(&g_stuDaynamic, stu_modify_new);
-
- free(stu_modify_new);
-
- printStu(&g_stuDaynamic);
-
- return 1;
- }
-
- int action_delete()
- {
- printf("输入需要删除的记录:\n");
- char* name[100];
- scanf("%s", name);
- stu_delete(&g_stuDaynamic, name);
- printStu(&g_stuDaynamic);
- return 0;
- }
-
- bool isTargetAlpha(char c)
- {
- if(toupper(c) == 'A' || toupper(c) == 'D' || toupper(c) == 'C' || toupper(c) == 'F' || toupper(c) == 'Q' || toupper(c) == 'I')
- {
- return true;
- }
-
- return false;
- }
-
- //int i = 0;
- //
- //void add() const
- //{
- // i++;
- //}
-
- int list_func()
- {
- // add();
-
- bool m_flag = true;
- if(NULL == g_stuDaynamic.next)
- {
- printf("g_stuDaynamic->next:%p\n", g_stuDaynamic.next);
- printf("g_stuDaynamic->next is NULL\n");
- }
-
- while(m_flag)
- {
- printf("选择操作(A:增加、D:删除、C:更改、F:查找、Q:退出):\n");
- // printf("选择操作(A:增加、D:删除、C、更改:\n");
- // printf("hello");
- char action[2];
- scanf("%s", action);
- if(!isTargetAlpha(action[0]))
- {
- continue;
- }
- switch(toupper(action[0]))
- {
- case 'A':
- {
- action_add();
- break;
- }
-
- case 'F':
- {
- printf("输入查询的姓名:\n");
- char name[100];
- scanf("%s", name);
- action_find(name);
- break;
- }
-
- case 'C':
- {
- action_modify();
- break;
- }
-
- case 'D':
- {
- action_delete();
- break;
- }
-
- case 'Q':
- {
- m_flag = false;
- printf("退出\n");
- break;
- }
-
- //插入数据有序排列
- case 'I':
- {
- action_insert();
- break;
- }
-
- default:
- {
- printf("操作有误,请重新输入\n");
- break;
- }
- }
-
-
- }
-
- return 0;
- }
-
-
- //g_stuDaynamic->next:00000000
- //g_stuDaynamic->next is NULL
- //选择操作(A:增加、D:删除、C:更改、F:查找、Q:退出):
- //A
- //输入姓名, 年龄, 性别, 分数
- //zhangs 7 0 77
- //打印学生信息
- //姓名:zhangs, 年龄:7, 性别:0, 成绩:77
- //选择操作(A:增加、D:删除、C:更改、F:查找、Q:退出):
- //A
- //输入姓名, 年龄, 性别, 分数
- //lilu 8 1 88
- //打印学生信息
- //姓名:zhangs, 年龄:7, 性别:0, 成绩:77
- //姓名:lilu, 年龄:8, 性别:1, 成绩:88
- //选择操作(A:增加、D:删除、C:更改、F:查找、Q:退出):
- //A
- //输入姓名, 年龄, 性别, 分数
- //wangmei 9 1 99
- //打印学生信息
- //姓名:zhangs, 年龄:7, 性别:0, 成绩:77
- //姓名:lilu, 年龄:8, 性别:1, 成绩:88
- //姓名:wangmei, 年龄:9, 性别:1, 成绩:99
- //选择操作(A:增加、D:删除、C:更改、F:查找、Q:退出):
- //I
- //输入姓名、年龄、性别、分数
- //xux 6 0 90
- //打印学生信息
- //姓名:zhangs, 年龄:7, 性别:0, 成绩:77
- //姓名:lilu, 年龄:8, 性别:1, 成绩:88
- //姓名:wangmei, 年龄:9, 性别:1, 成绩:99
- //姓名:xux, 年龄:6, 性别:0, 成绩:90
- //选择操作(A:增加、D:删除、C:更改、F:查找、Q:退出):
- //I
- //输入姓名、年龄、性别、分数
- //xiaom 6 1 80
- //打印学生信息
- //姓名:zhangs, 年龄:7, 性别:0, 成绩:77
- //姓名:xiaom, 年龄:6, 性别:1, 成绩:80
- //姓名:lilu, 年龄:8, 性别:1, 成绩:88
- //姓名:wangmei, 年龄:9, 性别:1, 成绩:99
- //姓名:xux, 年龄:6, 性别:0, 成绩:90
- //选择操作(A:增加、D:删除、C:更改、F:查找、Q:退出):
- //I
- //输入姓名、年龄、性别、分数
- //xiaoh 9 0 83
- //打印学生信息
- //姓名:zhangs, 年龄:7, 性别:0, 成绩:77
- //姓名:xiaom, 年龄:6, 性别:1, 成绩:80
- //姓名:xiaoh, 年龄:9, 性别:0, 成绩:83
- //姓名:lilu, 年龄:8, 性别:1, 成绩:88
- //姓名:wangmei, 年龄:9, 性别:1, 成绩:99
- //姓名:xux, 年龄:6, 性别:0, 成绩:90
- //选择操作(A:增加、D:删除、C:更改、F:查找、Q:退出):
-
-
上面的代码插入尾部的时候会异常,下面的可以正常插入尾部
- #include "test.h"
-
- //动态指针
- //①枚举类型不会写(成员不会写)
- //②结构体指针写法不会写
- //③scanf循环
- //④scanf用法
- //⑤switch-case写法
- //⑥strcpy == 0,没有判断是否==0,导致直接打印0
- //⑦解决scanf读单个字符会把换行符\n读取,且字符变量中只存了\n
-
-
- //性别
- typedef enum Gender
- {
- male,
- female,
- middle
- }Gend;
-
- //结构体
- typedef struct stu
- {
- char name[10];
- int age;
- Gend gender;
- int score;
- struct stu* next;
- }Stu;
-
- Stu g_stuDaynamic;
-
- int stu_add(Stu* stu)
- {
- if(NULL == stu)
- {
- return -1;
- }
-
- Stu *stuTemp = &g_stuDaynamic;
-
- while(stuTemp->next)
- {
- stuTemp = stuTemp->next;
- }
-
- stuTemp->next = stu;
-
- return 1;
- }
-
- //插入数据有序排列
- //存在最后一个节点判断异常
- void stu_insert1(Stu* new)
- {
- Stu* previous;
- Stu* current;
- Stu* next;
-
- previous = &g_stuDaynamic;
- current = g_stuDaynamic.next;
-
- while(current->next != NULL && current->score <= new->score )
- {
- previous = current;
- current = current->next;
- }
-
- if(current->next == NULL)
- {
- current->next = new;
- }
- else
- {
- previous->next = new;
- new->next = current;
- }
- }
-
- //处理有些复杂
- void stu_insert2(Stu* new)
- {
- Stu* previous;
- Stu* current;
- Stu* next;
-
- previous = &g_stuDaynamic;
- current = g_stuDaynamic.next;
-
- while(current->score <= new->score && current->next != NULL)
- {
- previous = current;
- current = current->next;
- }
-
- //这边处理起来有些吃力,感觉需要识别是因为到结尾了还是当前节点大于插入数据
- if(current->score > new->score)
- {
- previous->next = new;
- new->next = current;
- }
- else
- {
- current->next = new;
- }
- }
-
- //C和指针照着写
- void stu_insert3(Stu* new)
- {
- Stu* previous;
- Stu* current;
- Stu* next;
-
- previous = NULL;
- current = &g_stuDaynamic;
-
- while(current->score <= new->score && current != NULL)
- {
- previous = current;
- current = current->next;
- }
-
- //这边处理起来有些吃力,感觉需要识别是因为到结尾了还是当前节点大于插入数据
- if(current->score > new->score)
- {
- previous->next = new;
- new->next = current;
- }
- else
- {
- current->next = new;
- }
- }
-
- //C和指针照着写,程序死机
- void stu_insert4(Stu* new)
- {
- Stu* previous;
- Stu* current;
- Stu* next;
-
- previous = NULL;
- current = &g_stuDaynamic;
-
- while( current->score <= new->score && current != NULL) //这边内存泄漏,访问其他内存,没有先判断current是否为空
- {
- previous = current;
- current = current->next;
- }
-
- //这边处理起来有些吃力,感觉需要识别是因为到结尾了还是当前节点大于插入数据
- if(current->score > new->score)
- {
- previous->next = new;
- new->next = current;
- }
- else
- {
- previous->next = new;
- }
- }
-
- //C和指针照着写,程序死机
- void stu_insert5(Stu* new)
- {
- Stu* previous;
- Stu* current;
- Stu* next;
-
- previous = NULL;
- current = &g_stuDaynamic;
-
- while( current->score <= new->score && current != NULL) //这边内存泄漏,访问其他内存,没有先判断current是否为空
- {
- previous = current;
- current = current->next;
- }
-
- //这边处理起来有些吃力,感觉需要识别是因为到结尾了还是当前节点大于插入数据
-
- if(current->score > new->score) //这边内存泄露,current=NULL时,内存泄漏
- {
- previous->next = new;
- new->next = current;
- }
- else
- {
- previous->next = new;
- }
- }
-
- void stu_insert(Stu* new)
- {
- Stu* previous;
- Stu* current;
- Stu* next;
-
- previous = NULL;
- current = &g_stuDaynamic;
-
- while(current != NULL && current->score <= new->score)
- {
- previous = current;
- current = current->next;
- }
-
- //这边处理起来有些吃力,感觉需要识别是因为到结尾了还是当前节点大于插入数据
- if(current == NULL)
- {
- previous->next = new;
- }
- else
- {
- previous->next = new;
- new->next = current;
- }
- }
-
- int stu_find(Stu* stu, char* name)
- {
- Stu *temp = stu;
- while(NULL == temp)
- {
- return -1;
- }
-
- while(temp)
- {
- if( strcmp(temp->name, name) == 0)
- {
- printf("find the record");
- printf("姓名:%s, 年龄:%d, 性别:%d, 成绩:%d\n", temp->name, temp->age, temp->gender, temp->score);
-
- return 1;
- }
- temp = temp->next;
- }
-
- printf("find the record Empty!");
- }
-
- int stu_modify(const Stu* stu, Stu* stu_modify)
- {
- if(NULL == stu)
- {
- return -1;
- }
-
- Stu* temp = stu;
- while(temp)
- {
- if(strcmp(temp->name, stu_modify->name) == 0)
- {
- (*temp).age = stu_modify->age;
- (*temp).gender = stu_modify->gender;
- (*temp).score = stu_modify->score;
-
- return 1;
- }
- temp = temp->next;
- }
- }
-
- //删除
- int stu_delete(Stu* stu, char* name)
- {
- if (NULL == stu)
- {
- return -1;
- }
-
- Stu* temp = stu;
- while (temp)
- {
- if(NULL != temp->next && strcmp(temp->next->name, name) == 0)
- {
- //目标节点在重点
- Stu* traget = temp->next;
- Stu* tragetNext = traget->next;
- temp->next = tragetNext;
- free(traget);
-
- printf("已找到记录并删除\n");
- return 1;
- }
- temp = temp->next;
- }
-
- printf("未找到可删除记录\n");
- return 0;
- }
-
- void printStu(Stu* stu)
- {
- Stu* temp = stu->next;
- printf("打印学生信息\n");
- while(temp)
- {
- printf("姓名:%s, 年龄:%d, 性别:%d, 成绩:%d\n", temp->name, temp->age, temp->gender, temp->score);
- temp = temp->next;
- }
- }
-
- int action_add()
- {
- char name[10] = {'\0'};
- int age;
- int score;
- Gend gender;
-
- printf("输入姓名, 年龄, 性别, 分数\n");
- scanf("%s %d %d %d", name, &age, &gender, &score);
- Stu* stu_new = (Stu*)malloc(sizeof(Stu));
- if(NULL == stu_new)
- {
- printf("malloc fail");
- return -1;
- }
-
- memcpy(stu_new->name, name, 10);
- stu_new->age = age;
- stu_new->score = score;
- stu_new->gender = gender;
- stu_new->next = NULL;
-
- stu_add(stu_new);
-
- printStu(&g_stuDaynamic);
- }
-
- //插入数据进行有序排列
- int action_insert()
- {
- char name[10] = {'\0'};
- int age;
- int score;
- Gend gender;
-
- printf("输入姓名、年龄、性别、分数\n");
- scanf("%s %d %d %d", name, &age, &gender, &score);
- Stu* stu_new = (Stu*)malloc(sizeof(Stu));
- if(NULL == stu_new)
- {
- printf("malloc fail");
- return -1;
- }
-
- memcpy(stu_new->name, name, 10);
- stu_new->age = age;
- stu_new->score = score;
- stu_new->gender = gender;
- stu_new->next = NULL;
-
- stu_insert(stu_new);
-
- printStu(&g_stuDaynamic);
- }
-
- int action_find(char* name)
- {
- stu_find(&g_stuDaynamic, name);
- return 0;
- }
-
- int action_modify()
- {
- char name[10] = {'\0'};
- int age;
- int score;
- Gend gender;
-
- Stu *stu_modify_new = (Stu*)malloc(sizeof(Stu));
- if(NULL == stu_modify_new)
- {
- printf("malloc fail");
- return -1;
- }
-
- printf("输入修改的姓名, 年龄, 性别, 分数\n");
- scanf("%s %d %d %d", name, &age, &gender, &score);
-
- memcpy(stu_modify_new->name, name, 10);
- stu_modify_new->age = age;
- stu_modify_new->score = score;
- stu_modify_new->gender = gender;
-
- stu_modify(&g_stuDaynamic, stu_modify_new);
-
- free(stu_modify_new);
-
- printStu(&g_stuDaynamic);
-
- return 1;
- }
-
- int action_delete()
- {
- printf("输入需要删除的记录:\n");
- char* name[100];
- scanf("%s", name);
- stu_delete(&g_stuDaynamic, name);
- printStu(&g_stuDaynamic);
- return 0;
- }
-
- bool isTargetAlpha(char c)
- {
- if(toupper(c) == 'A' || toupper(c) == 'D' || toupper(c) == 'C' || toupper(c) == 'F' || toupper(c) == 'Q' || toupper(c) == 'I')
- {
- return true;
- }
-
- return false;
- }
-
- int list_func()
- {
- bool m_flag = true;
- if(NULL == g_stuDaynamic.next)
- {
- printf("g_stuDaynamic->next:%p\n", g_stuDaynamic.next);
- printf("g_stuDaynamic->next is NULL\n");
- }
-
- while(m_flag)
- {
- printf("选择操作(A:增加、D:删除、C:更改、F:查找、Q:退出):\n");
- char action[2];
- scanf("%s", action);
- if(!isTargetAlpha(action[0]))
- {
- continue;
- }
- switch(toupper(action[0]))
- {
- case 'A':
- {
- action_add();
- break;
- }
-
- case 'F':
- {
- printf("输入查询的姓名:\n");
- char name[100];
- scanf("%s", name);
- action_find(name);
- break;
- }
-
- case 'C':
- {
- action_modify();
- break;
- }
-
- case 'D':
- {
- action_delete();
- break;
- }
-
- case 'Q':
- {
- m_flag = false;
- printf("退出\n");
- break;
- }
-
- //插入数据有序排列
- case 'I':
- {
- action_insert();
- break;
- }
-
- default:
- {
- printf("操作有误,请重新输入\n");
- break;
- }
- }
-
-
- }
-
- return 0;
- }
-
-
- //g_stuDaynamic->next:00000000
- //g_stuDaynamic->next is NULL
- //选择操作(A:增加、D:删除、C:更改、F:查找、Q:退出):
- //A
- //输入姓名, 年龄, 性别, 分数
- //zhangs 7 0 77
- //打印学生信息
- //姓名:zhangs, 年龄:7, 性别:0, 成绩:77
- //选择操作(A:增加、D:删除、C:更改、F:查找、Q:退出):
- //A
- //输入姓名, 年龄, 性别, 分数
- //lilu 8 1 88
- //打印学生信息
- //姓名:zhangs, 年龄:7, 性别:0, 成绩:77
- //姓名:lilu, 年龄:8, 性别:1, 成绩:88
- //选择操作(A:增加、D:删除、C:更改、F:查找、Q:退出):
- //A
- //输入姓名, 年龄, 性别, 分数
- //wangmei 9 0 99
- //打印学生信息
- //姓名:zhangs, 年龄:7, 性别:0, 成绩:77
- //姓名:lilu, 年龄:8, 性别:1, 成绩:88
- //姓名:wangmei, 年龄:9, 性别:0, 成绩:99
- //选择操作(A:增加、D:删除、C:更改、F:查找、Q:退出):
- //I
- //输入姓名、年龄、性别、分数
- //lili 5 1 101
- //打印学生信息
- //姓名:zhangs, 年龄:7, 性别:0, 成绩:77
- //姓名:lilu, 年龄:8, 性别:1, 成绩:88
- //姓名:wangmei, 年龄:9, 性别:0, 成绩:99
- //姓名:lili, 年龄:5, 性别:1, 成绩:101
- //选择操作(A:增加、D:删除、C:更改、F:查找、Q:退出):
-
几经波折啊!
现在可以实现数据的增加、插入、删除、查找、修改了。但是离C和指针还有一些 差别或者差距。
差距在于我这个目前使用的是一个全局链表变量。所以所有的程序只能针对于这个链表运行。因为函数中写死了链表变量。
所以这是我又想到一个点。就是怎么叫解耦或者什么叫解耦。那就是函数中不能出现全局变量或者写死某个值或变量。
我的这段代码就是没有解耦,比如stu_insert函数中就出现这样的代码
- previous = &g_stuDaynamic;
- current = g_stuDaynamic.next;
高度耦合。
所以后面的代码修改方向就是需要解耦。
2024年1月16日 11:16:16
下面是解耦的代码,
搞的头炸啊!
//lianbiao.c文件
- #include "lianbiao.h"
-
- void func()
- {
- printf("hello\n");
- }
-
- bool isTargetCharacter(char* choose)
- {
- if(choose[0] == 'A' || choose[0] == 'I' || choose[0] == 'D' || choose[0] == 'M' || choose[0] == 'F')
- {
- return true;
- }
-
- return false;
- }
-
- //这边printf也是有问题的,我也是把跟指针当做value=0在用,从第二个节点开始打印。同理,我的add函数也是等于是从value=0结构后面加的
- void print_lianbiao(lianbiao* stu)
- {
- lianbiao* root = stu;
- lianbiao* current = root->next;
- while(current != NULL)
- {
- printf("姓名:%s,年龄:%d,性别:%d,成绩:%d\n", current->name, current->age, current->gender, current->score);
- current = current->next;
- }
- }
-
- int stu_add1(lianbiao* stu, lianbiao* new_stu)
- {
- while(stu == NULL)
- {
- return 0;
- }
-
- lianbiao* previous = stu;
- lianbiao** current = &previous->next;
-
- while(*current != NULL)
- {
- *current = (*current)->next;
- }
-
- *current = new_stu;
- return 1;
- }
-
- int stu_add2(lianbiao* stu, lianbiao* new_stu)
- {
- while(stu == NULL)
- {
- return 0;
- }
-
- lianbiao* previous = stu;
- lianbiao* current = previous->next;
-
- while(current != NULL)
- {
- current = current->next;
- }
-
- lianbiao** p = ¤t;
- *p = new_stu;
- return 1;
- }
-
- //吊毛,槽,这样写竟然就可以了,妈的,自己捣鼓一晚上都没弄好。看了书就好了
- int stu_add(lianbiao* stu, lianbiao* new_stu)
- {
- while(stu == NULL)
- {
- return 0;
- }
-
- lianbiao* previous = stu; //stu是二级指针,解引用一次,里面的成员都可以被成功赋值
- lianbiao* current = previous->next; //现在复盘,大概是previous->next可以被赋值。但是现在的操作是previous->next赋值给previous,再去更改previous的值就更改不了next的值
-
- while(current != NULL)
- {
- previous = current;
- current = current->next;
- }
-
- previous->next = new_stu;
-
- return 1;
- }
-
- int action_add(lianbiao* stu_lianbiao)
- {
- char name[10];
- int age;
- int gender;
- int score;
- //lianbiao stu; //这边好像不能写局部变量,栈上申请内存,感觉每次的地址是一样的额
-
- printf("输入需要增加(add)的数据, age=0时退出add操作:\n");
- while(1)
- {
- printf("输入姓名、年龄、性别、成绩\n");
- scanf("%s %d %d %d", name, &age, &gender, &score);
- if(age == 0)
- {
- break;
- }
- lianbiao* stu = (lianbiao*)malloc(sizeof(lianbiao));
- strcpy(stu->name, name);
- stu->age = age;
- stu->gender = gender;
- stu->score = score;
- stu->next = NULL; //忘了写
- if(stu_add(stu_lianbiao, stu))
- {
- printf("添加成功\n");
- }
- }
- print_lianbiao(stu_lianbiao);
- printf("结束添加add操作\n");
- }
-
- //这个没有传入根指针的二级指针,竟然也成功了
- //我是把根指针当做一个value=0的节点在用了,所以都是在后面add
- int stu_insert(lianbiao* stu, lianbiao* new_stu)
- {
- if(stu == NULL)
- {
- return 0;
- }
-
- lianbiao* previous = NULL;
- lianbiao* current = stu;
-
- while(current != NULL && current->score < new_stu->score) //这个地方关于current->score < new_stu->score我是存在疑问的。但是实际调试的时候score的值是0.只能理解为全局变量会被初始化为0
- {
- previous = current;
- current = current->next;
- }
-
- if(current == NULL) //这边我还是没有真正的理解书中表达的意思。这边应该写成previous == NULL
- {
- previous->next = new_stu;
- }
- else
- {
- previous->next = new_stu;
- new_stu->next = current;
- }
-
- return 1;
- }
-
- void action_insert(lianbiao* stu_lianbiao)
- {
- char name[10];
- int age;
- int gender;
- int score;
-
- printf("输入需要插入(insert)的数据, age=0时退出insert操作:\n");
- while(1)
- {
- printf("输入姓名、年龄、性别、成绩\n");
- scanf("%s %d %d %d", name, &age, &gender, &score);
- if(age == 0)
- {
- break;
- }
- lianbiao* stu = (lianbiao*)malloc(sizeof(lianbiao));
- strcpy(stu->name, name);
- stu->age = age;
- stu->gender = gender;
- stu->score = score;
- stu->next = NULL; //忘了写
- if(stu_insert(stu_lianbiao, stu))
- {
- printf("添加成功\n");
- print_lianbiao(stu_lianbiao);
- }
- }
-
- printf("结束添加add操作\n");
- }
-
- void stu_list_func(lianbiao* stu_lianbiao)
- {
- bool flag = true;
- char choose[10];
- printf("欢迎进入学生信息管理系统\n");
- while(flag)
- {
- printf("选择操作A:增加、I:插入、D:删除、M:修改、F:查找\n");
- scanf("%s", choose);
- if(!isTargetCharacter(choose))
- {
- continue;
- }
-
- switch(choose[0])
- {
- case 'A':
- {
- action_add(stu_lianbiao);
-
- break;
- }
-
- case 'I':
- {
- action_insert(stu_lianbiao);
- break;
- }
-
- case 'D':
- {
- break;
- }
-
- case 'M':
- {
- break;
- }
-
- case 'F':
- {
- break;
- }
-
- case 'Q':
- {
- flag = false;
- break;
- }
-
- default:
- {
- break;
- }
- }
- }
- }
-
- //D:\APP\codeBlock\ADTlianbiao\main.c
- //12, 7
- //Hello world!
- //欢迎进入学生信息管理系统
- //选择操作A:增加、I:插入、D:删除、M:修改、F:查找
- //A
- //输入需要增加(add)的数据, age=0时退出add操作:
- //输入姓名、年龄、性别、成绩
- //zhangs 7 0 77
- //添加成功
- //输入姓名、年龄、性别、成绩
- //lilu 8 1 88
- //添加成功
- //输入姓名、年龄、性别、成绩
- //wangmei 9 0 99
- //添加成功
- //输入姓名、年龄、性别、成绩
- //bv 0 0 0
- //姓名:zhangs,年龄:7,性别:0,成绩:77
- //姓名:lilu,年龄:8,性别:1,成绩:88
- //姓名:wangmei,年龄:9,性别:0,成绩:99
- //结束添加add操作
- //选择操作A:增加、I:插入、D:删除、M:修改、F:查找
- //I
- //输入需要插入(insert)的数据, age=0时退出insert操作:
- //输入姓名、年龄、性别、成绩
- //xiaoming 6 0 66
- //添加成功
- //姓名:xiaoming,年龄:6,性别:0,成绩:66
- //姓名:zhangs,年龄:7,性别:0,成绩:77
- //姓名:lilu,年龄:8,性别:1,成绩:88
- //姓名:wangmei,年龄:9,性别:0,成绩:99
- //输入姓名、年龄、性别、成绩
- //xiaohong 9 1 101
- //添加成功
- //姓名:xiaoming,年龄:6,性别:0,成绩:66
- //姓名:zhangs,年龄:7,性别:0,成绩:77
- //姓名:lilu,年龄:8,性别:1,成绩:88
- //姓名:wangmei,年龄:9,性别:0,成绩:99
- //姓名:xiaohong,年龄:9,性别:1,成绩:101
- //输入姓名、年龄、性别、成绩
- //xc 0 0 0
- //结束添加add操作
-
//lianbiao.h
- #ifndef LIANBIAO_H
- #define LIANBIAO_H
-
- #include "stdio.h"
- #include
- #include
-
- typedef struct Lianbiao
- {
- char name[10];
- int age;
- int gender;
- int score;
- struct Lianbiao* next;
- }lianbiao;
-
- typedef struct TEST
- {
- int a;
- int* p;
- }Test;
-
- void func();
-
- void stu_list_func(lianbiao* stu_lianbiao);
-
- #endif // LIANBIAO_H
//main.c
- #include
- #include
-
- #include "lianbiao.h"
-
- lianbiao g_stu_lianbiao;
-
- int testFun(Test* test)
- {
- test->a = 12;
- int* b = (int*)malloc(sizeof(int));
- *b = 7;
- int* p = test->p;
- p = b; //这样写不能正常赋值
-
- int **q = &(test->p); //不需要加括号,->运算符优先级高于&和*
- *q = b; //这样写可以正常赋值
- }
-
- int main()
- {
- printf("%s\n", __FILE__);
-
- Test test;
- testFun(&test);
- printf("%d, %d", test.a, *test.p);
-
- printf("Hello world!\n");
- int *p = &g_stu_lianbiao;
- stu_list_func(&g_stu_lianbiao);
- return 0;
- }
看打印记录感觉代码正常运行了。实际上上面的代码还是有问题,那就是我一直都其实没有理解根节点指针(rootp)是什么意思。在上面的diamante中,我其实一直都是这么用的。那就是将根节点指针指向的value=0的节点当做跟指针在用。(实际上g_stu_lianbiao的初始化就是0)。
这也是我为什么打印的时候会跳过一个节点,写的奇奇怪怪。
- lianbiao* root = stu;
- lianbiao* current = root->next;
上面显示我把root->next当做current。root->score所在的节点被我跳过了。
3.2.2.4 解耦阶段二
//lianbiao.h
- #ifndef LIANBIAO_H
- #define LIANBIAO_H
-
- #include "stdio.h"
- #include
- #include
-
- typedef struct Lianbiao
- {
- char name[10];
- int age;
- int gender;
- int score;
- struct Lianbiao* next;
- }lianbiao;
-
- typedef struct TEST
- {
- int a;
- int* p;
- }Test;
-
- void func();
-
- void stu_list_func(lianbiao** stu_lianbiao);
-
- #endif // LIANBIAO_H
//lianbiao.c
- #include "lianbiao.h"
-
- void func()
- {
- printf("hello\n");
- }
-
- bool isTargetCharacter(char* choose)
- {
- if(choose[0] == 'A' || choose[0] == 'I' || choose[0] == 'D' || choose[0] == 'M' || choose[0] == 'F')
- {
- return true;
- }
-
- return false;
- }
-
- //这边printf也是有问题的,我也是把跟指针当做value=0在用,从第二个节点开始打印。同理,我的add函数也是等于是从value=0结构后面加的
- void print_lianbiao1(lianbiao* stu)
- {
- lianbiao* root = stu;
- lianbiao* current = root->next;
- while(current != NULL)
- {
- printf("姓名:%s,年龄:%d,性别:%d,成绩:%d\n", current->name, current->age, current->gender, current->score);
- current = current->next;
- }
- }
-
- void print_lianbiao(lianbiao** stu)
- {
- lianbiao* current = *stu;
- while(current != NULL)
- {
- printf("姓名:%s,年龄:%d,性别:%d,成绩:%d\n", current->name, current->age, current->gender, current->score);
- current = current->next;
- }
- }
-
- int stu_add1(lianbiao* stu, lianbiao* new_stu)
- {
- while(stu == NULL)
- {
- return 0;
- }
-
- lianbiao* previous = stu;
- lianbiao** current = &previous->next;
-
- while(*current != NULL)
- {
- *current = (*current)->next;
- }
-
- *current = new_stu;
- return 1;
- }
-
- int stu_add2(lianbiao* stu, lianbiao* new_stu)
- {
- while(stu == NULL)
- {
- return 0;
- }
-
- lianbiao* previous = stu;
- lianbiao* current = previous->next;
-
- while(current != NULL)
- {
- current = current->next;
- }
-
- lianbiao** p = ¤t;
- *p = new_stu;
- return 1;
- }
-
- //吊毛,槽,这样写竟然就可以了,妈的,自己捣鼓一晚上都没弄好。看了书就好了
- int stu_add3(lianbiao* stu, lianbiao* new_stu)
- {
- while(stu == NULL)
- {
- return 0;
- }
-
- lianbiao* previous = stu; //stu是二级指针,解引用一次,里面的成员都可以被成功赋值
- lianbiao* current = previous->next; //现在复盘,大概是previous->next可以被赋值。但是现在的操作是previous->next赋值给previous,再去更改previous的值就更改不了next的值
-
- while(current != NULL)
- {
- previous = current;
- current = current->next;
- }
-
- previous->next = new_stu;
-
- return 1;
- }
-
- int stu_add(lianbiao** stu, lianbiao* new_stu)
- {
- while(stu == NULL)
- {
- return 0;
- }
-
- lianbiao* previous = NULL; //stu是二级指针,解引用一次,里面的成员都可以被成功赋值
- lianbiao* current = *stu; //现在复盘,大概是previous->next可以被赋值。但是现在的操作是previous->next赋值给previous,再去更改previous的值就更改不了next的值
-
- while(current != NULL)
- {
- previous = current;
- current = current->next;
- }
-
- if(previous == NULL)
- {
- *stu = new_stu;
- }
- else
- {
- previous->next = new_stu;
- new_stu->next = current;
- }
-
- return 1;
- }
-
- int action_add(lianbiao** stu_lianbiao)
- {
- char name[10];
- int age;
- int gender;
- int score;
- //lianbiao stu; //这边好像不能写局部变量,栈上申请内存,感觉每次的地址是一样的额
-
- printf("输入需要增加(add)的数据, age=0时退出add操作:\n");
- while(1)
- {
- printf("输入姓名、年龄、性别、成绩\n");
- scanf("%s %d %d %d", name, &age, &gender, &score);
- if(age == 0)
- {
- break;
- }
- lianbiao* stu = (lianbiao*)malloc(sizeof(lianbiao));
- strcpy(stu->name, name);
- stu->age = age;
- stu->gender = gender;
- stu->score = score;
- stu->next = NULL; //忘了写
- if(stu_add(stu_lianbiao, stu))
- {
- printf("添加成功\n");
- print_lianbiao(stu_lianbiao);
- }
- }
-
- printf("结束添加add操作\n");
- }
-
- //这个没有传入根指针的二级指针,竟然也成功了
- //我是把根指针当做一个value=0的节点在用了,所以都是在后面add
- int stu_insert1(lianbiao* stu, lianbiao* new_stu)
- {
- if(stu == NULL)
- {
- return 0;
- }
-
- lianbiao* previous = NULL;
- lianbiao* current = stu;
-
- while(current != NULL && current->score < new_stu->score) //这个地方关于current->score < new_stu->score我是存在疑问的。但是实际调试的时候score的值是0.只能理解为全局变量会被初始化为0
- {
- previous = current;
- current = current->next;
- }
-
- if(current == NULL) //这边我还是没有真正的理解书中表达的意思。这边应该写成previous == NULL
- {
- previous->next = new_stu;
- }
- else
- {
- previous->next = new_stu;
- new_stu->next = current;
- }
-
- return 1;
- }
-
- int stu_insert(lianbiao** stu, lianbiao* new_stu)
- {
- if(stu == NULL)
- {
- return 0;
- }
-
- lianbiao* previous = NULL;
- lianbiao* current = *stu;
-
- while(current != NULL && current->score < new_stu->score) //这个地方关于current->score < new_stu->score我是存在疑问的。但是实际调试的时候score的值是0.只能理解为全局变量会被初始化为0
- {
- previous = current;
- current = current->next;
- }
-
- if(previous == NULL) //这边我还是没有真正的理解书中表达的意思。这边应该写成previous == NULL
- {
- *stu = new_stu;
- }
- else
- {
- previous->next = new_stu;
-
- }
- new_stu->next = current; //靠这个一直没在意,调试的时候才发现
-
- return 1;
- }
-
- void action_insert(lianbiao* stu_lianbiao)
- {
- char name[10];
- int age;
- int gender;
- int score;
-
- printf("输入需要插入(insert)的数据, age=0时退出insert操作:\n");
- while(1)
- {
- printf("输入姓名、年龄、性别、成绩\n");
- scanf("%s %d %d %d", name, &age, &gender, &score);
- if(age == 0)
- {
- break;
- }
- lianbiao* stu = (lianbiao*)malloc(sizeof(lianbiao));
- strcpy(stu->name, name);
- stu->age = age;
- stu->gender = gender;
- stu->score = score;
- stu->next = NULL; //忘了写
- if(stu_insert(stu_lianbiao, stu))
- {
- printf("添加成功\n");
- print_lianbiao(stu_lianbiao);
- }
- }
-
- printf("结束添加add操作\n");
- }
-
- void stu_list_func(lianbiao** stu_lianbiao)
- {
- bool flag = true;
- char choose[10];
- printf("欢迎进入学生信息管理系统\n");
- while(flag)
- {
- printf("选择操作A:增加、I:插入、D:删除、M:修改、F:查找\n");
- scanf("%s", choose);
- if(!isTargetCharacter(choose))
- {
- continue;
- }
-
- switch(choose[0])
- {
- case 'A':
- {
- action_add(stu_lianbiao);
-
- break;
- }
-
- case 'I':
- {
- action_insert(stu_lianbiao);
- break;
- }
-
- case 'D':
- {
- break;
- }
-
- case 'M':
- {
- break;
- }
-
- case 'F':
- {
- break;
- }
-
- case 'Q':
- {
- flag = false;
- break;
- }
-
- default:
- {
- break;
- }
- }
- }
- }
-
- //D:\APP\codeBlock\ADTlianbiao\main.c
- //12, 7
- //Hello world!
- //欢迎进入学生信息管理系统
- //选择操作A:增加、I:插入、D:删除、M:修改、F:查找
- //A
- //输入需要增加(add)的数据, age=0时退出add操作:
- //输入姓名、年龄、性别、成绩
- //zhangs 7 0 77
- //添加成功
- //姓名:zhangs,年龄:7,性别:0,成绩:77
- //输入姓名、年龄、性别、成绩
- //lilu 8 1 88
- //添加成功
- //姓名:zhangs,年龄:7,性别:0,成绩:77
- //姓名:lilu,年龄:8,性别:1,成绩:88
- //输入姓名、年龄、性别、成绩
- //wangmei 9 0 99
- //添加成功
- //姓名:zhangs,年龄:7,性别:0,成绩:77
- //姓名:lilu,年龄:8,性别:1,成绩:88
- //姓名:wangmei,年龄:9,性别:0,成绩:99
- //输入姓名、年龄、性别、成绩
- //vc 0 0 0
- //结束添加add操作
- //选择操作A:增加、I:插入、D:删除、M:修改、F:查找
- //I
- //输入需要插入(insert)的数据, age=0时退出insert操作:
- //输入姓名、年龄、性别、成绩
- //xiaoming 6 0 66
- //添加成功
- //姓名:xiaoming,年龄:6,性别:0,成绩:66
- //姓名:zhangs,年龄:7,性别:0,成绩:77
- //姓名:lilu,年龄:8,性别:1,成绩:88
- //姓名:wangmei,年龄:9,性别:0,成绩:99
- //输入姓名、年龄、性别、成绩
- //hanxue 9 1 102
- //添加成功
- //姓名:xiaoming,年龄:6,性别:0,成绩:66
- //姓名:zhangs,年龄:7,性别:0,成绩:77
- //姓名:lilu,年龄:8,性别:1,成绩:88
- //姓名:wangmei,年龄:9,性别:0,成绩:99
- //姓名:hanxue,年龄:9,性别:1,成绩:102
- //输入姓名、年龄、性别、成绩
- //wuhu 7 0 82
- //添加成功
- //姓名:xiaoming,年龄:6,性别:0,成绩:66
- //姓名:zhangs,年龄:7,性别:0,成绩:77
- //姓名:wuhu,年龄:7,性别:0,成绩:82
- //姓名:lilu,年龄:8,性别:1,成绩:88
- //姓名:wangmei,年龄:9,性别:0,成绩:99
- //姓名:hanxue,年龄:9,性别:1,成绩:102
- //输入姓名、年龄、性别、成绩
- //vc 0 0 0
- //结束添加add操作
- //选择操作A:增加、I:插入、D:删除、M:修改、F:查找
-
//main.c
- #include
- #include
-
- #include "lianbiao.h"
-
- lianbiao* g_stu_lianbiao = NULL;
-
- int testFun(Test* test)
- {
- test->a = 12;
- int* b = (int*)malloc(sizeof(int));
- *b = 7;
- int* p = test->p;
- p = b; //这样写不能正常赋值
-
- // int **q = &(test->p); //不需要加括号,->运算符优先级高于&和*
- // *q = b; //这样写可以正常赋值
-
- test->p = b; //离谱的是,这样也可以更改结构体中指针的值
- }
-
- //这里的问题是test是个指针,指向一块内存。test指针指向的内存中的数据可以更改。因为确实是对真实内存进行修改
- //链表中的问题是,更改根节点的值。指针的值是值传递,无法修改。所以要传递地址的地址
-
- int main()
- {
- printf("%s\n", __FILE__);
-
- Test test;
- testFun(&test);
- printf("%d, %d\n", test.a, *test.p);
-
- printf("Hello world!\n");
- int *p = &g_stu_lianbiao;
- stu_list_func(&g_stu_lianbiao);
- return 0;
- }
上面的代码就实现了C和指针里面的链表。
2024年1月17日09:36:36
今天还回顾了一下链表,理了一下,下面的是画的图

所以对malloc也理解了一些。就是malloc申请了一块内存空间。用一个指针p指向那块内存。
implicit declaration of function 'toupper' [-Wimplicit-function-declaration]
加上头文件"ctype.h"就不报错了。但是按理没有加头文件程序不能执行啊。但是没有头文件程序也是正常执行了。
翻译:函数'toupper'的隐式声明
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。