软件工程课程实验报告:实验四

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

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

新创建一个目录lab4完成实验。


一、实验要求

  • 用可重用的链表模块来实现命令行菜单小程序,执行某个命令时调用一个特定的函数作为执行动作;
  • 链表模块的接口设计要足够通用,命令行菜单小程序的功能保持不变;
  • 可以将通用的Linktable模块集成到我们的menu程序中;
  • 接口规范;
  • 及时提交代码以防丢失

二、实验过程

1. 创建lab4文件夹

软件工程课程实验报告:实验四_第1张图片

2. 编写程序
  • linkable.h
// 防止重复定义
#ifndef _LINK_TABLE_H_
#define _LINK_TABLE_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;
} tLinkTable;

// Interface
// Create a LinkTable
tLinkTable * CreateLinkTable();

// Delete
int DeleteLinkTable(tLinkTable *pLinkTable);

// Add a Node to LinkTable
int AddLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode * pNode);

// Delete a Node 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_
  • linkable.c
#include <stdio.h>
#include <stdlib.h>
#include "linkable.h"

// Create a LinkTable
tLinkTable * CreateLinkTable()
{
    tLinkTable *pTable = (tLinkTable*)malloc(sizeof(tLinkTable));
    pTable->pHead = NULL;
    pTable->pTail = NULL;
    pTable->SumOfNode = 0;
    return pTable;
}

// Delete
int DeleteLinkTable(tLinkTable *pLinkTable)
{
    free(pLinkTable);
    return 0;
}

// Add a Node to LinkTable
int AddLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode * pNode)
{
    if (pLinkTable == NULL)
    {
        printf("The table is empty!\n");
        exit(0);
    }
    if (pNode == NULL)
    {
        printf("The node is empty!\n");
        return 0;
    }
    if (pLinkTable->pHead == NULL)
    {
        pLinkTable->pHead = pNode;
        pLinkTable->pTail = pNode;
        pLinkTable->pTail->pNext = NULL;
        pLinkTable->SumOfNode = 1;
    }
    else
    {
        pLinkTable->pTail->pNext = pNode;
        pLinkTable->pTail = pNode;
        pLinkTable->pTail->pNext = NULL;
        pLinkTable->SumOfNode++;
    }
    return 0;
}

// Get LinkTableHead
tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable)
{
    if (pLinkTable == NULL)
    {
        printf("The table is empty!\n");
        exit(0);
    }
    return pLinkTable->pHead;
}

// Get next LinkTableNode
tLinkTableNode * GetNextLinkTableNode(tLinkTable *pLinkTable, tLinkTableNode * pNode)
{
    if (pLinkTable == NULL)
    {
        printf("The table is empty!\n");
        exit(0);
    }
    if (pNode == NULL)
    {
        printf("The node is empty!\n");
        exit(0);
    }
    return pNode->pNext;
}
  • menu.c
    主程序如下:
int main ()
{
    InitMenuData(&head);
    info();
    printf("Plesea input a command:\n");
    while(1)
    {
        char cmd[CMD_MAX_LEN];
        printf(">>>");
        scanf("%s",cmd);
        tDataNode *p = FindCmd(head,cmd);
        if (p == NULL)
        {
            printf("Error: Wrong command!\n");
            printf("Type 'info' for available commands.\n");
            continue;
        }
        printf("%s - %s\n", p->cmd, p->desc);
        if (p->handler != NULL)
        {
            p->handler();
        }
     }
    return 0;
}

集成在menu.c中的linktable:

#define CMD_MAX_LEN 128
#define DESC_LEN 1024
#define CMD_NUM 20
//定义命令结构体
typedef struct DataNode
{
    tLinkTableNode *pNext;
    char* cmd;                  //commands
    char* desc;                 //Descriptions of commands
    int (*handler)();
    struct DataNode *next;
}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 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="info";
    pNode->desc="Command Informations";
    pNode->handler=info;
    AddLinkTableNode(*ppLinkTable,(tLinkTableNode *)pNode);
    pNode=(tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd="quit";
    pNode->desc="close this program";
    pNode->handler=quit;
    AddLinkTableNode(*ppLinkTable,(tLinkTableNode *)pNode);
    pNode=(tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd="plus";
    pNode->desc="result of a + b";
    pNode->handler=plus;
    AddLinkTableNode(*ppLinkTable,(tLinkTableNode *)pNode);
    pNode=(tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd="minus";
    pNode->desc="result of a - b";
    pNode->handler=minus;
    AddLinkTableNode(*ppLinkTable,(tLinkTableNode *)pNode);
    pNode=(tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd="multiply";
    pNode->desc="result of a * b";
    pNode->handler=multiply;
    AddLinkTableNode(*ppLinkTable,(tLinkTableNode *)pNode);
    pNode=(tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd="divide";
    pNode->desc="result of a / b";
    pNode->handler=divide;
    AddLinkTableNode(*ppLinkTable,(tLinkTableNode *)pNode);
    pNode=(tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd="power";
    pNode->desc="result of a ^ b";
    pNode->handler=power;
    AddLinkTableNode(*ppLinkTable,(tLinkTableNode *)pNode);
    pNode=(tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd="square";
    pNode->desc="result of the square root of a";
    pNode->handler=square;
    AddLinkTableNode(*ppLinkTable,(tLinkTableNode *)pNode);
    pNode=(tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd="factorial";
    pNode->desc="result of a!";
    pNode->handler=factorial;
    AddLinkTableNode(*ppLinkTable,(tLinkTableNode *)pNode);
    pNode=(tDataNode*)malloc(sizeof(tDataNode));
    pNode->cmd="absolute";
    pNode->desc="result of |a|";
    pNode->handler=absolute;
    AddLinkTableNode(*ppLinkTable,(tLinkTableNode *)pNode);
    return 0;
}
tLinkTable* head=NULL;

菜单命令包括以下9种:
- 介绍命令信息info()
- 加法运算plus()
- 减法运算minus()
- 乘法运算multiply()
- 除法运算divide()
- 幂运算power()
- 平方根运算square()
- 阶乘运算factorial()
- 绝对值运算absolute()
- 退出quit()
限制于报告篇幅,以上命令的具体实现代码就不在文中贴出,烦请移步github工程中查看。

https://github.com/973301529/se/tree/master/lab4

3. 编译执行
  • 初始运行情况,info()介绍可用指令的相关信息
    软件工程课程实验报告:实验四_第2张图片
  • 检测info()、plus()、power()、factorial()、absolute()、quit()等指令的运行情况
    软件工程课程实验报告:实验四_第3张图片
4. 将代码同步到github

软件工程课程实验报告:实验四_第4张图片

三、实验总结

本次实验在上次实验的基础上更进一步,对可重用的链表模块来实现命令行菜单小程序进行实验,更加熟悉了链表的相关知识,并学习了链表模块的接口设计,初步了解了接口设计。在此次实验中,也感受到了自己在链表设计中的不足,以后的学习中会更加注重链表的学习。

你可能感兴趣的:(软件工程实验报告)