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

实验四:用可重用的链表模块来实现命令行菜单小程序V2.5

2017-10-10 16:12 651 查看
【shawn520 + 《软件工程(C编码实践篇)》MOOC课程作业http://mooc.study.163.com/course/USTC-1000002006

【代码仓库】https://github.com/shawn520/SE.git

实验要求

用可重用的链表模块来实现命令行菜单小程序,执行某个命令时调用一个特定的函数作为执行动作;

链表模块的接口设计要足够通用,命令行菜单小程序的功能保持不变;

可以将通用的Linktable模块集成到我们的menu程序中;

接口规范;

实验过程

进入实验目录

git clone https://github.com/shawn520/SE.git mkdir lab4
cd lab4
vim menu.c


menu.c中添加如下代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "linktable.h"

#define     FILEPATH_MAX          80
#define     CMD_MAX_LENGTH         128

void help();
void quit();

typedef struct DataNode
{
tLinkTableNode *pNext;
char *cmd;
char *desc;
void (*handler)();
}tDataNode;

char cwdbuff[64] = {0};
char cwdbuffsub[64] = {0};
//declare a tLinkTable

tLinkTable *head = NULL;
//find the command
tDataNode *FindCmd(tLinkTable *head, char *cmd)
{
tDataNode *pNode = (tDataNode *)GetLinkTableHead(head);
while (pNode != NULL)
{
if (strcmp(pNode->cmd, cmd) == 0)
{
return pNode;
}
pNode = (tDataNode *)GetNextLinkTableNode(head, (tLinkTableNode *)pNode);
}
return NULL;
}
//show the desc
int ShowAllCmd(tLinkTable *head)
{
tDataNode *pNode = (tDataNode *)GetLinkTableHead(head);
while (pNode != NULL)
{
pr
4000
intf("%s - %s\n", pNode->cmd, pNode->desc);
pNode = (tDataNode *)GetNextLinkTableNode(head, (tLinkTableNode *)pNode);
}
return 0;
}
//init
int InitMenuData(tLinkTable **ppLinktable)
{
*ppLinktable = CreateLinkTable();

tDataNode *pNode = (tDataNode *)malloc(sizeof(tDataNode));
pNode->cmd = "help";
pNode->desc = "This is help command.";
pNode->handler = help;
AddLinkTableNode(*ppLinktable, (tLinkTableNode *)pNode);

pNode = (tDataNode *)malloc(sizeof(tDataNode));
pNode->cmd = "quit";
pNode->desc = "quit the command line.";
pNode->handler = quit;
AddLinkTableNode(*ppLinktable, (tLinkTableNode *)pNode);
return 0;
}

int main ()
{
char getCommand[CMD_MAX_LENGTH];
InitMenuData(&head);
while(1)
{
printf("Please Input Command: ");
scanf("%s",getCommand);
tDataNode *p = FindCmd(head,getCommand);
if(p == NULL)
{
printf("error: Wrong Command!!\n");
}
else
{
p -> handler();
}
}
return 0;
}

//show commmand imformation
void help()
{
ShowAllCmd(head);
}

//exit
void quit()
{
exit(0);
}


编辑linktable.h

#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 LinkTable
int DeleteLinkTable(tLinkTable *pLinkTable);

//Add CMD
int AddLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode *pNode);

//Delete CMD
int DelLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode *pNode);

//Get LinkTableHead
tLinkTableNode *GetLinkTableHead(tLinkTable *pLinkTable);

//Get nextLinkTableNode
tLinkTableNode *GetNextLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode *pNode);

#endif


编辑 linktable.c

#include <stdio.h>
#include <stdlib.h>
#include "linktable.h"

#define SUCCESS 0
#define FAILURE (-1)

tLinkTable *CreateLinkTable()
{
tLinkTable *pLinkTable = (tLinkTable *)malloc(sizeof(tLinkTable));
if (pLinkTable == NULL)
{
printf("malloc error!\n");
return NULL;
}
pLinkTable->pHead = NULL;
pLinkTable->pTail = NULL;
pLinkTable->SumOfNode = 0;
pthread_mutex_init(&(pLinkTable->mutex), NULL);
return pLinkTable;
}

int DeleteLinkTable(tLinkTable *pLinkTable)
{
if (pLinkTable == NULL)
{
return SUCCESS;
}
while (pLinkTable->pHead != NULL)
{
tLinkTableNode *pNode = pLinkTable->pHead;
pLinkTable->pHead = pNode->pNext;
free(pNode);
}
free(pLinkTable);
return SUCCESS;
}

int AddLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode *pNode)
{
if (pLinkTable == NULL || pNode == NULL)
{
printf("AddLinkTableNode error!\n");
return FAILURE;
}
pNode->pNext = NULL;
if (pLinkTable->pHead == NULL)
{
pLinkTable->pHead = pNode;
pLinkTable->pTail = pNode;
pLinkTable->SumOfNode += 1;
}
else
{
pLinkTable->pTail->pNext = pNode;
pLinkTable->pTail = pNode;
pLinkTable->SumOfNode += 1;
}
return SUCCESS;
}

int DelLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode *pNode)
{
if (pLinkTable == NULL || pNode == NULL)
{
printf("DelLinkTableNode error!\n");
return FAILURE;
}
tLinkTableNode *pFront = pLinkTable->pHead;
if (pFront == NULL)
{
printf("pLinkTable is NULL!\n");
return FAILURE;
}
else if (pFront == pNode)
{
pLinkTable->pHead = pFront->pNext;
free(pFront);
return SUCCESS;
}
tLinkTableNode *pBack = pFront;
pFront = pFront->pNext;
while (pFront != NULL)
{
if (pFront == pNode)
{
pBack->pNext = pFront->pNext;
free(pFront);
return SUCCESS;
}
pFront = pFront->pNext;
pBack = pBack->pNext;
}
printf("not find error!\n");
return FAILURE;
}

tLinkTableNode *GetLinkTableHead(tLinkTable *pLinkTable)
{
if (pLinkTable == NULL)
{
return NULL;
}
return pLinkTable->pHead;
}

tLinkTableNode *GetNextLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode *pNode)
{
if (pLinkTable == NULL || pNode == NULL)
{
return NULL;
}
tLinkTableNode *p = pLinkTable->pHead;
if (p == NULL)
{
return NULL;
}
while (p != NULL)
{
if (p == pNode)
{
return p->pNext;
}
p = p->pNext;
}
return NULL;
}


编译得到可执行文件

gcc linktable.c menu.c -o menu


并测试menu程序的功能,如图所示



完成后提交到git

git add  linktable.c linktable.h menu.c
git commit -m 'menu_v2.5'
git push




实验心得及体会:

实验越来越难了。

通用Linktable模块的接口设计

将通用的Linktable模块集成到我们的menu程序中

定义接口 - “天王盖地虎,宝塔镇河妖”黑社会接头也设计接口的!

接口规范

内聚和耦合

通用原则

通用链表模块的接口设计

模块化的好处:包容变化

将通用的LinkTable集成到我们的menu程序中

本地化外部接口(Localize input and output)

欢迎大家访问我的——

GitHub主页: https://github.com/shawn520/SE

CSDN博客: http://blog.csdn.net/liushawn520

新浪微博 @奔跑中的Shawn
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐