【实验报告】高软实验7
来源:互联网 发布:写算法 编辑:程序博客网 时间:2024/05/29 18:46
【Jerryykt1464929958440 + 《软件工程(C编码实践篇)》MOOC课程作业http://mooc.study.163.com/course/USTC-1000002006 】
github地址:https://github.com/JerryLittleBear/experiment.git
【实验目的】:
1. 为menu子系统设计接口,并写用户范例代码来实现原来的功能
2. 使用make和make clean来编译程序和清理自动生成的文件
3. 使menu子系统支持带参数的复杂命令,并在用户范例代码中自定义一个带参数的复杂命令
4. 使用getopt()函数来获取命令行参数
【实验过程】:
1. menu子系统接口
定义menu.h接口
#ifndef __MENU_H__#define __MENU_H__/*----------Add Command to Menu----------*/int MenuConfig(char* cmd, char* desc, int (*handler)(int argc, char** argv));/*----------Menu Engine Execute----------*/int ExecuteMenu();int Help(int argc, char **argv);int Quit(int argc, char **argv);#endif
修改menu.c中实现接口:int ExecuteMenu(){ while(1) {int argc = 0;char *argv[CMD_MAX_ARGV_NUM]; 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; } /* convert cmd to argc/argv */ 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 *p = (tDataNode*)SearchLinkTableNode(head, SearchCondition, (void*)argv[0]); if(p == NULL) { printf("This is a wrong cmd!\n"); continue; } if(p->handler != NULL) { p->handler(argc, argv); } } 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 = "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;
2. Makefile参考老师给的Makefile
CC_PTHREAD_FLAG = -lpthreadCC_FLAGS = -cCC_OUTPUT_FLAGS = -oCC = gccRM = -rmRM_FLAGS = -fSRC = linktable.c menu.c test.cTARGET = testOBJS = linktable.o menu.o test.oall:$(OBJS)$(CC) $(CC_OUTPUT_FLAGS) $(TARGET) $(OBJS).c.o:$(CC) $(CC_FLAGS) $<clean:$(RM) $(RM_FLAGS) $(OBJS) $(TARGET) *.bak
对代码进行make操作3. 实现带参数的复杂命令
int Hello(int argc, char** argv){ const char * optString = "abc"; opterr = 0; int opt; while((opt = getopt(argc, argv, optString)) != -1) { switch(opt) { case 'a': printf("method a\n"); break; case 'b': printf("method b\n"); break; default: break; } } optind = 0; return 0;}
可以实现对命令的带参数操作:命令是hello
-a和-b参数可以实现不同的hello命令
【实验总结】:
1、子系统的设计必须根据项目、功能的不同而不同,必须进行充分的需求分析,不可盲目。
就比如我们要为menu程序设计接口就不能和为linktable设计的接口一模一样,而必须考虑menu需要提供的功能,只需定义两个接口函数:MenuConfig用来给菜单加入命令,ExecuteMenu用来启动menu的引擎.
2、利用Makefile进行自动化编译
3、利用main函数的argc和argv参数,实现对命令行中带参数命令的实现
#include <stdio.h>//#包含<stdio.h>
int main(int argc,char* argv[]) //整数类型主函数(整数类型统计参数个数,字符类型指针数组指向字符串参数)
{
printf("%d\n",argc); //格式化输出
while(argc) //当(统计参数个数)
printf("%s\n",argv[--argc]); //格式化输出
return 0; //返回0;正常退出
}
4、strtok函数的使用
char *strtok(char s[], const char *delim);
strtok()用来将字符串分割成一个个片段。参数s指向欲分割的字符串,参数delim则为分割字符串,当strtok()在参数s的字符串中发现到参数delim的分割字符时则会将该字符改为\0 字符。在第一次调用时,strtok()必需给予参数s字符串(此时返回分割符前面的字符串),往后的调用则将参数s设置成NULL,值得注意的是,如果参数是NULL,则strtok返回s字符串的第二块被分割出来的子字符串。每次调用成功则返回被分割出片段的指针,当没有被分割的串时则返回NULL。
例子:
char s1[] = "my name is jerry";
char* p1 = strtok(s1, " ");
while(p1 != NULL)
{
printf("%s\n", p1);
p1 = strtok(NULL, " ");
}
这样的话依次打印my、name、is、jerry等4个字符串
5、getopt函数:
int getopt(int argc,char * const argv[ ],const char * optstring);
短参数的定义
getopt()使用optstring所指的字串作为短参数列表,象"1ac:d::"就是一个短参数列表。短参数的定义是一个'-'后面跟一个字母或数字,象-a, -b就是一个短参数。每个数字或字母定义一个参数。
其中短参数在getopt定义里分为三种:
1. 不带值的参数,它的定义即是参数本身。
2. 必须带值的参数,它的定义是在参数本身后面再加一个冒号。
3. 可选值的参数,它的定义是在参数本身后面加两个冒号 。
在这里拿上面的"1ac:d::"作为样例进行说明,其中的1,a就是不带值的参数,c是必须带值的参数,d是可选值的参数。
在实际调用中,'-1 -a -c cvalue -d', '-1 -a -c cvalue -ddvalue', '-1a -ddvalue -c cvalue'都是合法的。这里需要注意三点:
1. 不带值的参数可以连写,象1和a是不带值的参数,它们可以-1 -a分开写,也可以-1a或-a1连写。
2. 参数不分先后顺序,'-1a -c cvalue -ddvalue'和'-d -c cvalue -a1'的解析结果是一样的。
3. 要注意可选值的参数的值与参数之间不能有空格,必须写成-ddvalue这样的格式,如果写成-d dvalue这样的格式就会解析错误。
返回值
getopt()每次调用会逐次返回命令行传入的参数。
当没有参数的最后的一次调用时,getopt()将返回-1。
当解析到一个不在optstring里面的参数,或者一个必选值参数不带值时,返回'?'。
当optstring是以':'开头时,缺值参数的情况下会返回':',而不是'?' 。
参考资料:
http://vopit.blog.51cto.com/2400931/440453
http://www.cnblogs.com/qingergege/p/5914218.html
http://blog.csdn.net/huangxiaohu_coder/article/details/7475156
6、char* fgets(char* buf, int bufsize, FILE* stream)函数,每次读取最多bufsize-1个字符,回车结束,回车会读入,并且最后附加一个'\0',相当与在回车后面加一个'\0'
- 【实验报告】高软实验7
- 【实验报告】高软实验1
- 【实验报告】高软实验2
- 【实验报告】高软实验3
- 【实验报告】高软实验4
- 【实验报告】高软实验5
- 高软实验一报告
- 高软实验二报告
- 高软实验三报告
- 高软实验四报告
- 高软实验五报告
- 高软实验五报告
- 高软实验七报告
- 17高软实验一报告
- 17高软实验二报告
- 17高软实验三报告
- 17高软实验四报告
- 17高软实验七报告
- HTML学习06-表格
- 线性结构
- 566. Reshape the Matrix(2017/11/3)
- 机器学习部分知识点总结
- 设计模式之单例模式(Singleton)
- 【实验报告】高软实验7
- linux下解压命令大全
- Linux(五) 权限
- 关于Red Hat Enterprise中文乱码问题
- 关于交叉编译log4cplus库的问题
- Tiny6410学习ing—(一)、嵌…
- nginx源码阅读(七).nginx的模块化设计
- 【笔试题】Week05
- 20171103-程序员的自我修养