高软实验报告5(更改)
作者:互联网
网易云课堂昵称: 镍铬合金
学号:sa17225259
github: https://github.com/Niejinge/NSE
《软件工程(C编码实践篇)》MOOC课程作业http://mooc.study.163.com/course/USTC-1000002006 】
实验要求
- 给lab5-1.tar.gz找bug,quit命令无法运行的bug
- 利用callback函数参数使Linktable的查询接口更加通用
- 注意接口的信息隐藏
本次实验主要是从老师给的源代码里修改bug, 并优化代码,使用caLlback
来完成,最后实现接口的隐藏,总体还是比较简单的,因为不用自己去写代码,只需要好好理解老师的讲解,并修改好即可。
修改bug
首先下载老师的代码并运行,发现quit命令不能识别,如下图所示:
经过分析,发现在inktable.c
中SearchLinkTableNode
函数中有错误,while循环中最后一次循环到pLinkTable->ptail
就终止了,因此quit作为最后一条命令不能识别。修改为NULL,就可以了,修改后代码如下:
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode, void* args), void* args)
{
if(pLinkTable == NULL || Conditon == NULL)
{
return NULL;
}
tLinkTableNode * pNode = pLinkTable->pHead;
while(pNode != NULL)
{
if(Conditon(pNode, args) == SUCCESS)
{
return pNode;
}
pNode = pNode->pNext;
}
return NULL;
}
再运行程序,错误消失:
- 使用
callback
优化代码
对于 callback,就是被调用函数还要利用调用者提供信息,来完成函数的实现。现在我们就来对我们的代码完成优化,通过引入callback来对代码进行修改,以降低代码的耦合程度。
之前的代码中,在menu.c中,char cmd[CMD_MAX_LEN];
作为全局变量出现在main函数体外,这虽然实现了我们的目的,但是使用全局变量是不好的,这会无形之间增加代码之间的耦合程度。所以,我们要通过引入callback来降低耦合,使我们的代码更加完美。
为了实现我们的目的,通过在SearchCondition
中引入args参数,可以实现把cmd的声明放在main函数体内,具体代码如下:
int SearchCondition(tLinkTableNode * pLinkTableNode, void* args)
{
char * cmd = (char*) args;
tDataNode * pNode = (tDataNode *)pLinkTableNode;
if(strcmp(pNode->cmd, cmd) == 0)
{
return SUCCESS;
}
return FAILURE;
}
这里修改之后,相关地方都需要修改,总共需要修改的地方还有:
tDataNode* FindCmd(tLinkTable * head, char * cmd)
{
return (tDataNode*)SearchLinkTableNode(head,SearchCondition, cmd);
}
linktable.h和linktable.c中相关代码也需要修改:具体修改就不一一赘述了。
linktable.h:
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode, void* args), void* args);
linktable.c:
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode, void* args), void* args)
{
if(pLinkTable == NULL || Conditon == NULL)
{
return NULL;
}
tLinkTableNode * pNode = pLinkTable->pHead;
while(pNode != NULL)
{
if(Conditon(pNode, args) == SUCCESS)
{
return pNode;
}
pNode = pNode->pNext;
}
return NULL;
}
- 实现代码的隐藏
通过把头文件中数据结构的定义移到.c文件中,而在头文件仅实现结构的定义,就实现了代码的隐藏,只提供接口,提高了代码的健壮性。
通过上面的优化,我们的代码基本要求已经实现了,试运行也没有出错,很高兴,接下来添加自己的几个小函数,然后运行一下,本次实验就宣告完毕了!
因为本次实验是老师提供的源代码,这里就不全贴出来了,具体代码详情可见github。这里就贴出menu.c
的代码吧,因为这是改动最大的源文件。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 | #include <stdlib.h>#include "linktable.h"#include <string.h>int ();int Quit();int dogBark();int eat();int add();int sub();int happy();#define CMD_MAX_LEN 128#define DESC_LEN 1024#define CMD_NUM typedef struct DataNode{ tLinkTableNode * pNext; char* cmd; char* desc; int (*handler)();} tDataNode;int SearchCondition(tLinkTableNode * pLinkTableNode, void* args){ char * cmd = (char*) args; tDataNode * pNode = (tDat 大专栏 高软实验报告5(更改)aNode *)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, cmd);}/* show all cmd in listlist */int ShowAllCmd(tLinkTable * head){ tDataNode * pNode = (tDataNode*)GetLinkTableHead(head); while(pNode != NULL) { printf("%s - %sn", 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); pNode = (tDataNode*)malloc(sizeof(tDataNode)); pNode->cmd = "dogBark"; pNode->desc = "a dog bark at the midnight!"; pNode->handler = dogBark; AddLinkTableNode(*ppLinktable,(tLinkTableNode *)pNode); pNode = (tDataNode*)malloc(sizeof(tDataNode)); pNode->cmd = "eat"; pNode->desc = "it's supper time, let's eat some food"; pNode->handler = eat; AddLinkTableNode(*ppLinktable,(tLinkTableNode *)pNode); pNode = (tDataNode*)malloc(sizeof(tDataNode)); pNode->cmd = "add"; pNode->desc = "add two demo of numbers."; pNode->handler = add; AddLinkTableNode(*ppLinktable,(tLinkTableNode *)pNode); pNode = (tDataNode*)malloc(sizeof(tDataNode)); pNode->cmd = "sub"; pNode->desc = "sub two demo of two numbers."; pNode->handler = sub; AddLinkTableNode(*ppLinktable,(tLinkTableNode *)pNode); pNode = (tDataNode*)malloc(sizeof(tDataNode)); pNode->cmd = "happy"; pNode->desc = "keep smile in life everyday!"; pNode->handler = happy; AddLinkTableNode(*ppLinktable,(tLinkTableNode *)pNode); return 0; }/* menu program */tLinkTable * head = NULL;int main(){ char cmd[CMD_MAX_LEN]; 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 - %sn", p->cmd, p->desc); if(p->handler != NULL) { p->handler(); } }}int (){ ShowAllCmd(head); return 0; }int Quit(){ exit(0);}int dogBark(){ printf("Ruff! Ruff! Ruff ... !n"); return 0;}int eat(){ printf("uh..! The meat is declicious!n"); return 0;}int add(){ int x, y; printf("input two numbers:n"); scanf("%d %d", &x, &y); printf("x+y = %dn", x+y); return 0;}int sub(){ int x, y; printf("input two numbers:n"); scanf("%d %d", &x, &y); printf("x-y = %dn", x-y); return 0;}int happy(){ printf("hahaheheheiheixixihouhouxiaxia!n"); return 0;} |
- 实验结果
通过gcc linktable.c menu.c -o menu
生成可执行文件,然后通过命令./menu
运行文件,结果如下:
- 提交代码到github
- 实验总结
通过本次实验,深入理解了callback的机制,软件工程不只是能写出能执行的代码,更关键的是代码调优,通过callback和实现接口信息的隐藏,可以使我们的代码更加通用,更加健壮。这是思想是需要慢慢培养的,要在平时练习中注意使用,提高调优能力。
标签:return,高软,更改,int,tDataNode,cmd,pNode,tLinkTableNode,实验报告 来源: https://www.cnblogs.com/liuzhongrong/p/12249004.html