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

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

代码地址: http://git.shiyanlou.com/csxiaoyao/shiyanlou_cs122/src/master

1. 实验要求

  1. 用可重用的链表模块来实现命令行菜单小程序,执行某个命令时调用一个特定的函数作为执行动作
  2. 链表模块的接口设计要足够通用,命令行菜单小程序的功能保持不变
  3. 可以将通用的Linktable模块集成到menu程序中
  4. 接口规范

2. 实验思路

创建目录 lab4,定义 menu.c, linktable.c, linktable.h, testlinktable.c 四个文件,将通用的 Linktable 模块集成到 menu 程序中

3. 实验过程

在lab4中创建 linktable.hlinktable.cmenu.c 文件并编辑,实验代码如下:

3.1 linktable.h

#ifndef _LINK_TABLE_H_
#define _LINK_TABLE_H_
#define SUCCESS 0
#define FAILURE (-1)

typedef struct LinkTableNode
{
     struct LinkTableNode * pNext;
} tLinkTableNode;
typedef struct LinkTable
{
    tLinkTableNode *pHead;
    tLinkTableNode *pTail;
    int SumOfNode;
} tLinkTable;
// Create a LinkTable
tLinkTable * CreateLinkTable();
// Delete a LinkTable
int DeleteLinkTable(tLinkTable *pLinkTable);
// Add a LinktableNode to Linktable
int AddLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode *pNode);
// Delete a LinktableNode from Linktable
int DelLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode *pNode);
// Get LinktableHead
tLinkTableNode *GetLinkTableHead(tLinkTable *pLinkTable);
// Get next LinktableNode
tLinkTableNode *GetNextLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode *pNode);

#endif // _LINK_TABLE_H_

3.2 linktable.c

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

tLinkTable *CreateLinkTable()
{
    tLinkTable *pLinkTable = (tLinkTable*)malloc(sizeof(tLinkTable));
    if(pLinkTable == NULL)
    {
        return NULL;
    }
    pLinkTable->pHead = NULL;
    pLinkTable->pTail = NULL;
    pLinkTable->SumOfNode = 0;
    return pLinkTable;
}

int DeleteLinkTable(tLinkTable *pLinkTable)
{
    if(pLinkTable == NULL)
    {
        return FAILURE;
    }
    while(pLinkTable->pHead != NULL)
    {
        tLinkTableNode *tmp = pLinkTable->pHead;
        pLinkTable->pHead = pLinkTable->pHead->pNext;
        free(tmp);
    }
    pLinkTable->pHead = NULL;
    pLinkTable->pTail = NULL;
    pLinkTable->SumOfNode = -1;
    free(pLinkTable);
    return SUCCESS;
}

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

int DelLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode *pNode)
{
    if(pLinkTable == NULL ||pNode == NULL)
    {
        return FAILURE;
    }
    if(pLinkTable->pHead == pNode)
    {
        tLinkTableNode *tmp = pLinkTable->pHead;
        pLinkTable->pHead = pLinkTable->pHead->pNext;
        free(tmp);
        pLinkTable->SumOfNode--;
    }
    if(pLinkTable->SumOfNode == 0)
    {
        pLinkTable->pTail = NULL;
        return FAILURE;
    }
    tLinkTableNode *tmp = pLinkTable->pHead;
    while(tmp != NULL)
    {
        if(tmp->pNext == pNode)
        {
            tmp->pNext = pNode ->pNext;
            pLinkTable->SumOfNode --;
            if(pLinkTable->SumOfNode == 0)
            {
                pLinkTable->pTail = NULL;
            }
            return SUCCESS;
        }
        tmp = tmp->pNext;
    }
    return FAILURE;
}

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

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

3.3 menu.c

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

#define CMD_MAX_LEN 128
#define CMD_DESC_LEN 1024
#define CMD_NUM 10

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

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

int Help();
int Quit();
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;
}

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 = "version";
    pNode->desc = "Menu Program V1.0";
    pNode->handler = NULL;
    AddLinkTableNode(*ppLinkTable,(tLinkTableNode *)pNode);
    pNode = (tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd = "quit";
    pNode->desc = "Quit from Menu Program V1.0";
    pNode->handler = Quit;
    AddLinkTableNode(*ppLinkTable,(tLinkTableNode *)pNode);
    return 0;
}

tLinkTable *head = NULL;
int main()
{
    InitMenuData(&head);
    char cmd[CMD_MAX_LEN];
    while(1)
    {
        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();
        }
    }
    return 0;
}

int Help()
{
    ShowAllCmd(head);
    return 0;
}
int Quit()
{
    exit(0);
    return 0;
}

4. 运行结果

图片描述

5. 实验总结

这次实验复习了对链表的操作,对可重用的理解得到进一步提升

最新评论