学习之路——内部模块化的命令行菜单 V1.1

【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

github:
https://github.com/zhanghughsw/zswlab.git

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值