ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

工程化编程实战callback接口学习笔记

2020-03-18 12:57:07  阅读:286  来源: 互联网

标签:pTail 函数 callback 编程 链表 pNode pLinkTable 工程化 NULL


1.1、运行环境linux,编译工具gcc,实验代码lab5-1.tar.gz 即http://pan.baidu.com/s/1pJ0qAIv

1.2、使用gcc编译程序linktable.c和menu.c,即使用命令gcc -o test linktable.c menu.c,将linktable和menu.c编译成可执行文件,名为test。

注意需要在menu.c的头文件中加入#include<string.h>,否则报错缺失相关库。

1.3、输入./test运行之前编译的程序,然后在程序中输入help查看程序提供的命令参数,但是发现输入quit时,程序没有识别出该命令。

 

 

 

 

 

 

 

2问题发现和程序修改

 

 2.1、可以首先定位到menu.c的主函数main中,发现当tDataNode 类型的指针p为NULL时,报出This is a wrong cmd!信息,而指针p的值来源于函数FindCmd函数,观察FindCmd程序,可以继续定位到linktable.c文件中的SearchLinkTableNode函数。

 

int main()

{

    InitMenuData(&head);

   /* cmd line begins */

    while(1)

    {

        printf("Input a cmd number > ");

        scanf("%s", cmd);

        tDataNode *p = FindCmd(head, cmd);

        if( p == NULL)

        {

            printf("This is a wrong cmd!\n ");

            continue;

        }

        printf("%s - %s\n", p->cmd, p->desc);

        if(p->handler != NULL)

        {

            p->handler();

        }

   

    }

}

 

tDataNode* FindCmd(tLinkTable * head, char * cmd)

{

    return  (tDataNode*)SearchLinkTableNode(head,SearchCondition);

}

 

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;

}

 

该函数的两个参数分别表示由命令参数组成的链表头指针和当前命令是否找到,以下情况返回NULL:

 

pLinkTable == NULL

Conditon == NULL

该链表中所有节点的Condition都不为SUCCESS

调试程序,发现只有当pNode != pLinkTable->pTail条件为真时,不断的遍历链表上的节点信息,来对比用户输入的命令从而返回相应节点。所以继续定位到该循环,发现循环条件比较奇怪,我们继续调试这个条件,观察链表的结构和链表的添加节点操作。

 

 

tLinkTable * CreateLinkTable()

{

    tLinkTable * pLinkTable = (tLinkTable *)malloc(sizeof(tLinkTable));

    if(pLinkTable == NULL)

    {

        return NULL;

    }

    pLinkTable->pHead = NULL;

    pLinkTable->pTail = NULL;

    pLinkTable->SumOfNode = 0;

    pthread_mutex_init(&(pLinkTable->mutex), NULL);

    return pLinkTable;

}

 

int AddLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode)

{

    if(pLinkTable == NULL || pNode == NULL)

    {

        return FAILURE;

    }

    pNode->pNext = NULL;

    pthread_mutex_lock(&(pLinkTable->mutex));

    if(pLinkTable->pHead == NULL)

    {

        pLinkTable->pHead = pNode;

    }

    if(pLinkTable->pTail == NULL)

    {

        pLinkTable->pTail = pNode;

    }

    else

    {

        pLinkTable->pTail->pNext = pNode;

        pLinkTable->pTail = pNode;

    }

    pLinkTable->SumOfNode += 1 ;

    pthread_mutex_unlock(&(pLinkTable->mutex));

    return SUCCESS;        

}

 

分析上面的代码可以发现pLinkTable->pTail代表的是链表的最后一个节点的指针,这下在回到SearchLinkTableNode函数中的循环,发现当链表到达最后节点是就不再循环了,即并没有判断最后一个节点的Condition,中途停止返回空。

 

2.2、修改程序消除bug

 

知道了指针返回为空的原因是没有彻底遍历链表中的所以节点,漏了最后一个节点,所以我们修改循环条件

 

pNode != pLinkTable->pTail为pNode != pLinkTable->pTail-pNext或pNode != NULL

 

 修改后重新编译运行测试成功

 

 

 

 

3.分析callback接口的运行机制,总结callback接口设计的方法

在计算机程序设计中,回调函数,或简称回调(Callback 即call then back 被主函数调用运算后会返回主函数),是指通过函数参数传递到其它代码的,某一块可执行代码的引用。这一设计允许了底层代码调用在高层定义的子程序。(这是维基百科定义)

回调函数通常和原始调用者处于同意抽象层

回调函数实现的多态的机制,通过注册不同的函数到同一个类的不同对象中,可以事项多态的机制。

回调函数的实现方法

在类中声明函数指针,可以对函数进行绑定

类创建对象时,对对象中的函数指针进行绑定

通过对象,调用绑定的函数,实现回调机制。

标签:pTail,函数,callback,编程,链表,pNode,pLinkTable,工程化,NULL
来源: https://www.cnblogs.com/buzhidao1/p/12516713.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有