实验七:将menu设计为可重用的子系统
2017-11-09 21:16
411 查看
“软件工程(C编码实践篇)”实验报告
实验七:将menu设计为可重用的子系统
网易云课堂昵称:Arjen0130
《软件工程(C编码实践篇)》MOOC课程作业http://mooc.study.163.com/course/USTC-1000002006
依照学术诚信条款,我保证此回答为本人原创,所有回答中引用的外部材料已经做了出处标记。
GitHub仓库:https://github.com/Arjen0130/AdvancedSoftwareEngineering.git
实验报告原链接地址:http://note.youdao.com/noteshare?id=c18689570e3e66ecc2d226d2603e1beb&sub=ADEC9A84FF5C4FEBB80D28D2A701F643
1. 实验内容和要求
1.1 实验内容
在实验5的代码的基础上,将menu设计为可重用的子系统
1.2 实验要求
为menu子系统设计接口,并写用户范例代码来实现原来的功能;
使用make和make clean来编译程序和清理自动生成的文件;
使menu子系统支持带参数的复杂命令,并在用户范例代码中自定义一个带参数的复杂命令;
可以使用getopt函数获取命令行参数。
注:本实验在实验5的代码基础上进行。
2. 实验的思路和具体过程
2.1 实验的思路
看完实验七的相关学习视频以后,学习到了将一个menu系统设计为可重用子系统的方法,特别是相关接口的定义方法。
依照视频讲解,并参照实验要求,从而完成本次实验。
2.2 实验的具体过程
1)使用实验1中创建好的本地仓库,添加lab7文件夹,把实验5的需要用到的文件复制到lab7文件夹中;
2)添加接口文件,并对已有的相关文件进行修改,使其能够作为可重用的子系统被调用;
3)添加测试文件,测试步骤2)中完成的可重用的子系统的相关功能是否正确;
4)编译、调试通过后,添加到git本地仓库,并上传到git远端仓库。
3. 关键代码
3.1 增加的接口文件menu.h
3.2 对menu.c文件做出的修改
3.3 增加的测试文件test.c
3.4 Makefile文件代码
4. 相关截图
4.1 实验结果截图
4.2 关键代码截图
4.2.1 test.c文件中的关键代码截图
4.2.2 menu.h文件中的关键代码截图
4.2.3 menu.c文件中的关键代码截图
4.2.4 Makefile文件截图
4.3 操作过程截图
4.3.1 本次实验用到的头文件和源文件
4.3.2 执行make命令后的结果
4.3.3 将本地仓库的变化提交到远端仓库
4.4 复现操作截图
5. 实验过程中遇到的疑惑、困难及处理方法
本次实验过程中遇到的最大的问题就是getopt函数的调用问题。对应的menu命令初次执行的之后,一切正常,getopt函数可以正确读出menu命令的选项和参数。但是,当重复执行时,该函数无法正常工作。经过查找相关资料,发现getopt函数的使用了几个全局变量,其中一个optind变量用来记录上一次的处理位置。实际结果表明,为了使同一个命令能够多次重复工作,在调用getopt函数之前,需要重置optind变量的值。
6. 实验总结
通过本次实验,学习到了将一个menu程序修改为可重入子系统的方法。并且,学习使用了getopt函数。
实验七:将menu设计为可重用的子系统
网易云课堂昵称:Arjen0130
《软件工程(C编码实践篇)》MOOC课程作业http://mooc.study.163.com/course/USTC-1000002006
依照学术诚信条款,我保证此回答为本人原创,所有回答中引用的外部材料已经做了出处标记。
GitHub仓库:https://github.com/Arjen0130/AdvancedSoftwareEngineering.git
实验报告原链接地址:http://note.youdao.com/noteshare?id=c18689570e3e66ecc2d226d2603e1beb&sub=ADEC9A84FF5C4FEBB80D28D2A701F643
1. 实验内容和要求
1.1 实验内容
在实验5的代码的基础上,将menu设计为可重用的子系统
1.2 实验要求
为menu子系统设计接口,并写用户范例代码来实现原来的功能;
使用make和make clean来编译程序和清理自动生成的文件;
使menu子系统支持带参数的复杂命令,并在用户范例代码中自定义一个带参数的复杂命令;
可以使用getopt函数获取命令行参数。
注:本实验在实验5的代码基础上进行。
2. 实验的思路和具体过程
2.1 实验的思路
看完实验七的相关学习视频以后,学习到了将一个menu系统设计为可重用子系统的方法,特别是相关接口的定义方法。
依照视频讲解,并参照实验要求,从而完成本次实验。
2.2 实验的具体过程
1)使用实验1中创建好的本地仓库,添加lab7文件夹,把实验5的需要用到的文件复制到lab7文件夹中;
2)添加接口文件,并对已有的相关文件进行修改,使其能够作为可重用的子系统被调用;
3)添加测试文件,测试步骤2)中完成的可重用的子系统的相关功能是否正确;
4)编译、调试通过后,添加到git本地仓库,并上传到git远端仓库。
3. 关键代码
3.1 增加的接口文件menu.h
... ... /* * Add cmd to menu. * @cmd: Name of the cmd to be added. * @desc: Description of the cmd to be added. * @handler: A function handler which executes the cmd. * @return: Number reflects function status. */ int MenuConfig(char * cmd, char * desc, int (*handler)(int argc, char * argv[])); /* * Menu Engine Execute. * @return: Number reflects function status. */ int ExecuteMenu();
3.2 对menu.c文件做出的修改
... ... #include "menu.h" int Help(int argc, char * argv[]); #define CMD_MAX_LEN 128 #define CMD_MAX_ARGV_NUM 10 #define DESC_LEN 1024 #define CMD_NUM 10 //char cmd[CMD_MAX_LEN]; /* data struct and its operations */ typedef struct DataNode { tLinkTableNode * pNext; char* cmd; char* desc; int (*handler)(int argc, char * argv[]); } tDataNode; ... ... /* * Add cmd to menu. * @cmd: Name of the cmd to be added. * @desc: Description of the cmd to be added. * @handler: A function handler which executes the cmd. * @return: Number reflects function status. */ int MenuConfig(char * cmd, char * desc, int (*handler)(int argc, char * argv[])) { tDataNode * pNode = NULL; if(NULL == head) { head = CreateLinkTable(); pNode = (tDataNode *)malloc(sizeof(tDataNode)); pNode->cmd = "help"; pNode->desc = "Menu 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); return 0; } /* * Menu Engine Execute. * @return: Number reflects function status. */ int ExecuteMenu() { /* cmd line begins */ while(1) { int argc = 0; char *argv[CMD_MAX_ARGV_NUM]; char cmd[CMD_MAX_LEN]; char * pcmd = NULL; printf("Input a cmd > "); /* scanf("%s", cmd); */ pcmd = fgets(cmd, CMD_MAX_LEN, stdin); if(NULL == pcmd) { continue; } /* convert cmd to argc/argv */ pcmd = strtok(pcmd, " "); while((NULL != pcmd) && (CMD_MAX_ARGV_NUM > argc)) { argv[argc++] = pcmd; pcmd = strtok(NULL, " "); } if(1 == argc) { 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); } } } int Help(int argc, char * argv[]) { ShowAllCmd(head); return 0; } ... ...
3.3 增加的测试文件test.c
... ... #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <getopt.h> #include <string.h> #include "menu.h" #define MAX_OPTION_ARGUMENT_SIZE 128 /* *This function is used to process the "compare" command. */ int compare(int argc, char * argv[]) { int ch; char argA[MAX_OPTION_ARGUMENT_SIZE]; char argB[MAX_OPTION_ARGUMENT_SIZE]; printf("This is the compare command...\n"); /* for(int i = 0; i < argc; i++) */ /* { */ /* printf("The argv[%d] = %s\n", i, argv[i]); */ /* } */ /* printf("optind: %d\n", optind); */ optind = 1; //这句必不可少,否则,多次执行相同的参数时,会出现结果不一致的情 while((ch = getopt(argc, argv, "a:b:")) != -1) { printf("optind: %d\n", optind); switch(ch) { case 'a': printf("HAVE option: -a\n"); printf("The argument of -a is %s\n", optarg); argA[0] = '\0'; if(NULL != optarg) { memcpy(argA, optarg, strlen(optarg)); } break; case 'b': printf("HAVE option: -b\n"); printf("The argument of -b is %s\n", optarg); argB[0] = '\0'; if(NULL != optarg) { memcpy(argB, optarg, strlen(optarg)); } break; case '?': printf("Unknown option: %c\n", (char)optopt); break; } } return 0; } /* *This function is used to process the "get" command. */ int get(int argc, char * argv[]) { printf("This is the get command...\n"); return 0; } /* *This function is used to process the "pull" command. */ int pull(int argc, char * argv[]) { printf("This is the pull command...\n"); return 0; } /* *This function is used to process the "push" command. */ int push(int argc, char * argv[]) { printf("This is the push command...\n"); return 0; } /* *This function is used to process the "put" command. */ int put(int argc, char * argv[]) { printf("This is the put command...\n"); return 0; } /* *This function is used to quit the program. */ int quit(int argc, char * argv[]) { printf("This is the quit command...\n"); exit(0); } int main(int argc, int * argv[]) { MenuConfig("compare", "compare cmd:", compare); MenuConfig("get", "get cmd:", get); MenuConfig("pull", "pull cmd:", pull); MenuConfig("push", "push cmd:", push); MenuConfig("put", "put cmd:", put); MenuConfig("quit", "quit Cmd:", quit); return ExecuteMenu(); }
3.4 Makefile文件代码
# # Makefile for Menu Program # CC_PTHREAD_FLAGS = -lpthread CC_FLAGS = -c CC_OUTPUT_FLAGS = -o CC = gcc RM = rm RM_FLAGS = -f TARGET = test OBJS = test.o menu.o linktable.o all: $(OBJS) $(CC) $(CC_OUTPUT_FLAGS) $(TARGET) $(OBJS) .c.o: $(CC) $(CC_FLAGS) $< clean: $(RM) $(RM_FLAGS) $(OBJS) $(TARGET) *.bak
4. 相关截图
4.1 实验结果截图
4.2 关键代码截图
4.2.1 test.c文件中的关键代码截图
4.2.2 menu.h文件中的关键代码截图
4.2.3 menu.c文件中的关键代码截图
4.2.4 Makefile文件截图
4.3 操作过程截图
4.3.1 本次实验用到的头文件和源文件
4.3.2 执行make命令后的结果
4.3.3 将本地仓库的变化提交到远端仓库
4.4 复现操作截图
5. 实验过程中遇到的疑惑、困难及处理方法
本次实验过程中遇到的最大的问题就是getopt函数的调用问题。对应的menu命令初次执行的之后,一切正常,getopt函数可以正确读出menu命令的选项和参数。但是,当重复执行时,该函数无法正常工作。经过查找相关资料,发现getopt函数的使用了几个全局变量,其中一个optind变量用来记录上一次的处理位置。实际结果表明,为了使同一个命令能够多次重复工作,在调用getopt函数之前,需要重置optind变量的值。
6. 实验总结
通过本次实验,学习到了将一个menu程序修改为可重入子系统的方法。并且,学习使用了getopt函数。
相关文章推荐
- 实验七:将menu设计为可重用的子系统
- 实验七:将menu设计为可重用的子系统
- 实验七:将menu设计为可重用的子系统
- 实验七:将menu设计为可重用的子系统
- 实验七:将menu设计为可重用的子系统
- 软件工程(C编码实践篇)”实验报告实验七:将menu设计为可重用的子系统
- 实验7 将menu设计为可重用的子系统
- 将menu设计为可重用的子系统
- 将menu设计为可重用的子系统
- “软件工程(C编码实践篇)”实验报告【实验七:将menu设计为可重用的子系统】
- 高级软件工程实验7-----将menu设计为可重用的子系统
- 文章标题 实验七:将menu设计为可重用的子系统
- 实验报告七:将menu设计为可重用的子系统
- 实验报告七:将menu设计为可重用的子系统
- [高级软件工程实验]将menu设计为可重用的子系统
- 实验七:将menu设计为可重用的子系统
- 子系统的可重用设计
- MENU可重用的子系统
- 团队开发项目客户端——游戏子系统的设计(中)
- Android基础教程(五)之-----Menu功能菜单设计