一、实验目的
参考《代码中的软件工程》第六章可复用软件设计及lab5.2的源代码,完成实验并写一篇实验报告,总结Callback函数的工作机制以及通过参数进行解耦合的方法,深入理解接口设计中的抽象分层。
二、实验内容
回调函数是一种编程技巧,它可以让一个函数把另一个函数作为参数传递,并在适当的时机调用它。回调函数的作用是增加程序的灵活性和解耦性,让不同的模块可以相互协作。
linktable.c
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable,
int Condition(tLinkTableNode * pNode, void * args),
void * args)
{
if(pLinkTable == NULL || Condition == NULL)
{
return NULL;
}
tLinkTableNode * pNode = pLinkTable->pHead;
while(pNode != NULL)
{
if(Condition(pNode, args) == SUCCESS)
{
return pNode;
}
pNode = pNode->pNext;
}
return NULL;
}
该代码的功能是在一个链表中搜索满足某个条件的节点,并返回该节点的指针。如果链表为空或者条件函数为空,就返回空指针。如果找到了满足条件的节点,就返回该节点的指针。如果没有找到,就返回空指针。
代码中使用了以下变量和函数:
tLinkTable
是一个结构体类型,表示一个链表,它有一个成员变量pHead
,指向链表的头节点。tLinkTableNode
是一个结构体类型,表示一个链表节点,它有一个成员变量pNext
,指向下一个节点。Condition
是一个函数指针类型,表示一个条件函数,它接受两个参数:一个链表节点指针和一个任意类型的指针,并返回一个整数值。如果返回值为SUCCESS
,表示该节点满足条件;否则表示不满足。args
是一个任意类型的指针,表示条件函数的第二个参数。pLinkTable
是一个tLinkTable
类型的指针,表示要搜索的链表。pNode
是一个tLinkTableNode
类型的指针,表示当前遍历的节点。
代码的思路如下:
- 首先判断链表指针和条件函数指针是否为空,如果是,就返回空指针。
- 然后将当前节点指针初始化为链表的头节点。
- 然后进入一个循环,每次循环都对当前节点进行以下操作:
- 调用条件函数,传入当前节点指针和
args
指针,得到返回值。 - 如果返回值为
SUCCESS
,表示当前节点满足条件,就返回当前节点指针。 - 否则将当前节点指针更新为下一个节点的指针。
- 调用条件函数,传入当前节点指针和
- 如果循环结束还没有找到满足条件的节点,就返回空指针。
menu.c
int SearchCondition(tLinkTableNode * pLinkTableNode, void * args)
{
char * cmd = (char*) args;
tDataNode * pNode = (tDataNode *)pLinkTableNode;
if(strcmp(pNode->cmd, cmd) == 0)
{
return SUCCESS;
}
return FAILURE;
}
该代码的功能是定义一个条件函数,用于判断一个链表节点中的数据是否与给定的字符串相同,并返回一个整数值。如果相同,就返回 SUCCESS
;否则返回 FAILURE
。
代码中使用了以下变量和函数:
tLinkTableNode
是一个结构体类型,表示一个链表节点,它有一个成员变量pNext
,指向下一个节点。tDataNode
是一个结构体类型,继承自tLinkTableNode
,表示一个数据节点,它有一个成员变量cmd
,表示一个字符串。SearchCondition
是一个函数名,表示一个条件函数,它接受两个参数:一个链表节点指针和一个任意类型的指针,并返回一个整数值。如果返回值为SUCCESS
,表示该节点满足条件;否则表示不满足。pLinkTableNode
是一个tLinkTableNode
类型的指针,表示要判断的链表节点。args
是一个任意类型的指针,表示要比较的字符串。cmd
是一个char
类型的指针,表示要比较的字符串。pNode
是一个tDataNode
类型的指针,表示要判断的数据节点。strcmp
是一个标准库函数,用于比较两个字符串是否相等。如果相等,就返回 0;否则返回非零值。
代码的思路如下:
- 首先将
args
指针强制转换为char
类型的指针,并赋值给cmd
指针。 - 然后将
pLinkTableNode
指针强制转换为tDataNode
类型的指针,并赋值给pNode
指针。 - 然后调用
strcmp
函数,传入pNode->cmd
和cmd
两个字符串指针,得到返回值。 - 如果返回值为 0,表示两个字符串相等,就返回
SUCCESS
。 - 否则返回
FAILURE
。
上面两段代码中,第一段代码中的 Condition
就是一个回调函数,它被传递给 SearchLinkTableNode
函数,并在遍历链表的过程中被调用,用于判断节点是否满足条件。第二段代码中的 SearchCondition
就是一个具体的回调函数实现,它用于比较节点中的数据和给定的字符串是否相等。
回调函数有什么优缺点?
回调函数的优点是可以增加程序的灵活性和解耦性,让不同的模块可以相互协作;回调函数还可以处理异步操作和事件处理等情况。
回调函数的缺点是可能会导致回调地狱(Callback Hell),即嵌套过多的回调函数,导致代码难以阅读和维护。回调函数还不能用 try catch 捕获错误,不能直接 return。
为了解决回调地狱问题,可以使用 Promise、async/await 等技术来管理异步操作。Promise 是一种封装异步操作的对象,它可以用 then 和 catch 方法来链式处理异步结果和错误。async/await 是一种语法糖,它可以让异步操作看起来像同步操作一样,使用 await 关键字来等待 Promise 的结果,使用 try catch 来捕获错误。
三、实验总结
通过本次实验,我对回调函数有了更深入的理解和掌握,也提高了我的编程能力和思维方式。我认识到回调函数是一种非常有用和强大的编程技术,它可以让程序变得更加灵活和可靠。我还发现了回调函数的一些优缺点,以及如何使用更先进的技术来管理异步操作。
神秘数字:156