您的位置:首页 > 其它

软件工程课程实验报告:实验七

2017-11-06 20:17 274 查看

实验七:将menu设计为可重用的子系统

咖啡机《软件工程(C编码实践篇)》MOOC课程作业http://mooc.study.163.com/course/USTC-1000002006

新创建一个目录lab7完成实验。

一、实验要求

为menu子系统设计接口,并写用户范例代码来实现原来的功能;

使用make和make clean来编译程序和清理自动生成的文件;

使menu子系统支持带参数的复杂命令,并在用户范例代码中自定义一个带参数的复杂命令;

可以使用
getopt()
函数获取命令行参数。

二、实验过程

1. 设计menu子系统接口

menu.h
添加两个函数
MenuConfig()
ExecuteMenu()
用于添加命令和运行menu程序

/* add cmd to menu */
int MenuConfig(char* cmd, char* desc, int (*handler)(int argc, char *argv[]));
/* Menu Engine Execute */
int ExecuteMenu();


2. 子接口实现

menu.c
中实现
MenuConfig()
函数和
ExecuteMenu()
函数

/* Set or configure menu list */
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 = "This is the informations of commands";
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 b
4000
egins */
while(1)
{
int argc = 0;
char *argv[CMD_MAX_ARGV_NUM];
char cmd[CMD_MAX_LEN];
char *pcmd = NULL;
printf("Input a command> ");
pcmd = fgets(cmd, CMD_MAX_LEN, stdin);
tDataNode *p = FindCmd(head, cmd);
if( pcmd == NULL)
{
continue;
}
pcmd = strtok(pcmd, " ");
while(pcmd != NULL && argc < CMD_MAX_ARGV_NUM)
{
argv[argc] = pcmd;
argc ++;
pcmd = strtok(NULL, " ");
}
if(argc == 1)
{
int len = strlen(argv[0]);
*(argv[0] + len -1) = '\0';
}
tDataNode *pn = (tDataNode*)SearchLinkTableNode(head, SearchCondition, (void*)argv[0]);
if(pn == NULL)
{
printf("This is a wrong cmd!\n");
continue;
}
if(pn->handler != NULL)
{
pn->handler(argc, argv);
}
}
return 0;
}


3. 定义带参数的指令

利用
getopt()
获取命令参数,为命令定义不同参数下的不同执行操作。

int Help(int argc,char* argv[])
{
int opt;
while((opt=getopt(argc,argv,"l:a:"))!= -1)
{
switch(opt)
{
case 'a':
printf("this is -a option\n");
ShowAllCmd(head);
break;
case 'b':
printf("this is -b option\n");
break;
default:
printf("Unknowed  option %c\n",opt);
}
}
return 0;
}


4. 测试模块实现

主要由
test.c
承担,调用
menu.c
中的接口,添加和调用指令。其中,自定义的指令包括:

version

exit

plus

minus

multiply

divide

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

int Exit(int argc, char *argv[])
{
printf("exit the program\n");
exit(0);
}

int Version(int argc, char *argv[])
{
printf("menu program v3.0\n");
}

int plus(int argc, char *argv[])
{
float a,b;
printf("Input two numbers:\n");
scanf("%f", &a);
scanf("%f", &b);
printf("The sum of %f and %f is %f\n", a, b, a+b);
}

int minus(int argc, char *argv[])
{
float a,b;
printf("Input two numbers:\n");
scanf("%f", &a);
scanf("%f", &b);
printf("%f minus %f equals %f\n", a, b, a-b);
}

int multiply(int argc, char *argv[])
{
float a,b;
printf("Input two numbers:\n");
scanf("%f", &a);
scanf("%f", &b);
printf("%f multiply %f equals %f\n", a, b, a*b);
}

int divide(int argc, char *argv[])
{
float a,b;
printf("Input two numbers:\n");
scanf("%f", &a);
scanf("%f", &b);
if ( b == 0)
printf("Error: 0 can not be used as a divisor!\n");
else
printf("%f divided by %f is %f\n", a, b, a/b);
}

int main(int argc, char *argv[])
{
MenuConfig("version", "menu program v3.0", Version);
MenuConfig("plus", "sum of a and b", plus);
MenuConfig("minus", "result of a minus b", minus);
MenuConfig("multiply", "result of a times b", multiply);
MenuConfig("divide", "result of a divided by b", divide);
MenuConfig("exit", "Exit this program", Exit);
ExecuteMenu();
return 0;
}


5. 编辑Makefile

使用
make
make clean
来编译程序和清理自动生成的文件。

CC_PTHREAD_FLAGS     = -lpthread
CC_FLAGS             = -c
CC_OUTPUT_FLAGS      = -o
CC_MATH              = -lm
CC                   = gcc
RM                   = rm
RM_FLAGS             = -f

TARGET               = test
OBJS                 = linktable.o menu.o test.o

all:    $(OBJS)
$(CC) $(CC_OUTPUT_FLAGS) $(TARGET) $(OBJS) $(CC_MATH)

.c.o:
$(CC) $(CC_FLAGS) $<

clean:
$(RM) $(RM_FLAGS) $(OBJS) $(TARGET) *.bak


6. 编译运行

包括三部分:

- 利用
make
指令编译程序

- 执行程序,并利用
help -a
version
exit
等三个正确指令,
quit
一个错误指令进行测试

- 利用
make clean
清理程序执行过程中自动生成的文件。



7. 将代码同步到github



Github地址:https://github.com/973301529/se/tree/master/lab7

三、实验总结

通过此次实验,对程序进行了更进一步的可重用设计,学习了Makefile的编写方法,简化了编译命令。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: