“软件工程(C编码实践篇)”实验报告
实验三:内部模块化的命令行菜单小程序V2.0
网易云课堂昵称:
Arjen0130
《软件工程(C编码实践篇)》MOOC课程作业
http://mooc.study.163.com/course/USTC-1000002006
实验报告原链接地址:http://note.youdao.com/noteshare?id=1033468c36d251e622dbf5587c0ec3f1&sub=AF2D80676EB149D8BA24BDF8FDE01A13
1. 实验内容和要求
1.1 实验内容
实现内部模块化的命令行菜单小程序V2.0。
1.2 实验要求
代码的业务逻辑和数据存储之间的分离,即将系统抽象为两个层级:菜单业务逻辑和菜单数据存储;
遵守代码风格规范,参考借鉴代码设计规范的一些方法;
代码的业务逻辑和数据存储使用不同的源文件实现,即应该有2个.c和一个.h作为接口文件。
2. 实验的思路和具体过程
2.1 实验的思路
看完实验三的相关学习视频以后,在完善命令行菜单小程序时,根据视频中讲解的内容,尝试将系统抽象为两个层级,即菜单业务逻辑和菜单数据存储。
2.2 实验的具体过程
1)使用实验1中创建好的本地仓库,添加lab3文件夹,并在lab3目录下创建、编写相关的头文件以及源文件;
2)编译通过后,进行测试。待测试通过之后,将步骤1)中创建好的头文件和源文件提交到本地仓库;
3)将本地仓库的变化更新到GitHub远端仓库。
3. 关键代码
3.1 main函数关键代码
tDataNode head[] =
{
{"help", "this is help cmd.", help, &head[1]},
{"read", "this is read cmd.", read, &head[2]},
{"write", "this is write cmd", write, &head[3]},
{"get", "this is get cmd", get, &head[4]},
{"pull", "this is pull cmd", pull, &head[5]},
{"push", "this is push cmd", push, &head[6]},
{"compare", "this is compare cmd", compare, &head[7]},
{"put", "this is put cmd", put, &head[8]},
{"quit", "this is quit cmd", quit, NULL}
};
int main()
{
char cCmd[CMD_MAX_LEN];
while(1)
{
printf("Input a cmd > ");
scanf("%s", cCmd);
tDataNode *p = FindCmd(head, cCmd);
if (NULL == p)
{
printf("Undefined command...\n");
continue;
}
printf("%s - %s\n", p->cmd, p->desc);
if(NULL != p->handler)
{
p->handler();
}
}
return 0;
}
3.2 FindCmd函数关键代码
/*
* This function is used to find a cmd in the linklist and return the datanode pointer
* @head: the header of linklist
* @cmd: the command to be searched
* return value: if matched, return pointer of the command; or else return NULL
*/
tDataNode * FindCmd(tDataNode * head, char * cmd)
{
if((NULL == head) || (NULL == cmd))
{
return NULL;
}
tDataNode *p = head;
while(NULL != p)
{
if(0 == strcmp(p->cmd, cmd))
{
return p;
}
p = p->next;
}
return NULL;
}
3.3 ShowAllCmd函数关键代码
/*
*This function is used to show all cmd in listlist
* @head: the header of linklist
* return value: always zero
*/
int ShowAllCmd(tDataNode * head)
{
printf("Menu List:\n");
tDataNode *p = head;
while(NULL != p)
{
printf("%s - %s\n", p->cmd, p->desc);
p = p->next;
}
return 0;
}
3.4 help函数关键代码(以help函数为例)
/*
*This function is used to process the "help" command.
*/
void help()
{
printf("This is the help command...\n");
ShowAllCmd(head);
}
4. 相关截图
4.1 实验结果截图
注:每一条命令执行后,共打印出来两行提示信息。其中,第一行为命令的描述信息;第二行为命令函数执行后,函数体内printf函数的打印信息。
4.2 关键代码截图
4.3 操作过程截图
4.3.1 创建的各个头文件和源文件
4.3.2 将工作目录中的文件添加并提交到Git本地仓库
4.3.3 将本地仓库的变化提交到远端仓库
4.4 复现操作截图
5. 实验过程中遇到的疑惑、困难及处理方法
由于本次实验过程中用到了比较多的源文件,在使用gcc编译,使用git提交的过程中,如果按照文件名逐个输入,十分繁琐。通过查询相关资料,发现gcc和git都支持通配符,因此,在编译多个.c源文件时,可以直接使用gcc -o test *.c命令进行编译;在把源文件添加到git仓库时,可以使用git add *命令把当前目录下的所有文件全部添加到git仓库。
6. 实验总结
通过本次实验,熟悉了模块化编程的相关实现方法,并且,进一步练习了规范的代码编写格式。
此外,还熟悉了之前不是十分理解的结构体赋值方式,即
tDataNode head[] =
{
{"help", "this is help cmd.", help, &head[1]},
{"read", "this is read cmd.", read, &head[2]},
{"write", "this is write cmd", write, &head[3]},
{"get", "this is get cmd", get, &head[4]},
{"pull", "this is pull cmd", pull, &head[5]},
{"push", "this is push cmd", push, &head[6]},
{"compare", "this is compare cmd", compare, &head[7]},
{"put", "this is put cmd", put, &head[8]},
{"quit", "this is quit cmd", quit, NULL}
};