您的位置:首页 > 移动开发 > 微信开发

实验三:内部模块化的命令行菜单小程序V2.0

2017-10-09 10:51 465 查看

实验三:内部模块化的命令行菜单小程序V2.0

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

【代码仓库】https://github.com/shawn520/SE.git

GitHub代码链接

实验要求

注意代码的业务逻辑和数据存储之间的分离,即将系统抽象为两个层级:

菜单业务逻辑和菜单数据存储

要求:

1)遵守代码风格规范,参考借鉴代码设计规范的一些方法;

2)代码的业务逻辑和数据存储使用不同的源文件实现,即应该有2个.c和一个.h作为接口文件。

实验目的

通过设计简单的命令行菜单细小程序,了解并掌握程序内部模块化设计的思想,实现菜单数据存储与菜单业务逻辑的分离.

实验思路

用一个静态链表来存储可变化的菜单命令及其对应函数,在主函数中实菜单命令逻辑

将数据结构的定义、函数声明放到linklist.h中,声明的函数在linklist.c中实现,在menu.c中定义main函数。共实验help、quit、version、四则运算arithmetic、输出当前系统时间time、判断两个数的大小judge、求一个数的倒数、给一列数排序。

实验过程

在一个头文件中定义链表数据结构及其操作原型,并在相应源文件中实现其操作;然后在主函数源文件中实现菜单命令。

进入实验目录并创建menu.c作为业务逻辑模块

git clone https://github.com/shawn520/SE.git mkdir lab3
cd lab3
vim menu.c


在menu.c中添加如下代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "linklist.h"

#define CMD_MAX_LEN 128
#define DESC_LEN 1024
#define CMD_NUM 10

/*menu program*/

static tDataNode head[] =
{
{"help", "this is help cmd!", Help, &head[1]},
{"version", "menu program v2.0", NULL, &head[2]},

4000
{"quit", "Quit from menu", Quit, &head[3]},
{"add", "Addtion", Add, &head[4]},
{"sub", "Substraction", Sub, &head[5]},
{"Mul", "Multition", Mul, &head[6]},
{"Div", "Division", Div, NULL}
};

int Hello()
{
printf("Hi~My name is Shawn.\nThank you for use my cmd prgram!\n");

}

int main()
{

/* cmd line begins */
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;
}


编辑linklist.h,作为数据存储模块,增加可重用性

vim linklist.h


/**************************************************************************/
/* Copyright (C) mc2lab.com, SSE@USTC, 2017-2018                          */
/*                                                                        */
/*  FILE NAME                   :   menu.c                                */
/*  PRINCIPAL AUTHOR            :   ShawnLiu                              */
/*  SUBSYSTEM NAME              :   menu                                  */
/*  MODULE NAME                 :   menu                                  */
/*  LANGUAGE                    :   C                                     */
/*  TARGET ENVIRONMENT          :   ANY                                   */
/*  DATE OF FIRST RELEASE       :   2017/10/07                            */
/*  DESCRIPTION                 :   This is a menu program                */
/**************************************************************************/

/*
* Revision log:
*
* Created by ShawnLiu, 2017/10/07
*
*/

/* 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);

/* show all cmd in listlist*/
int ShowAllCmd(tDataNode * head);

int Help();
int Quit();
int Add();
int Sub();
int Mul();
int Div();


再定义存储所有cmd的linklist数据结构, 并声明其操作方法FindCmd(), 以及遍历输出linklist中所有节点的ShowAllCmd():

vim linklist.c


#include <stdio.h>
#include <stdlib.h>
#include <string.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 Quit()
{
exit(0);
}

int Add()
{
double num1, num2;
double sum;
printf("Addtion. Please input two numbers:\n");
scanf("%lf %lf", &num1, &num2 );
sum = num1 + num2;
printf("%lf + %lf = %lf\n", num1, num2, sum);
return 0;
}

int Sub()
{
double num1, num2;
double result;
printf("Subtraction. Please input two numbers:\n");
scanf("%lf %lf", &num1, &num2 );
result = num1 - num2;
printf("%lf - %lf = %lf\n", num1, num2, result);
}

int Mul()
{
double num1, num2;
double result;
printf("Multiplication. Please input two numbers:\n");
scanf("%lf %lf", &num1, &num2 );
result = num1 * num2;
printf("%lf * %lf = %lf\n", num1, num2, result);
}

int Div()
{
int num1, num2;
double result;
printf("Division. Please input two numbers:\n");
scanf("%d %d", &num1, &num2 );
if(num2==0)
{
printf("Error: divisor can not be zero!\n");
}
else
{
result = num1 / num2;
printf("%d / %d = %lf\n", num1, num2, result);
}
}


编译得到可执行文件

gcc menu.c linklist.c -o menu


并测试menu程序的功能,如图所示



完成后提交到git

git add menu.c linklist.h linklist.c
git commit -m 'menu_v2.0'
git push




复审实验

本实验的代码可通过如下方式下载并运行

git clone https://github.com/shawn520/SE.git cd lab3
gcc menu.c linklist.c -o menu
./menu


实验心得及体会:

软件=程序+软件工程

程序=算法+数据结构

经过基本Modularity (also called separation of concerns)设计的代码

模块化的思想和命令行菜单的实现范例(开源社区中常见的写法)

基本模块化的写法

代码设计中的一些常见方法

KISS(keep it simple & stupid)

using design to frame the code(matching design with implementation)

including pseuducode

不要和陌生人说话原则

合理利用Control Structures、Data Structures来简化代码

一定要有错误处理
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: