在课程目录下创建lab7文件夹。
给整个命令行菜单menu程序定义一套接口,提供两个方法。在menu.h文件中声明MenuConfig函数和ExcuteMenu函数。其中,MenuConfig函数用于向链表中添加命令结点,若原链表头结点为空,则先添加默认的help命令结点。ExcuteMenu函数改自原menu.c的main函数,用于获取并执行用户输入的命令。 menu.h
#ifndef _menu
#define _menu
int MenuConfig(char* cmd, char* desc, int (*handler)());
int ExecuteMenu();
#endif
copy
menu.c文件 实现menu.h文件中定义的MenuConfig函数和ExcuteMenu函数。使用getopt函数,使menu子系统支持带参数的命令。 修改ExcuteMenu函数,将输入的命令行解析为int argc ,char *agrv[]的形式。没有使用fgets获得一行数据而是定义了一个ReceiveCMD。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "linktable.h"
int Help(int argc, char* argv[]);
extern char* optarg;
extern int optind;
#define CMD_MAX_LEN 128
#define CMD_MAX_ARGV 128
#define DESC_LEN 1024
#define CMD_NUM 10
/* data struct and its operations */
tLinkTable* head = NULL;
typedef struct DataNode
{
tLinkTableNode * pNext;
char* cmd;
char* desc;
int (*handler)(int argc, char* argv[]);
} tDataNode;
int SearchCondition(tLinkTableNode * pLinkTableNode, void * args)
{
tDataNode * pNode = (tDataNode *)pLinkTableNode;
char * tempchar = args;
if(strcmp(pNode->cmd, args) == 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);
printf("---------------------------------------------\n");
while(pNode != NULL)
{
printf("%s - %s\n", pNode->cmd, pNode->desc);
pNode = (tDataNode*)GetNextLinkTableNode(head,(tLinkTableNode *)pNode);
}
printf("---------------------------------------------\n");
return 0;
}
int ReceiveCMD(char* cmd, int* argc, char* argv[])
{
char* pcmd = NULL;
pcmd = fgets(cmd, CMD_MAX_LEN, stdin);
int len = strlen(cmd);
*(cmd + len - 1) = '\0';
pcmd = strtok(pcmd, " ");
while(pcmd == NULL)
{
return -1;
}
while(pcmd != NULL && (*argc) < CMD_MAX_ARGV)
{
argv[*argc] = pcmd;
(*argc)++;
pcmd = strtok(NULL, " ");
}
return 0;
}
int MenuConfig(char* cmd, char* desc, int (*handler)(int argc, char* argv[]))
{
tDataNode* pNode = NULL;
if(head == NULL)
{
head = CreateLinkTable();
pNode = (tDataNode*)malloc(sizeof(tDataNode));
pNode->cmd = "help";
pNode->desc = "list all cmds";
pNode->handler = Help;
AddLinkTableNode(head, (tLinkTableNode*)pNode);
}
pNode = (tDataNode*)malloc(sizeof(tDataNode));
pNode->cmd = cmd;
pNode->desc = desc;
pNode->handler = handler;
AddLinkTableNode(head, (tLinkTableNode*)pNode);
return 0;
}
/* menu program */
int ExecuteMenu()
{
/* cmd line begins */
while(1)
{
int argc = 0;
char* argv[CMD_MAX_ARGV];
char cmd[CMD_MAX_LEN];
printf("Input a cmd number > ");
if(ReceiveCMD(cmd, &argc, argv) == -1)
{
continue;
}
//scanf("%s", cmd);
tDataNode *p = FindCmd(head, argv[0]);
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(argc, argv);
}
}
}
int Help(int argc, char* argv[])
{
int ch;
char* ch_prom;
if(argc == 1)
{
ShowAllCmd(head);
return 0;
}
while((ch = getopt(argc, argv, "shl:")) != -1)
{
switch(ch)
{
case 's':
printf("This is \"-s\" mode help\n");
ShowAllCmd(head);
break;
case 'h':
printf("This is \"-h\" mode help\n");
ShowAllCmd(head);
break;
case '?':
printf("Wrong argument!\n");
}
}
optind = 1;
return 0;
}
copy
test.c文件
#include "menu.h"
#include <stdio.h>
#include <stdlib.h>
int version(int argc, char* argv);
int quit(int argc, char* argv);
int main()
{
char* cmd = "version";
char* desc = "version information";
MenuConfig(cmd, desc, version);
cmd = "quit";
desc = "type \"quit\" to exit";
MenuConfig(cmd, desc, quit);
ExecuteMenu();
return 0;
}
int version(int argc, char* argv)
{
printf("v1.0\n");
return 0;
}
int quit(int argc, char* argv)
{
exit(0);
return 0;
}
copy
编写Makefile文件,使用户可以使用make来编译程序。
CC_FLAGS = -c
CC_OUTPUT_FLAGS = -o
CC = gcc
TARGET = test
OBJS = linktable.o menu.o test.o
RM = rm
RM_FLAGS = -f
all: $(OBJS)
$(CC) $(CC_OUTPUT_FLAGS) $(TARGET) $(OBJS)
.c.o:
$(CC) $(CC_FLAGS) $<
clean:
$(RM) $(RM_FLAGS) $(OBJS) $(TARGET) *.bak
copy
学习时间 304分钟
操作时间 102分钟
按键次数 3031次
实验次数 6次
报告字数 5494字
是否完成 完成