实验四:用可重用的链表模块来实现命令行菜单小程序V2.5
实验要求:
- 用可重用的链表模块来实现命令行菜单小程序,执行某个命令时调用一个特定的函数作为执行动作;
- 链表模块的接口设计要足够通用,命令行菜单小程序的功能保持不变;
- 可以将通用的Linktable模块集成到我们的menu程序中;
- 接口规范;
实验步骤
- 编写代码
- 编译多个文件
- 提交git
版本库URL:https://git.coding.net/fuguanqi/ASE.git
心得体会:
此次实验的特点是利用通用的链表结点结构体(tLinkTableNode),构建相应的应用链表节点(tLinkNode), tLinkTableNode 是 tLinkNode 中的一个成员,需要注意的一点是,想要实现链表重用,必须在定义 tLinkNode 时把 tLinkTableNode 放在第一个成员的位置,否则会发生指针错误。
源代码:
menu.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "linktable.h"
#define CMD_MAX_LEN 128
#define DESC_LEN 1024
#define CMD_NUM 10
typedef struct DataNode
{
tLinkTableNode *pNext;
char* cmd;
char* desc;
int(*handler)();
} tDataNode;
int Help();
int Quit();
tDataNode * FindCmd(tLinkTable *linkTable, char * cmd)
{
if (linkTable == NULL)
{
return NULL;
}
tDataNode * pNode = (tDataNode *)GetLinkTableHead(linkTable);
//printf("*** %s ***", pNode->desc);
while (pNode != NULL)
{
if (strcmp(pNode->cmd, cmd) == 0)
{
return pNode;
}
pNode = (tDataNode *)GetNextLinkTableNode(linkTable, (tLinkTableNode *)pNode);
}
return NULL;
}
int ShowAllCmd(tLinkTable* linktable)
{
tDataNode *pNode = (tDataNode*)GetLinkTableHead(linktable);
while (pNode != NULL)
{
printf("%s-%s\n", pNode->cmd, pNode->desc);
pNode = (tDataNode*)GetNextLinkTableNode(linktable, (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.3";
pNode->handler = NULL;
AddLinkTableNode(*ppLinkTable, (tLinkTableNode *)pNode);
pNode = (tDataNode *)malloc(sizeof(tDataNode));
pNode->cmd = "quit";
pNode->desc = "Quit from Menu Program V1.3";
pNode->handler = Quit;
AddLinkTableNode(*ppLinkTable, (tLinkTableNode *)pNode);
return 0;
}
tLinkTable *linktable = NULL;
int main()
{
InitMenuData(&linktable);
//tDataNode * q = (tDataNode *)GetLinkTableHead(linktable);
//printf("%s", q->desc);
while (1)
{
char cmd[CMD_MAX_LEN];
printf("Input a cmd number > ");
//scanf_s("%s", cmd,_countof(cmd));
scanf("%s", cmd);
tDataNode *p = FindCmd(linktable, 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(linktable);
return 0;
}
int Quit()
{
exit(0);
}
linktable.c
#include "linktable.h"
#include <stdlib.h>
#include<stdio.h>
tLinkTable * CreateLinkTable()
{
tLinkTable * pLinkTable = (tLinkTable *)malloc(sizeof(tLinkTable));
if (pLinkTable == NULL)
{
return NULL;
}
pLinkTable->pHead = NULL;
pLinkTable->pTail = NULL;
pLinkTable->SumOfNode = 0;
return pLinkTable;
}
int AddLinkTableNode(tLinkTable * pLinkTable, tLinkTableNode * pNode)
{
if (pLinkTable->SumOfNode == 0)
{
pLinkTable->pHead = pNode;
pLinkTable->pTail = pNode;
pLinkTable->SumOfNode++;
pNode->pNext = NULL;
return 0;
}
pLinkTable->pTail->pNext = pNode;
pLinkTable->pTail = pNode;
pNode->pNext = NULL;
pLinkTable->SumOfNode++;
return 0;
}
int DelLinkTableNode(tLinkTable * pLinkTable, tLinkTableNode * pNode)
{
if (pLinkTable->SumOfNode == 0)
{
printf("LinkTable is NULL");
exit(0);
}
tLinkTableNode *q = pLinkTable->pHead;
if (q == pNode)
{
pLinkTable->pHead = pLinkTable->pHead->pNext;
free(pNode);
return 0;
}
while (q->pNext != pNode)
{
q = q->pNext;
}
tLinkTableNode *r = q->pNext;
q->pNext = r->pNext;
free(r);
return 0;
}
tLinkTableNode * GetLinkTableHead(tLinkTable *LinkTable)
{
return LinkTable->pHead;
}
tLinkTableNode * GetNextLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode * pNode)
{
return pNode->pNext;
}
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 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);
//Get LinkTableHead
tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable);
//Get next LinkTableNode
tLinkTableNode * NextLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode * pNode);
#endif /* _LINK_TABLE_H_ */