首页 > 程序开发 > 软件开发 > C语言 >

软件工程:C编码实践篇学习总结

2017-10-10

软件工程:C编码实践篇学习总结。实验要求:用可重用的链表模块来实现命令行菜单小程序,执行某个命令时调用一个特定的函数作为执行动作; 链表模块的接口设计要足够通用,命令行菜单小程序的功能保持不变; 可以将通用的Linktable模块集成到我们的menu程序中;

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

实验要求

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

实验过程

1.建立远程仓库,并下载到本地

git clone https://github.com/libaoquan95/seClass_lab4.git

并进入版本库并创建 menu.c linktable.h linktable.c 文件
这里写图片描述

2 linktable.h

#ifndef _LINK_TABLE_H_
#define _LINK_TABLE_H_

#include 
#define  SUCCESS 0
#define  FAILURE (-1)

/*
 * LinkTableNode Node Type
 */
typedef struct LinkTableNode
{
    struct LinkTableNode *pNext;
}tLinkTableNode;

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

tLinkTable * CreateLinkTable();
int          DelLinkTable(tLinkTable* pLinkTable);
int          AddLinkTable(tLinkTable* pLinkTable,tLinkTableNode *pNode);
int          DelLinkTableNode(tLinkTable* pLinkTable,tLinkTableNode *pNode);
tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable);
tLinkTableNode * GetNextLinkTableNode(tLinkTable* pLinkTable,tLinkTableNode *pNode);
#endif

3 linktable.c

#include 
#include 
#include 
#include "linktable.h"

tLinkTable * CreateLinkTable()
{
    tLinkTable *pLinkTable=(tLinkTable*)malloc(sizeof(tLinkTable));
    if (pLinkTable == NULL)
    {
        return NULL;
        printf("create linktable failure! ");
    }
    pLinkTable->pHead = NULL;
    pLinkTable->pTail = NULL;
    pLinkTable->SumOfNode = 0;
    return pLinkTable;
}

int DelLinkTable(tLinkTable* pLinkTable)
{
    if(pLinkTable == NULL)
    {
        return FAILURE;
    }

    while(pLinkTable->pHead != NULL)
    {
        tLinkTableNode *p = pLinkTable->pHead;
        pLinkTable->pHead = p->pNext;
        free(p);
    }

    pLinkTable->pHead = NULL;
    pLinkTable->pTail = NULL;
    pLinkTable->SumOfNode = 0;
    free(pLinkTable);
    return SUCCESS;
}

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

int DelLinkTableNode(tLinkTable* pLinkTable,tLinkTableNode *pNode)
{
    if (pLinkTable == NULL)
    {
        return FAILURE;
    }
    tLinkTableNode *pWork = pLinkTable->pHead;
    tLinkTableNode *pre = pWork;

    if (pLinkTable->pHead == pNode)
    {
        pLinkTable->pHead = pWork->pNext;
        free(pWork);
        return SUCCESS;
    }

    while (pWork != NULL)
    {
        if(pWork == pNode)
        {
            pre->pNext = pWork->pNext;
            free(pWork);
            return SUCCESS;
        }
        pre = pWork;
        pWork = pWork->pNext;
    }

    return FAILURE;
}

tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable)
{
    if (pLinkTable->pHead == NULL)
    {
        printf("LinkTable is empty\n");
        return NULL;
    }
    return pLinkTable->pHead;
}

tLinkTableNode * GetNextLinkTableNode(tLinkTable* pLinkTable,tLinkTableNode *pNode)
{
    if (pLinkTable == NULL || pNode == NULL)
    {
        printf("LinkTable is empty\n");
        return NULL;
    }

    tLinkTableNode *pWork = pLinkTable->pHead;

    while(pWork != NULL)
    {
        if(pWork == pNode)
            return pWork->pNext;
        pWork = pWork->pNext;
    }

    return NULL;
}

4 menu.c

/*
 * Copyright (C) libaoquan95@github.com, 2017-2018
 *
 * File name                  : menu.c
 * Principal author           : libaoquan95
 * Subsystem name             : menu 
 * Module name                : menu
 * Language                   : C 
 * Date of first release      : 2017/10/09
 * Deacription                : This is a menu program
*/

#include 
#include 
#include 
#include 
#include 
#include "linktable.h"

#define CMD_MAX_LEN 128
#define DESC_LEN 1024
#define CMD_NUM 10

int PrintCommand();
int PrintSystemTime();
int PrintCurrentWorkingDirectory();
int Add();
int Sub();
int Mul();
int Div();
int Quit();

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 ShowAllCmd(tLinkTable *head)
{
    tDataNode *pNode = (tDataNode*)GetLinkTableHead(head);
    printf("-------------------------------------------------------------------\n");
    while(pNode != NULL)
    {
        printf("\t\t %s: \t\t %s\n", pNode->cmd, pNode->desc);
        pNode= (tDataNode*)GetNextLinkTableNode(head, (tLinkTableNode*)pNode);
    }
    printf("-------------------------------------------------------------------\n");
    return 0;
}

static tDataNode menu[] =
{
    {(tLinkTableNode*)&menu[1], "help", "Print all command of menu",                  PrintCommand},
    {(tLinkTableNode*)&menu[2], "time", "Show system time",                           PrintSystemTime},
    {(tLinkTableNode*)&menu[3], "pwd", "Show current working directory",              PrintCurrentWorkingDirectory},
    {(tLinkTableNode*)&menu[4], "add", "Calculate the summarize of the two integer numbers",      Add},
    {(tLinkTableNode*)&menu[5], "sub", "Calculate the subtractions of the two integer numbers",   Sub},
    {(tLinkTableNode*)&menu[6], "mul", "Calculate the multiplication of the two integer numbers", Mul},
    {(tLinkTableNode*)&menu[7], "div", "Calculate the division of the two integer numbers",       Div},
    {(tLinkTableNode*)NULL,     "quit", "Exit menu program",                         Quit}
};

int InitMenuData(tLinkTable **ppLinkTable)
{
    *ppLinkTable = CreateLinkTable();
    (*ppLinkTable)->pHead = (tLinkTableNode*)&menu[0];
    (*ppLinkTable)->pTail = (tLinkTableNode*)&menu[7];
    (*ppLinkTable)->SumOfNode = 8;
}

tLinkTable *head = NULL;

int main()
{
    InitMenuData(&head);
    while(1)
    {
        char cmd[CMD_MAX_LEN];
        printf("$menu > ");
        scanf("%s", cmd);
        tDataNode *p = FindCmd(head, cmd);
        if(p == NULL)
        {
            printf("ERROR: This is not a command, you can input 'help' to find command\n");
            continue;
        }
        if(p->handler != NULL)
        {
            p->handler();
        }
    }
}

/**
 * print all command and it's information
 * @param none
 * @return none
 */
int PrintCommand()
{
    ShowAllCmd(head);
    return 0;
}

/**
 * print current time
 * @param none
 * @return none
 */
int PrintSystemTime()
{
    struct tm *ptr;
    time_t it;
    it = time(NULL);
    ptr = localtime(&it);
    printf("%4d年%02d月%02d日  %d:%d:%d\n", ptr->tm_year + 1900, ptr->tm_mon + 1, ptr->tm_mday, 
                                          ptr->tm_hour, ptr->tm_min,ptr->tm_sec);
    return 0;
}

/**
 * print current working directory path
 * @param none
 * @return none
 */
int PrintCurrentWorkingDirectory()
{
    char buf[256];
    getcwd(buf, sizeof(buf));
    printf("当前路径:  %s\n", buf);
    return 0;
}

/**
 * calculate add of two interage numbers
 * @param none
 * @return calculate result
 */
 int Add()
 {
     int num1 = 0, num2 = 0;
     printf("input number1:");
     scanf("%d", &num1);
     printf("input number2:");
     scanf("%d", &num2);
     printf("%d + %d = %d\n", num1, num2, num1 + num2);
     return 0;
 }

 /**
  * calculate sub of two interage numbers
  * @param none
  * @return calculate result
  */
 int Sub()
 {
     int num1 = 0, num2 = 0;
     printf("input number1:");
     scanf("%d", &num1);
     printf("input number2:");
     scanf("%d", &num2);
     printf("%d - %d = %d\n", num1, num2, num1 - num2);
     return 0;
 }

 /**
  * calculate mul of two interage numbers
  * @param none
  * @return calculate result
  */
 int Mul()
 {
     int num1 = 0, num2 = 0;
     printf("input number1:");
     scanf("%d", &num1);
     printf("input number2:");
     scanf("%d", &num2);
     printf("%d * %d = %d\n", num1, num2, num1 * num2);
     return 0;
 }

 /**
  * calculate div of two interage numbers
  * @param none
  * @return calculate result
  */
 int Div()
 {

     int num1 = 0, num2 = 0;
     printf("input number1:");
     scanf("%d", &num1);
     printf("input number2:");
     scanf("%d", &num2);
     if(num2 != 0)
     {
         printf("%d / %d = %d\n", num1, num2, num1 / num2);
     }
     else
     {
         printf("ERROR: don't division 0\n");
     }
     return 0;
 }

 /**
  * quit command
  * @param none
  * @return none
  */
 int Quit()
 {
     exit(0);
     return 0;
 }

5.编译程序并运行
5.1 编译

gcc linktable.h linktable.c menu.c -o menu
./menu

这里写图片描述
5.2 运行
help 命令
这里写图片描述
time 命令
这里写图片描述
pwd 命令
这里写图片描述
add 命令
这里写图片描述
sub 命令
这里写图片描述
mul 命令
这里写图片描述
div 命令
这里写图片描述
错误的命令
这里写图片描述
quit 命令
这里写图片描述
6.上传至远程版本库
这里写图片描述


实验总结

通过这次菜单程序模块化设计使我学会了许多的软件工程思想,体会到了模块化的巨大作用

本次实验设计了一个通用的链表模块,在调用时指定了具体的数据类型,体现了高类聚低耦合的思想,接口更加规范,使我们的代码更具有通用性并且更容易管理。

在实验中体会到了函数接口规范对于可重用的重要性,以及代码设计规范的一些方法。在编译的过程中也学习了链接的相关知识,对gcc编译器有了进一步的理解.

相关文章
最新文章
热点推荐