实验三:内部模块化的命令行菜单小程序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来简化代码
一定要有错误处理
相关文章推荐
- 实验报告三:内部模块化的命令行菜单小程序V2.0
- 实验三:内部模块化的命令行菜单小程序V2.0
- 实验三:内部模块化的命令行菜单小程序V2.0
- 实验报告三:内部模块化的命令行菜单小程序V2.0
- [高级软件工程实验]内部模块化的命令行菜单小程序V2.0
- 文章标题 实验三:内部模块化的命令行菜单小程序V2.0
- “软件工程(C编码实践篇)”实验报告【实验三:内部模块化的命令行菜单小程序V2.0】
- 实验三:内部模块化的命令行菜单小程序V2.0
- 实验三:内部模块化的命令行菜单小程序V2.0
- 实验三:内部模块化的命令行菜单小程序V2.0
- 内部模块化的命令行菜单小程序
- 软件工程(C编码实践篇) 实验三:内部模块化的命令行菜单
- 文章标题 实验四:用可重用的链表模块来实现命令行菜单小程序V2.5
- 实验四:用可重用的链表模块来实现命令行菜单小程序V2.5
- [高级软件工程实验]用可重用的链表模块来实现命令行菜单小程序V2.5
- 命令行菜单小程序v2.0
- 实验四:用可重用的链表模块来实现命令行菜单小程序V2.5
- 实验四:用可重用的链表模块来实现命令行菜单小程序
- 实验五:用callback增强链表模块来实现命令行菜单小程序V2.8
- 实验二:命令行菜单小程序V1.0