【zhanghughsw + 《软件工程(C编码实践篇)》MOOC课程作业http://mooc.study.163.com/course/USTC-1000002006 】
本文为网易云课堂课程《软件工程(C编码实践)》的实验报告,本次实验为在上一实验(命令行菜单小程序)的基础上,将代码实现内部模块化。
附上一实验的链接:命令行菜单小程序V1.0
一、实验思路
要实现代码的内部模块化,最重要的是做好“区分”工作,在将操作函数化的前提下,实现数据与操作的分离,在本次实验中应该针对本命令行菜单所涉及的各种功能,逐一实现函数化,而后实现内部模块化。
以下为程序所涉及的功能:
- time:获取当前的日期与时间
- calculation:进行加减乘除四则运算
- notepad :在当前文件夹创建并使用vim打开一个文本文档*.txt
- version:打印程序的版本号
- mac : 打开文件管理器nautilus
- explore :打开浏览器
- help :列出所有指令及解释
- quit :退出程序
二、实验步骤
1.函数化各功能代码
int Time()
{
time_t now;
struct tm *tm_now;
time(&now);
tm_now = localtime(&now);
printf("now datetime:%d-%d-%d %d:%d:%d\n",tm_now->tm_year+1900,tm_now->tm_mon+1,tm_now->tm_mday,tm_now->tm_hour,tm_now->tm_min,tm_now->tm_sec);
}
int Calculation()
{
char ch;
int num1,num2;
printf("which calculations: + - * /:");
scanf("%c",&ch);
while(1)
{
scanf("%c",&ch);
setbuf(stdin,NULL);
if(ch == 'Q')
{
return 1;
}
else if(ch != '+' && ch != '-' && ch != '*' && ch!= '/')
{
printf("Input Wrong!please input the one of '+','-','*','/'\n");
}
else
{
printf("You want to have a %c calculate,input the two number,separate by comma!\n",ch);
break;
}
}
scanf("%d,%d",&num1,&num2);
if(ch == '+')
{
printf("%d+%d=%d\n",num1,num2,num1 + num2);
}
else if(ch == '-')
{
printf("%d-%d=%d\n",num1,num2,num1 - num2);
}
else if(ch == '*')
{
printf("%d*%d=%d\n",num1,num2,num1 * num2);
}
else if(ch == '/')
{
printf("%d/%d=%f\n",num1,num2,(float)num1 / num2);
}
else
{
printf("Input Wrong!");
return -1;
}
return 0;
}
int Help()
{
printf("Menu List:\n");
tDataNode *p = head;
while(p != NULL)
{
printf("%s - %s\n",p->cmd, p->desc);
p = p->next;
}
return 0;
}
int Quit()
{
exit(0);
}
int Notepad()
{
system("touch ./*.txt");
system("vim ./*.txt");
return 0;
}
int Mgc()
{
system("nautilus");
return 0;
}
int Explore()
{
system("firefox");
return 0;
}
2.内部模块化代码
将代码分解为3个部分:
linklist.c——内含各功能代码
linklist.h——内含库函数及自定义数据结构
menu.c——主函数
各部分代码为
linklist.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "linklist.h"
tDataNode* FindCmd(tDataNode * head,char * cmd)
{
if(head == NULL || cmd == NULL)
{
return NULL;
}
tDataNode *p = head;
while(p != NULL)
{
if(strcmp(p->cmd, cmd) == 0)
{
return p;
}
p = p->next;
}
return NULL;
}
int ShowAllCmd(tDataNode * head)
{
printf("Menu List:\n");
tDataNode *p = head;
while(p != NULL)
{
printf("%s - %s\n",p->cmd, p->desc);
p = p->next;
}
return 0;
}
int Time()
{
time_t now;
struct tm *tm_now;
time(&now);
tm_now = localtime(&now);
printf("now datetime:%d-%d-%d %d:%d:%d\n",tm_now->tm_year+1900,tm_now->tm_mon+1,tm_now->tm_mday,tm_now->tm_hour,tm_now->tm_min,tm_now->tm_sec);
}
int Calculation()
{
char ch;
int num1,num2;
printf("which calculations: + - * /:");
scanf("%c",&ch);
while(1)
{
scanf("%c",&ch);
setbuf(stdin,NULL);
if(ch == 'Q')
{
return 1;
}
else if(ch != '+' && ch != '-' && ch != '*' && ch!= '/')
{
printf("Input Wrong!please input the one of '+','-','*','/'\n");
}
else
{
printf("You want to have a %c calculate,input the two number,separate by comma!\n",ch);
break;
}
}
scanf("%d,%d",&num1,&num2);
if(ch == '+')
{
printf("%d+%d=%d\n",num1,num2,num1 + num2);
}
else if(ch == '-')
{
printf("%d-%d=%d\n",num1,num2,num1 - num2);
}
else if(ch == '*')
{
printf("%d*%d=%d\n",num1,num2,num1 * num2);
}
else if(ch == '/')
{
printf("%d/%d=%f\n",num1,num2,(float)num1 / num2);
}
else
{
printf("Input Wrong!");
return -1;
}
return 0;
}
int Quit()
{
exit(0);
}
int Notepad()
{
system("touch ./*.txt");
system("vim ./*.txt");
return 0;
}
int Mgc()
{
system("nautilus");
return 0;
}
int Explore()
{
system("firefox");
return 0;
}
linklist.h
/*data struct and its operations*/
typedef struct DataNode
{
char* cmd;
char* desc;
int (*handler)();
struct DataNode *next;
}tDataNode;
/*find a cmd in the linklist and return the datanode pointer*/
tDataNode* FindCmd(tDataNode * head, char * cmd);
int ShowAllCmd(tDataNode * head);
menu.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "linklist.h"
#define CMD_MAX_LEN 128
#define DESC_LEN 1024
#define CMD_NUM 10
int Help();
int Time();
int Calculation();
int Notepad();
int Mgc();
int Explore();
int Quit();
static tDataNode head[] =
{
{"help","this is help cmd!",Help,&head[1]},
{"time","You can use this cmd to get the localtime!",Time,&head[2]},
{"calculation","You can use this cmd to have a simple calculate",Calculation,&head[3]},
{"notepad","You can use this cmd to open a nate file by vim",Notepad,&head[4]},
{"version","menu line v1.1 by yiyu",NULL,&head[5]},
{"mgc","You can use this cmd to open File System",Mgc,&head[6]},
{"explore","You can use this cmd to open explore",Explore,&head[7]},
{"quit","Quit the menu",Quit,NULL}
};
void main()
{
while(1)
{
char cmd[CMD_MAX_LEN];
printf("input a cmd number ->");
scanf("%s", cmd);
tDataNode *p = FindCmd(head, cmd);
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();
}
}
}
int Help()
{
ShowAllCmd(head);
return 0;
}
三、实验总结
本次课程是收获巨大的,让我意识到自己一直以来都是在“胡编乱造”代码,只是简单的实现代码所要求的功能,而未有考虑过其模块化,有了这一次实验,在以后的学习中,我将会更加注重除实现功能外的其他方面
复审代码
通过如下命令可以从Git版本库中拉取代码并编译运行
git clone https://github.com/zhanghughsw/zswlab.git
cd zswlab
cd lab3
gcc menu.c linklist.c -o menu
./menu