学习之路——用可重用的链表模块来实现命令行菜单小程序V2.5

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

本文为网易云课堂课程《软件工程(C编码实践)》的实验报告,本次实验为在前几次实验(命令行菜单小程序)的基础上,将使用可重用链表模块来实现内部模块化。

附上一实验的链接:内部模块化的命令行菜单小程序V1.0

一.实验思路

本次实验的目的是将命令小程序使用可重用的链表模块来实现,可采用“文件柜”这种链表与数据相对独立的方式进行代码改写,改写过程中尽可能的保持原主函数不变,体现重用的意义。

附小程序功能列表:
- time:获取当前的日期与时间
- calculation:进行加减乘除四则运算
- notepad :在当前文件夹创建并使用vim打开一个文本文档*.txt
- version:打印程序的版本号
- mac : 打开文件管理器nautilus
- explore :打开浏览器
- help :列出所有指令及解释
- help :列出所有指令及解释


二、代码实现

和上一实验一样分三个文件来进行代码编写,分别为menu.c linktable.c linktable.h

在本文件中实现主函数的编写,主要功能是输入的cmd字符获取与匹配

void main()
{
    InitMenuData(&head);
    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;
        }
        if (strcmp(p->cmd, "help") != 0)
        {
            printf("%s - %s\n", p->cmd, p->desc);
        }
        if(p->handler != NULL)
        {
            p->handler();
        }
    }
}

值得注意的是,在前一实验中使用全局变量来存储指令,而在本实验中,重写为了使用指针列表进行指令数据的存储

int InitMenuData(tLinkTable ** ppLinktable)
{
    *ppLinktable = CreateLinkTable();
    tDataNode* pNode = (tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd = "help";
    pNode->desc = "Menu List:";
    pNode->handler = Help;
    AddLinkTableNode(*ppLinktable,(tLinkTableNode * )pNode);

    pNode = (tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd = "time";
    pNode->desc = "You can use this cmd to get the localtime!";
    pNode->handler = Time;
    AddLinkTableNode(*ppLinktable,(tLinkTableNode * )pNode);

    pNode = (tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd = "caculation";
    pNode->desc = "You can use this cmd to have a simple calculate";
    pNode->handler = Calculation;
    AddLinkTableNode(*ppLinktable,(tLinkTableNode * )pNode);

    pNode = (tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd = "notepad";
    pNode->desc = "You can use this cmd to open a note file by vim";
    pNode->handler = Notepad;
    AddLinkTableNode(*ppLinktable,(tLinkTableNode * )pNode);

    pNode = (tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd = "version";
    pNode->desc = "menu line v1.2 bu yiyu";
    pNode->handler = NULL;
    AddLinkTableNode(*ppLinktable,(tLinkTableNode * )pNode);

    pNode = (tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd = "mgc";
    pNode->desc = "You can use this cmd to open the File System";
    pNode->handler = Mgc;
    AddLinkTableNode(*ppLinktable,(tLinkTableNode * )pNode);

    pNode = (tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd = "explore";
    pNode->desc = "You can use this cmd to open the explore";
    pNode->handler = Explore;
    AddLinkTableNode(*ppLinktable,(tLinkTableNode * )pNode);

    pNode = (tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd = "quit";
    pNode->desc = "Quit the menu";
    pNode->handler = Quit;
    AddLinkTableNode(*ppLinktable,(tLinkTableNode * )pNode);

    return 0;
};

linktable.h

本文件用于编写链表以及链表节点的数据结构以及声明在其上的一系列操作

#define _LINK_TABLE_H_

#include <pthread.h>

#define SUCESS 0
#define FAILURE (-1)

typedef struct LinkTableNode
{
    struct LinkTableNOde * pNext;
}tLinkTableNode;

typedef struct LinkTable
{
    tLinkTableNode *pHead;
    tLinkTableNode *pTail;
    int SumOfNode;
    pthread_mutex_t mutex;
}tLinkTable;

tLinkTable * CreateLinkTable();

int DeleteLinkTable(tLinkTable *pLinkTable);

int AddLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);

int DelLinkTable(tLinkTable *pLinkTable,tLinkTableNode * pNode);

tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable);

tLinkTableNode * GetNextLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);

linktable.c

本文件具体定义了链表的各种操作以及指令所对应的操作
CreateTable()——创建链表

tLinkTable * CreateLinkTable()
{
    tLinkTable *p = (tLinkTable*)malloc(sizeof(tLinkTable));
    tLinkTableNode * pNode = (tLinkTableNode *)malloc(sizeof(tLinkTableNode));
    pNode->pNext = NULL;
    p->pHead = pNode;
    p->pTail = pNode;
    p->SumOfNode = 0;
    return p;
}

AddLinkTableNode()——以头插的方式将节点插入链表

int AddLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode * pNode) 
{
    if (pLinkTable->SumOfNode == 0)
    {
        pNode->pNext = NULL;
        pLinkTable->pTail = pNode;
        pLinkTable->pHead = pNode;
        pLinkTable->SumOfNode += 1;
        return 1;
    }
    pNode->pNext = pLinkTable->pHead;
    pLinkTable->pHead = pNode;

    pLinkTable->SumOfNode ++;

    return 0;
}

GetLinkTableHead()——返回头结点

tLinkTableNode * GetNextLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode * pNode)
{
    return pNode->pNext;
}

GetNextLinkTableNode()——返回下一节点

tLinkTableNode * GetNextLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode * pNode)
{
    return pNode->pNext;
}

以及各项指令的功能函数

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;
}

三、实验总结

本次实验是收获巨大的,让我认识了可重用的链表模块,同时在实验过程中,巩固了链表的相关知识,特别是链表的插入、遍历等方面

复审代码
通过如下命令可以从Git版本库中拉取代码并编译运行

git clone https://github.com/zhanghughsw/zswlab.git
cd zswlab
cd lab4
gcc menu.c linktable.c -o menu
./menu

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

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值