您的位置:首页 > 移动开发 > 微信开发

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

2017-10-22 11:51 489 查看

一、实验要求

给lab5-1.tar.gz找bug,quit命令无法运行的bug

利用callback函数参数使Linktable的查询接口更加通用

注意接口的信息隐藏

二、实验过程

本次实验中所用版本库地址为:https://github.com/WhiteWhiteW/se_2017.git

使用mkdir命令创建lab5目录,并在该目录下对lab5-1.tar.gz进行解压缩,使用到的命令是
tar -zxvf lab5-1.tar.gz


使用Xcode进行编译调试debug

项目导入后,运行结果如下所示。可以看到输入命令为quit时,得到的返回结果是
This is a wrong cmd!
,并非预期中的结果。



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


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


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

代码如下。

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     10

char 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);
}


三、实验结果

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



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

可得到结果如下。



help命令可得到命令提示菜单列表

version命令可得到当前程序版本信息

quit命令退出当前程序

其他输入默认为错误的输入信息

四、提交到github



五、心得体会

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

在本次实验中,熟悉了callback函数的使用,对模块化的编程思想有了进一步的学习。debug在实际代码调试中起到很重要的作业,自己还需继续努力。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐