实验五:用callback增强链表模块来实现命令行菜单小程序V2.8

来源:互联网 发布:java书籍推荐 豆瓣 编辑:程序博客网 时间:2024/06/05 16:00

一、实验要求

  1. 给lab5-1.tar.gz找bug,quit命令无法运行的bug
  2. 利用callback函数参数使Linktable的查询接口更加通用
  3. 注意接口的信息隐藏

二、实验过程

  1. 本次实验中所用版本库地址为:https://github.com/WhiteWhiteW/se_2017.git
  2. 使用mkdir命令创建lab5目录,并在该目录下对lab5-1.tar.gz进行解压缩,使用到的命令是tar -zxvf lab5-1.tar.gz
  3. 使用Xcode进行编译调试debug
  4. 项目导入后,运行结果如下所示。可以看到输入命令为quit时,得到的返回结果是This is a wrong cmd!,并非预期中的结果。

    这里写图片描述

  5. 修改linktable.c中的while(pNode != pLinkTable -> pTail)改为while(pNode != NULL)

    原因:在linktable.c中的tLinkTableNode * SearchLinkTableNode下,由于quit是最后一个节点,当找到quit时循环条件不满足而退出,不会执行函数体中的代码,因此无法执行quit命令。所以将while(pNode != pLinkTable -> pTail)改为while(pNode != NULL)

  6. 利用callback函数参数使linktable的查询接口更加通用,注重接口的信息隐藏。

  7. 代码如下。

    linktable.h

/********************************************************************//*  FILE NAME             :  linktabe.h                             *//*  PRINCIPAL AUTHOR      :  Wyy                                    *//*  SUBSYSTEM NAME        :  LinkTable                              *//*  MODULE NAME           :  LinkTable                              *//*  LANGUAGE              :  C                                      *//*  TARGET ENVIRONMENT    :  ANY                                    *//*  DATE OF FIRST RELEASE :  2017/10/22                             *//*  DESCRIPTION           :  interface of Link Table                *//********************************************************************/#ifndef _LINK_TABLE_H_#define _LINK_TABLE_H_#include <pthread.h>#define SUCCESS 0#define FAILURE (-1)/* * LinkTable Node Type */typedef struct LinkTableNode{    struct LinkTableNode * pNext;}tLinkTableNode;/* * LinkTable Type */typedef struct LinkTable{    tLinkTableNode *pHead;    tLinkTableNode *pTail;    int         SumOfNode;    pthread_mutex_t mutex;}tLinkTable;/* * Create a LinkTable */tLinkTable * CreateLinkTable();/* * Delete a LinkTable */int DeleteLinkTable(tLinkTable *pLinkTable);/* * Add a LinkTableNode to LinkTable */int AddLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);/* * Delete a LinkTableNode from LinkTable */int DelLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);/* * Search a LinkTableNode from LinkTable * int Conditon(tLinkTableNode * pNode); */tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode));/* * get LinkTableHead */tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable);/* * get next LinkTableNode */tLinkTableNode * GetNextLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);#endif /* _LINK_TABLE_H_ */

linktable.c

/********************************************************************//*  FILE NAME             :  linktabe.c                             *//*  PRINCIPAL AUTHOR      :  Wyy                                    *//*  SUBSYSTEM NAME        :  LinkTable                              *//*  MODULE NAME           :  LinkTable                              *//*  LANGUAGE              :  C                                      *//*  TARGET ENVIRONMENT    :  ANY                                    *//*  DATE OF FIRST RELEASE :  2017/10/22                             *//*  DESCRIPTION           :  interface of Link Table                *//********************************************************************/#include<stdio.h>#include<stdlib.h>#include"linktable.h"/* * Create a LinkTable */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;}/* * Delete a LinkTable */int DeleteLinkTable(tLinkTable *pLinkTable){    if(pLinkTable == NULL)    {        return FAILURE;    }    while(pLinkTable->pHead != NULL)    {        tLinkTableNode * p = pLinkTable->pHead;        pthread_mutex_lock(&(pLinkTable->mutex));        pLinkTable->pHead = pLinkTable->pHead->pNext;        pLinkTable->SumOfNode -= 1 ;        pthread_mutex_unlock(&(pLinkTable->mutex));        free(p);    }    pLinkTable->pHead = NULL;    pLinkTable->pTail = NULL;    pLinkTable->SumOfNode = 0;    pthread_mutex_destroy(&(pLinkTable->mutex));    free(pLinkTable);    return SUCCESS;}/* * Add a LinkTableNode to LinkTable */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;}/* * Delete a LinkTableNode from LinkTable */int DelLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode){    if(pLinkTable == NULL || pNode == NULL)    {        return FAILURE;    }    pthread_mutex_lock(&(pLinkTable->mutex));    if(pLinkTable->pHead == pNode)    {        pLinkTable->pHead = pLinkTable->pHead->pNext;        pLinkTable->SumOfNode -= 1 ;        if(pLinkTable->SumOfNode == 0)        {            pLinkTable->pTail = NULL;        }        pthread_mutex_unlock(&(pLinkTable->mutex));        return SUCCESS;    }    tLinkTableNode * pTempNode = pLinkTable->pHead;    while(pTempNode != NULL)    {        if(pTempNode->pNext == pNode)        {            pTempNode->pNext = pTempNode->pNext->pNext;            pLinkTable->SumOfNode -= 1 ;            if(pLinkTable->SumOfNode == 0)            {                pLinkTable->pTail = NULL;            }            pthread_mutex_unlock(&(pLinkTable->mutex));            return SUCCESS;        }        pTempNode = pTempNode->pNext;    }    pthread_mutex_unlock(&(pLinkTable->mutex));    return FAILURE;}/* * Search a LinkTableNode from LinkTable * int Conditon(tLinkTableNode * pNode); */tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode)){    if(pLinkTable == NULL || Conditon == NULL)    {        return NULL;    }    tLinkTableNode * pNode = pLinkTable->pHead;    while(pNode != NULL)    {        if(Conditon(pNode) == SUCCESS)        {            return pNode;        }        pNode = pNode->pNext;    }    return NULL;}/* * get LinkTableHead */tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable){    if(pLinkTable == NULL)    {        return NULL;    }    return pLinkTable->pHead;}/* * get next LinkTableNode */tLinkTableNode * GetNextLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode){    if(pLinkTable == NULL || pNode == NULL)    {        return NULL;    }    tLinkTableNode * pTempNode = pLinkTable->pHead;    while(pTempNode != NULL)    {        if(pTempNode == pNode)        {            return pTempNode->pNext;        }        pTempNode = pTempNode->pNext;    }    return NULL;}

menu.c

/********************************************************************//*  FILE NAME             :  menu.c                                 *//*  PRINCIPAL AUTHOR      :  Wyy                                    *//*  SUBSYSTEM NAME        :  menu                                   *//*  MODULE NAME           :  menu                                   *//*  LANGUAGE              :  C                                      *//*  TARGET ENVIRONMENT    :  ANY                                    *//*  DATE OF FIRST RELEASE :  2017/10/22                             *//*  DESCRIPTION           :  This is a menu program                 *//********************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include "linktable.h"int Help();int Quit();#define CMD_MAX_LEN 128#define DESC_LEN    1024#define CMD_NUM     10char cmd[CMD_MAX_LEN];/* data struct and its operations */typedef struct DataNode{    tLinkTableNode * pNext;    char*   cmd;    char*   desc;    int     (*handler)();} tDataNode;int SearchCondition(tLinkTableNode * pLinkTableNode){    tDataNode * pNode = (tDataNode *)pLinkTableNode;    if(strcmp(pNode->cmd, cmd) == 0)    {        return  SUCCESS;      }    return FAILURE;        }/* find a cmd in the linklist and return the datanode pointer */tDataNode* FindCmd(tLinkTable * head, char * cmd){    return  (tDataNode*)SearchLinkTableNode(head,SearchCondition);}/* show all cmd in listlist */int ShowAllCmd(tLinkTable * head){    tDataNode * pNode = (tDataNode*)GetLinkTableHead(head);    while(pNode != NULL)    {        printf("%s - %s\n", pNode->cmd, pNode->desc);        pNode = (tDataNode*)GetNextLinkTableNode(head,(tLinkTableNode *)pNode);    }    return 0;}int InitMenuData(tLinkTable ** ppLinktable){    *ppLinktable = CreateLinkTable();    tDataNode* pNode = (tDataNode*)malloc(sizeof(tDataNode));    pNode->cmd = "help";    pNode->desc = "Menu List:";    pNode->handler = Help;    AddLinkTableNode(*ppLinktable,(tLinkTableNode *)pNode);    pNode = (tDataNode*)malloc(sizeof(tDataNode));    pNode->cmd = "version";    pNode->desc = "Menu Program V1.0";    pNode->handler = NULL;     AddLinkTableNode(*ppLinktable,(tLinkTableNode *)pNode);    pNode = (tDataNode*)malloc(sizeof(tDataNode));    pNode->cmd = "quit";    pNode->desc = "Quit from Menu Program V1.0";    pNode->handler = Quit;     AddLinkTableNode(*ppLinktable,(tLinkTableNode *)pNode);    return 0; }/* menu program */tLinkTable * head = NULL;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();        }    }}int Help(){    ShowAllCmd(head);    return 0; }int Quit(){    exit(0);}

三、实验结果

  1. 修改之后,得到运行结果如下所示。可看到,输入命令为quit时,会退出当前正在执行的程序,并得到预期的输出结果Quit from Menu Program V1.0.

    这里写图片描述

  2. 在命令行下使用gcc menu.c linktable.c -o menu命令进行编译,并且使用./menu命令运行结果。
    可得到结果如下。

    这里写图片描述

    • help命令可得到命令提示菜单列表
    • version命令可得到当前程序版本信息
    • quit命令退出当前程序
    • 其他输入默认为错误的输入信息

四、提交到github

这里写图片描述

五、心得体会

在上次的实验四中也遇到了类似的问题,上次出现的问题是段错误,经仔细查证,最后发现出现问题的地方在于链表节点的存储部分。

在本次实验中,熟悉了callback函数的使用,对模块化的编程思想有了进一步的学习。debug在实际代码调试中起到很重要的作业,自己还需继续努力。

阅读全文
0 0
原创粉丝点击