1.环境搭建
1.1 在mac平台使用vscode进行环境搭建
- 安装C/C++插件
- 安装gcc,mac可能自带有gcc,可使用gcc --version查看gcc版本
- 打开项目文件并另存为工作区
- 配置tasks.json和launch.json文件
1.2 解决Debugger executable ‘/usr/local/bin/gdb‘ is not signed.报错
原因是在Mac系统(10.9)里默认不允许GNU gdb访问其他进程,需要对gdb进行签名。
具体做法可参考 https://www.jianshu.com/p/303bc5f53a52 给gdb授权或者添加信任证书
1.3 mac Catalina环境中要使用vscode进行调试还需要安装code runner和codelldb插件,并在设置中添加:
"code-runner.runInTerminal": true
2.项目分析和bug查找
2.1 项目数据结构

2.2 运行项目,报错隐式调用库函数却没有include该文件,在menu.c头部添加#include<string.h>

2.3 运行menu程序,发现quit指令出错,返回“This is a wrong cmd”

//根据代码可知此时 p==NULL
tDataNode *p = FindCmd(head, cmd);
if( p == NULL)
{
printf("This is a wrong cmd!\n ");
continue;
}
//FindCmd函数中又调用的SearchLinkTableNode函数
tDataNode* FindCmd(tLinkTable * head, char * cmd)
{
return (tDataNode*)SearchLinkTableNode(head,SearchCondition);
}
//分析SearchLinkTableNode函数
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode))
{
if(pLinkTable == NULL || Conditon == NULL)
{
return NULL;
}
tLinkTableNode * pNode = pLinkTable->pHead;
while(pNode != pLinkTable->pTail)
{
if(Conditon(pNode) == SUCCESS)
{
return pNode;
}
pNode = pNode->pNext;
}
return NULL;
}
//while循环条件为:当pNode不指向队尾的时候才能进入循环,则处于链表队尾的最后一个指令不会被识别
//quit函数正好是初始化时最后一个放入指令链表的函数,所以输入quit时返回的是空
2.4 Debug调试代码
在while循环处和SearchConditin函数处加断点进行调试

并监视数据变化情况

可以看到输入的指令为“quit”,第一次循环的节点指令为“help”,点击继续(F8)

再继续则退出了while循环,证实了上文的分析。循环判定条件出错导致处于队尾的指令不被识别。
//更改循环条件则可以避免这种情况
while(pNode != NULL)

可以看到成功识别了quit指令
3.callback回调函数总结
当某一函数A想要调用一个中间函数时,这个中间函数允许函数A来定义部分函数行为,从代码的角度来说就是这个中间函数要求函数A(以函数指针的形式)先传入一个函数B,这个B就叫回调函数。中间函数需要这个函数B来构成完整的操作逻辑。
类比就像我找4S店说要买车,我先把我的要求(回调函数)给4S店(中间函数),4S店根据我的要求返还我一份符合条件的车型。
在此项目中
//在项目中就使用了回调函数
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode))
//使用时传入的是menu.c中的SearchCondition函数
(tDataNode*)SearchLinkTableNode(head,SearchCondition);
回调函数的优点:
- 可以灵活的改变中间函数的行为
- 降低耦合,易于更新需求
- 分离了使用者和中间函数,一定程度上可以保护数据隐私,你只能用我当前给你的回调函数
工程化编程实战callback接口学习笔记
原文:https://www.cnblogs.com/moseleven/p/12520243.html