实验四:用可重用的链表模块来实现命令行菜单小程序V2.5

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

实验要求

  1. 用可重用的链表模块来实现命令行菜单小程序,执行某个命令时调用一个特定的函数作为执行动作;

  2. 链表模块的接口设计要足够通用,命令行菜单小程序的功能保持不变;

  3. 可以将通用的Linktable模块集成到我们的menu程序中;

  4. 接口规范;

实验过程

进入实验目录

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

menu.c中添加如下代码

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

#define     FILEPATH_MAX          80
#define     CMD_MAX_LENGTH         128

void help();        
void quit();

typedef struct DataNode
{
    tLinkTableNode *pNext;
    char *cmd;
    char *desc;
    void (*handler)();
}tDataNode;

char cwdbuff[64] = {0};
char cwdbuffsub[64] = {0};
//declare a tLinkTable


tLinkTable *head = NULL;
//find the command
tDataNode *FindCmd(tLinkTable *head, char *cmd)
{
    tDataNode *pNode = (tDataNode *)GetLinkTableHead(head);
    while (pNode != NULL)
    {
        if (strcmp(pNode->cmd, cmd) == 0)
        {
            return pNode;
        }
        pNode = (tDataNode *)GetNextLinkTableNode(head, (tLinkTableNode *)pNode);
    }
    return NULL;
}
//show the desc
int ShowAllCmd(tLinkTable *head)
{
    tDataNode *pNode = (tDataNode *)GetLinkTableHead(head);
    while (pNode != NULL)
    {
        printf("%s - %s\n", pNode->cmd, pNode->desc);
        pNode = (tDataNode *)GetNextLinkTableNode(head, (tLinkTableNode *)pNode);
    }
    return 0;
}
//init
int InitMenuData(tLinkTable **ppLinktable)
{
    *ppLinktable = CreateLinkTable();

    tDataNode *pNode = (tDataNode *)malloc(sizeof(tDataNode));
    pNode->cmd = "help";
    pNode->desc = "This is help command.";
    pNode->handler = help;
    AddLinkTableNode(*ppLinktable, (tLinkTableNode *)pNode);

    pNode = (tDataNode *)malloc(sizeof(tDataNode));
    pNode->cmd = "quit";
    pNode->desc = "quit the command line.";
    pNode->handler = quit;
    AddLinkTableNode(*ppLinktable, (tLinkTableNode *)pNode);
    return 0;
}

int main ()
{
    char getCommand[CMD_MAX_LENGTH];
    InitMenuData(&head);
    while(1)
    {
        printf("Please Input Command: ");
        scanf("%s",getCommand);
        tDataNode *p = FindCmd(head,getCommand);
        if(p == NULL)
        {
            printf("error: Wrong Command!!\n");        
        }
        else
        {
            p -> handler();
        }
    }
    return 0;
}

//show commmand imformation
void help()
{
    ShowAllCmd(head);
}

//exit
void quit()
{
    exit(0);
}

编辑linktable.h

#ifndef __LINK_TABLE_H__
#define __LINK_TABLE_H__

#include<pthread.h>

#define SUCCESS 0
#define FAILURE (-1)

//LinkTable Node Type

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

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

//Create a LinkTable
tLinkTable *CreateLinkTable();

//Delete LinkTable
int DeleteLinkTable(tLinkTable *pLinkTable);

//Add CMD
int AddLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode *pNode);

//Delete CMD
int DelLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode *pNode);

//Get LinkTableHead
tLinkTableNode *GetLinkTableHead(tLinkTable *pLinkTable);

//Get nextLinkTableNode
tLinkTableNode *GetNextLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode *pNode);

#endif

编辑 linktable.c

#include <stdio.h>
#include <stdlib.h>
#include "linktable.h"

#define SUCCESS 0
#define FAILURE (-1)

tLinkTable *CreateLinkTable()
{
    tLinkTable *pLinkTable = (tLinkTable *)malloc(sizeof(tLinkTable));
    if (pLinkTable == NULL)
    {
        printf("malloc error!\n");
        return NULL;
    }
    pLinkTable->pHead = NULL;
    pLinkTable->pTail = NULL;
    pLinkTable->SumOfNode = 0;
    pthread_mutex_init(&(pLinkTable->mutex), NULL);
    return pLinkTable;
}

int DeleteLinkTable(tLinkTable *pLinkTable)
{
    if (pLinkTable == NULL)
    {
        return SUCCESS;
    }
    while (pLinkTable->pHead != NULL)
    {
        tLinkTableNode *pNode = pLinkTable->pHead;
        pLinkTable->pHead = pNode->pNext;
        free(pNode);
    }
    free(pLinkTable);
    return SUCCESS;
}

int AddLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode *pNode)
{
    if (pLinkTable == NULL || pNode == NULL)
    {
        printf("AddLinkTableNode error!\n");
        return FAILURE;
    }
    pNode->pNext = NULL;
    if (pLinkTable->pHead == NULL)
    {
        pLinkTable->pHead = pNode;
        pLinkTable->pTail = pNode;
        pLinkTable->SumOfNode += 1;
    }
    else
    {
        pLinkTable->pTail->pNext = pNode;
        pLinkTable->pTail = pNode;
        pLinkTable->SumOfNode += 1;
    }
    return SUCCESS;
}

int DelLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode *pNode)
{
    if (pLinkTable == NULL || pNode == NULL)
    {
        printf("DelLinkTableNode error!\n");
        return FAILURE;
    }
    tLinkTableNode *pFront = pLinkTable->pHead;
    if (pFront == NULL)
    {
        printf("pLinkTable is NULL!\n");
        return FAILURE;
    }
    else if (pFront == pNode)
    {
        pLinkTable->pHead = pFront->pNext;
        free(pFront);
        return SUCCESS;
    }
    tLinkTableNode *pBack = pFront;
    pFront = pFront->pNext;
    while (pFront != NULL)
    {
        if (pFront == pNode)
        {
            pBack->pNext = pFront->pNext;
            free(pFront);
            return SUCCESS;
        }
        pFront = pFront->pNext;
        pBack = pBack->pNext;
    }
    printf("not find error!\n");
    return FAILURE;
}

tLinkTableNode *GetLinkTableHead(tLinkTable *pLinkTable)
{
    if (pLinkTable == NULL)
    {
        return NULL;
    }
    return pLinkTable->pHead;
}

tLinkTableNode *GetNextLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode *pNode)
{
    if (pLinkTable == NULL || pNode == NULL)
    {
        return NULL;
    }
    tLinkTableNode *p = pLinkTable->pHead;
    if (p == NULL)
    {
        return NULL;
    }
    while (p != NULL)
    {
        if (p == pNode)
        {
            return p->pNext;
        }
        p = p->pNext;
    }
    return NULL;
}

编译得到可执行文件

gcc linktable.c menu.c -o menu

并测试menu程序的功能,如图所示
这里写图片描述

完成后提交到git

git add  linktable.c linktable.h menu.c 
git commit -m 'menu_v2.5'
git push

这里写图片描述

实验心得及体会:

实验越来越难了。

通用Linktable模块的接口设计
将通用的Linktable模块集成到我们的menu程序中
定义接口 - “天王盖地虎,宝塔镇河妖”黑社会接头也设计接口的!

  • 接口规范
  • 内聚和耦合
  • 通用原则

通用链表模块的接口设计

模块化的好处:包容变化

将通用的LinkTable集成到我们的menu程序中

本地化外部接口(Localize input and output)

欢迎大家访问我的——

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值