将menu设计为可重用的子系统
学号:SA17225091
姓名:龚雨濛
github:https://github.com/lgddd/gr_lab
1. 实验要求
- 为menu子系统设计接口,并写用户范例代码来实现原来的功能;
- 使用make和make clean来编译程序和清理自动生成的文件;
- 使menu子系统支持带参数的复杂命令,并在用户范例代码中自定义一个带参数的复杂命令;
- 可以使用getopt函数获取命令行参数;
2. 实验过程
- 新建lab7文件夹
- 拷贝lab5文件至lab7
- 新建 menu.h
#ifndef _menu
#define _menu
int MenuConfig(char* cmd, char* desc, int (*handler)());
int ExecuteMenu();
#endif
- 新建Makefile文件
CC_PTHREAD_FLAGS = -lpthread
CC_FLAGS = -c
CC_OUTPUT_FLAGS = -o
CC = gcc
RM = rm
RM_FLAGS = -f
TARGET = test
OBJS = linktable.o menu.o test.o
all: $(OBJS)
$(CC) $(CC_OUTPUT_FLAGS) $(TARGET) $(OBJS)
.c.o:
$(CC) $(CC_FLAGS) $<
clean:
$(RM) $(RM_FLAGS) $(OBJS) $(TARGET) *.bak
用ExcuteMenu取代main函数并作相应修改
int ExecuteMenu()
{
//InitMenuData(&head);
//char cmd[81];
/* cmd line begins */
while(1)
{
//char cmd[CMD_MAX_LEN];
int argc = 0;
char *argv[CMD_MAX_ARGV_LEN];
//char cmd[CMD_MAX_LEN];
char *pcmd = NULL;
printf("Input a cmd number > ");
//scanf("%s", cmd);
pcmd = fgets(cmd, CMD_MAX_LEN, stdin);
if(pcmd == NULL)
{
continue;
}
pcmd = strtok(pcmd, " ");
while(pcmd != NULL && argc < CMD_MAX_ARGC_LEN)
{
printf("%s\n", pcmd);
argv[argc] = pcmd;
argc++;
pcmd = strtok(NULL, " ");
}
if(argc == 1)
{
int len = strlen(argv[0]);
*(argv[0] + len - 1) = '\0';
}
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);
}
}
}
- 修改ExcuteConfig
int MenuConfig(char *cmd, char *desc, int (*handler)(int argc, char *argv[]))
{
tDataNode *pNode = NULL;
if(head == NULL)
{
head = (tLinkTable *)CreateLinkTable();
pNode = (tDataNode *)malloc(sizeof(tDataNode));
pNode->cmd = "help";
pNode->desc = "Help List";
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);
}
- 新建test.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "linktable.h"
#include "menu.h"
/*
int getopt(int argc, char * const argv[], const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;
*/
int Quit(int argc, char* argv[]);
int main(int argc, char* argv[])
{
MenuConfig("version", "Menu Program V3.0", NULL);
MenuConfig("quit", "Quit from Menu Program V3.0", Quit);
ExecuteMenu();
}
int Quit(int argc, char* argv[])
{
int oc;
char *b_opt_arg;
while((oc = getopt(argc, argv, "cl:\n")) != -1)
{
switch(oc)
{
case 'c':
printf("Clean Success,exiting\n");
//delay(2000);
sleep(2);
break;
case 'l':
b_opt_arg = optarg;
printf("Log :%s\n",optarg);
//delay(2000);
sleep(2);
break;
case '\n':
break;
}
}
exit(0);
}
3.实验心得与总结
- 本次实验通过为menu设计子系统接口,进一步提高了menu小程序的可重用性和模块化。Makefile的使用实现了自动化的脚本,省去了每次敲很多的编译命令。
- 模块化的思想有利于提高编程的可重用性和效率。以后我也会把这种思想运用其他代码的编写中。