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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/oniy_/article/details/78243214

【网易云课堂昵称:JaYiFen + 《软件工程(C编码实践篇)》MOOC课程作业http://mooc.study.163.com/course/USTC-1000002006 】


实验要求:

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

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

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

  • 接口规范;


实验思路:

将上一节的代码进行改造重用,将每个功能封装成一个链表节点。然后在menu中调用等操作。实现更进一步的模块化设计。


实验代码(因为代码较多就不截图上传,直接提出源代码):

1.menu.c

#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

typedef struct DataNode
{
	tLinkTableNode *pNext;
	char* cmd;
	char* desc;
	int(*handler)();
	struct DataNode *next;
}tDataNode;
用可重用的链表模块来实现命令行菜单小程序V2.5
tDataNode *FindCmd(tLinkTable *head, char *cmd)
{
	tDataNode* pNode=(tDataNode*)GetLinkTableHead(head);
	while(NULL != pNode)
	{
		if(!strcmp(pNode->cmd,cmd))
		{
			return pNode;
		}
		pNode=(tDataNode*)GetNextLinkTableNode(head,(tLinkTableNode*)pNode);
	}
	return NULL;
}

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="help command:";
	pNode->handler=help;
	AddLinkTableNode(*ppLinkTable,(tLinkTableNode *)pNode);
	pNode=(tDataNode*)malloc(sizeof(tDataNode));
	pNode->cmd="version";
	pNode->desc="menu program v1.1 beta";
	pNode->handler=NULL;
	AddLinkTableNode(*ppLinkTable,(tLinkTableNode *)pNode);
	pNode=(tDataNode*)malloc(sizeof(tDataNode));
	pNode->cmd="quit";
	pNode->desc="quit this software";
	pNode->handler=quit;
	AddLinkTableNode(*ppLinkTable,(tLinkTableNode *)pNode);
	return 0;
}

tLinkTable* head=NULL;

int main()
{
	InitMenuData(&head);
	while(1)
	{
		char cmd[CMD_MAX_LEN];
		printf("Please Input Command >");
		scanf("%s",cmd);
		tDataNode *p = FindCmd(head,cmd);
		if(NULL == p)
		{
			printf("wrong cmd!\n");
			continue;
		}
		printf("%s - %s\n",p->cmd,p->desc);
		if(NULL != p -> handler)
		{
			p -> handler();
		}
	}
}

int help()
{
	printf("Menu List:\n");
	ShowAllCmd(head);
	return 0;
}

int quit()
{
	exit(0);
	return 0;
}

2.linktable.h

#ifndef _LINK_TABLE_H_
#define _LINK_TABLE_H_

#define SUCCESS 0
#define FAILURE (-1)

typedef struct LinkTableNode
{
	    struct LinkTableNode *pNext;
}tLinkTableNode;

typedef struct LinkTable
{
	    tLinkTableNode *pHead;
		    tLinkTableNode *pTail;
			    int     SumOfNode;
}tLinkTable;

tLinkTable *CreateLinkTable();
int DeleteLinkTable(tLinkTable *pLinkTable);
int AddLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode *pNode);
int DeleteLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode *pNode);
tLinkTableNode *GetLinkTableHead(tLinkTable *pLinkTable);
tLinkTableNode *GetNextLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode *pNode);

#endif

3.linktable.c

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

tLinkTable *CreateLinkTable()
{
	tLinkTable *pLinkTable=(tLinkTable*)malloc(sizeof(tLinkTable));
	pLinkTable->pHead=NULL;
	pLinkTable->SumOfNode=0;
	return pLinkTable;
}

int DeleteLInkTable(tLinkTable *pLinkTable)
{
	if(NULL == pLinkTable)
	{
		return FAILURE;
	}
	if(NULL == pLinkTable->pHead)
	{
		free(pLinkTable);
		return SUCCESS;
	}
	tLinkTableNode *pNode=GetLinkTableHead(pLinkTable);
	tLinkTableNode *pTempNode;

	while(NULL != pNode)
	{
		pTempNode=pNode;
		pNode=GetNextLinkTableNode(pLinkTable,pNode);
		free(pTempNode);
	}
	free(pNode);
	return SUCCESS;
}

int AddLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode *pNode)
{
	if(NULL == pLinkTable || NULL ==  pNode)
	{
		return FAILURE;
	}
	if(pLinkTable->pHead == NULL)
	{
		pLinkTable->pHead=pNode;
		return SUCCESS;
	}
	tLinkTableNode *ptrNode=GetLinkTableHead(pLinkTable);
	while(ptrNode->pNext != NULL)
	{
		ptrNode=ptrNode->pNext;
	}
	ptrNode->pNext=pNode;
	return SUCCESS;
}

int DelLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode *pNode)
{
	if(pLinkTable == NULL || pNode == NULL)
	{
		return FAILURE;
	}
	if(pLinkTable->pHead == NULL)
	{
		free(pLinkTable->pHead);
		return SUCCESS;
	}
	tLinkTableNode *ptrNode = GetLinkTableHead(pLinkTable);
	while(ptrNode->pNext != pNode)
	{
		ptrNode=ptrNode->pNext;
	}
	tLinkTableNode *ptrTemp=ptrNode->pNext;
	ptrNode->pNext=ptrTemp->pNext;
	free(ptrTemp);
	return SUCCESS;

}

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

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


实验运行截图:



上传代码:


GitHub地址

实验总结:

从实验和视频课中可以知道接口的分类:

1.共享数据或变量名;

2.call-in functions;

3.同步调用接口;

4,异步调用接口;



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

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

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

  • 接口规范;


猜你喜欢

转载自blog.csdn.net/oniy_/article/details/78243214