您的位置:首页 > 移动开发 > 微信开发

高级软件工程lab5-----用callback增强链表模块来实现命令行菜单小程序V2.8

2017-10-20 21:01 501 查看
高级软件工程lab5-----用callback增强链表模块来实现命令行菜单小程序V2.8

git地址:https://github.com/phny/lab5.git




实验步骤:

一,给lab5-1.tar.gz找bug,quit命令无法运行的bug。

1,首先将文件下载下来进行查看



编译项目并运行,发现quit命令确实是无法使用



于是仔细检查代码出现这一问题的原因,发现问题出现在linktable.c中的SearchLinkTableNode中,while循环条件while(pNode != pLinkTable -> pTail)使得函数在找到链表最后一个节点时即退出循环,因此无法访问最后一个节点.将while(pNode != pLinkTable
-> pTail)改为while(pNode != NULL)即可,修改后再次编译项目运行,我们发现quit命令已经可以正常使用。



运行修改后的项目:



二,利用callback函数参数使Linktable的查询接口更加通用

具体的代码如下所示:

menu.c代码:

/************************************************************************/

/*  Copyright(C) mclab.com SSE@USTC , 2017/10/20    */

/*  FILENAME
:menu.c     */

/*  PRINCIPAL AUTHOR:heyulin
    */

/*  SUBSYSTEM NAME:mene
    */

/*  MODULE NAME:menu
    */

/*  LANGUAGE
:C         */

/*  TARGET ENVIRONMENT:ANY
    */

/*  DATE OF FIRST RELEASE:2017/10/20
    */

/*  DESCRIPTION:This is a program 
    */ 
/************************************************************************/

#include <stdio.h>

#include <stdlib.h>

#include "linktable.h"

#define CMD_MAX_LEN 128

#define DESC_LEN    1024

#define CMD_NUM     10

void help();

void add();

void sub();

void max();

void min();

void ls();

void quit();

/* data struct and its operations */

typedef struct DataNode

{

    tLinkTableNode* pNext;

    char*   cmd;

    char*   desc;

    int     (*handler)();

} tDataNode;

int SearchCondition(tLinkTableNode* pLinkTableNode, void* args)

{

    char *cmd = (char*)args;

    tDataNode * pNode = (tDataNode *)pLinkTableNode;

    if(strcmp(pNode->cmd, cmd) == 0)

    {

        return  SUCCESS;  

    }

    return FAILURE;           

}

/* find a cmd in the linklist and return the datanode pointer */

tDataNode* FindCmd(tLinkTable* head, char* cmd)

{

    return  (tDataNode*)SearchLinkTableNode(head, SearchCondition, (void*)cmd);

}

/* show all cmd in listlist */

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 = "help!";

    pNode->handler = help;

    AddLinkTableNode(*ppLinktable, (tLinkTableNode*)pNode);

    pNode = (tDataNode*)malloc(sizeof(tDataNode));

    pNode->cmd = "add";

    pNode->desc = "addition";

    pNode->handler = add; 

    AddLinkTableNode(*ppLinktable, (tLinkTableNode*)pNode);

    pNode = (tDataNode*)malloc(sizeof(tDataNode));

    pNode->cmd = "sub";

    pNode->desc = "sub";

    pNode->handler = sub; 

    AddLinkTableNode(*ppLinktable, (tLinkTableNode*)pNode);

    pNode = (tDataNode*)malloc(sizeof(tDataNode));

    pNode->cmd = "ls";

    pNode->desc = "list";

    pNode->handler = ls; 

    AddLinkTableNode(*ppLinktable, (tLinkTableNode*)pNode);

    pNode = (tDataNode*)malloc(sizeof(tDataNode));

    pNode->cmd = "max";

    pNode->desc = "max";

    pNode->handler = max; 

    AddLinkTableNode(*ppLinktable, (tLinkTableNode*)pNode);

    pNode = (tDataNode*)malloc(sizeof(tDataNode));

    pNode->cmd = "min";

    pNode->desc = "min";

    pNode->handler = min; 

    AddLinkTableNode(*ppLinktable, (tLinkTableNode*)pNode);

    pNode = (tDataNode*)malloc(sizeof(tDataNode));

    pNode->cmd = "quit";

    pNode->desc = "Quit from Menu Program V2.8";

    pNode->handler = quit; 

    AddLinkTableNode(*ppLinktable, (tLinkTableNode*)pNode);

    return 0; 

}

/* menu program */

tLinkTable* head = NULL;

int main()

{

    InitMenuData(&head); 

   /* cmd line begins */

    while(1)

    {

        char cmd[CMD_MAX_LEN];

        printf("please input a cmd >\n");

        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();

        }

    }

}

void help()

{

d78a

    ShowAllCmd(head);

}

void add()

{

    double num1;

    double num2;

    double result;

    printf("Addition!Please input two numbers!\n");

    printf("Use 'Blank' or 'Enter' to divide the two numbers.\n");

    scanf("%lf%lf", &num1, &num2);

    result=num1+num2;

    printf("%.2lf\n", result);

}

void sub()

{    

    double minuend;

    double meiosis;

    double result;

    printf("subtraction!Please input two numbers!\n");

    printf("Use 'Blank' or 'Enter' to divide the two numbers.\n");

    scanf("%lf%lf", &minuend, &meiosis);

    result=minuend-meiosis;

    printf("%.2lf\n", result);

}

void mul()

{    

    double num1;

    double num2;

    double result;

    printf("Multiplication!Please input two numbers!\n");

    printf("Use 'Blank' or 'Enter' to divide the two numbers.\n");

    scanf("%lf%lf", &num1, &num2);

    result=num1*num2;

    printf("%.2lf\n", result);

}

 void divi()

{   

    double dividend;

    double divisor;

    double result;

    printf("Divition!Please input two numbers!\n");

    printf("Use 'Blank' or 'Enter' to divide the two numbers.\n");

    scanf("%lf%lf", ÷nd, &divisor);

    if(divisor==0)

    {

        printf("Error!Dividor can not be zero!\n");

    }

    result=dividend / divisor;

    printf("%.2lf\n", result);

 }

void max()

{

    int a,b;

    int max;

    printf("please enter two integers:\n");

    printf("Use 'Blank' or 'Enter' to divide the two numbers.\n");

    scanf("%d",&a);

    scanf("%d",&b);

    if(a>b)

        max=a;

    else

        max=b;

    printf("the maximum of %d and %d is %d\n",a,b,max);

}

void min()

{

    int a,b;

    int min;

    printf("please enter two integers:\n");

    scanf("%d",&a);

    scanf("%d",&b);

    if(a<b)

         min=a;

    else

        min=b;

    printf("the minimum of %d and %d is %d\n",a,b,min);

}

void ls()

{

    system("ls");

}

void Error()



    printf("Command not found!\n");

}

void quit()

{

    exit(0);

}

linktable.c代码:

/************************************************************************/

/* Copyright(C) mclab.com SSE@USTC , 2017/10/20    */

/* FILENAME
:menu.c     */

/* PRINCIPAL AUTHOR:heyulin
    */

/* SUBSYSTEM NAME:mene
    */

/* MODULE NAME:menu
    */

/* LANGUAGE
:C         */

/* TARGET ENVIRONMENT:ANY
    */

/* DATE OF FIRST RELEASE:2017/10/20
    */

/* DESCRIPTION:This is a program
    */
/************************************************************************/

#include<stdio.h>

#include<stdlib.h>

#include"linktable.h"

struct LinkTable

{

    tLinkTableNode *pHead;

    tLinkTableNode *pTail;

    int         SumOfNode;

    pthread_mutex_t mutex;

};

/*

 * Create a LinkTable

 */

tLinkTable * CreateLinkTable()

{

    tLinkTable * pLinkTable = (tLinkTable *)malloc(sizeof(tLinkTable));

    if(pLinkTable == NULL)

    {

        return NULL;

    }

    pLinkTable->pHead = NULL;

    pLinkTable->pTail = NULL;

    pLinkTable->SumOfNode = 0;

    pthread_mutex_init(&(pLinkTable->mutex), NULL);

    return pLinkTable;

}

/*

 * Delete a LinkTable

 */

int DeleteLinkTable(tLinkTable *pLinkTable)

{

    if(pLinkTable == NULL)

    {

        return FAILURE;

    }

    while(pLinkTable->pHead != NULL)

    {

        tLinkTableNode * p = pLinkTable->pHead;

        pthread_mutex_lock(&(pLinkTable->mutex));

        pLinkTable->pHead = pLinkTable->pHead->pNext;

        pLinkTable->SumOfNode -= 1 ;

        pthread_mutex_unlock(&(pLinkTable->mutex));

        free(p);

    }

    pLinkTable->pHead = NULL;

    pLinkTable->pTail = NULL;

    pLinkTable->SumOfNode = 0;

    pthread_mutex_destroy(&(pLinkTable->mutex));

    free(pLinkTable);

    return SUCCESS;

}

/*

 * Add a LinkTableNode to LinkTable

 */

int AddLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode)

{

    if(pLinkTable == NULL || pNode == NULL)

    {

        return FAILURE;

    }

    pNode->pNext = NULL;

    pthread_mutex_lock(&(pLinkTable->mutex));

    if(pLinkTable->pHead == NULL)

    {

        pLinkTable->pHead = pNode;

    }

    if(pLinkTable->pTail == NULL)

    {

        pLinkTable->pTail = pNode;

    }

    else

    {

        pLinkTable->pTail->pNext = pNode;

        pLinkTable->pTail = pNode;

    }

    pLinkTable->SumOfNode += 1 ;

    pthread_mutex_unlock(&(pLinkTable->mutex));

    return SUCCESS;

}

/*

 * Delete a LinkTableNode from LinkTable

 */

int DelLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode)

{

    if(pLinkTable == NULL || pNode == NULL)

    {

        return FAILURE;

    }

    pthread_mutex_lock(&(pLinkTable->mutex));

    if(pLinkTable->pHead == pNode)

    {

        pLinkTable->pHead = pLinkTable->pHead->pNext;

        pLinkTable->SumOfNode -= 1 ;

        if(pLinkTable->SumOfNode == 0)

        {

            pLinkTable->pTail = NULL;

        }

        pthread_mutex_unlock(&(pLinkTable->mutex));

        return SUCCESS;

    }

    tLinkTableNode * pTempNode = pLinkTable->pHead;

    while(pTempNode != NULL)

    {

        if(pTempNode->pNext == pNode)

        {

            pTempNode->pNext = pTempNode->pNext->pNext;

            pLinkTable->SumOfNode -= 1 ;

            if(pLinkTable->SumOfNode == 0)

            {

                pLinkTable->pTail = NULL;

            }

            pthread_mutex_unlock(&(pLinkTable->mutex));

            return SUCCESS;

        }

        pTempNode = pTempNode->pNext;

    }

    pthread_mutex_unlock(&(pLinkTable->mutex));

    return FAILURE;

}

/*

 * Search a LinkTableNode from LinkTable

 * int Conditon(tLinkTableNode * pNode);

 */

tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode,void * args), void * args)

{

    if(pLinkTable == NULL || Conditon == NULL)

    {

        return NULL;

    }

    tLinkTableNode * pNode = pLinkTable->pHead;

    while(pNode != NULL)

    {

        if(Conditon(pNode,args) == SUCCESS)

        {

            return pNode;

        }

        pNode = pNode->pNext;

    }

    return NULL;

}

/*

 * get LinkTableHead

 */

tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable)

{

    if(pLinkTable == NULL)

    {

        return NULL;

    }

    return pLinkTable->pHead;

}

/*

 * get next LinkTableNode

 */

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

{

    if(pLinkTable == NULL || pNode == NULL)

    {

        return NULL;

    }

    tLinkTableNode * pTempNode = pLinkTable->pHead;

    while(pTempNode != NULL)

    {

        if(pTempNode == pNode)

        {

            return pTempNode->pNext;

        }

        pTempNode = pTempNode->pNext;

    }

    return NULL;

}

linktable.h代码:

/************************************************************************/

/* Copyright(C) mclab.com SSE@USTC , 2017/10/20    */

/* FILENAME
:menu.c     */

/* PRINCIPAL AUTHOR:heyulin
    */

/* SUBSYSTEM NAME:mene
   */

/* MODULE NAME:menu
 */

/* LANGUAGE
:C       */

/* TARGET ENVIRONMENT:ANY
  */

/* DATE OF FIRST RELEASE:2017/10/20
*/

/* DESCRIPTION:This is a program
  */

/************************************************************************/

/*

 * Revision log:

 *

 * Created by Wang Shiqing,2017/10/18

 *

 */

#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 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);

/*

 * Search a LinkTableNode from LinkTable

 * int Conditon(tLinkTableNode * pNode);

 */

tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode,void * args),void *args);

/*

 * get LinkTableHead

 */

tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable);

/*

 * get next LinkTableNode

 */

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

#endif /* _LINK_TABLE_H_ */

这次使用callback函数参数使得linktable查询接口更加通用,更加符合了接口设计可重用的原则与特点,符合软件工程编码规范。

在文件添加到本地的版本库中去:



提交到远程版本库中:



三,Code Review

把项目从github上clone 下来



测试项目是否能够正常运行:



四,实验总结

1,回调函数的使用是的查询链表的接口变得更加通用,同时也增加了代码的健壮性与可维护性。

2,回调函数使得程序的整个处理流程更加清晰易懂,实现了代码的可重用性与低耦合的要求

3,这次实验提高了自己的编码能力的同时,也学会了一些接口设计遵循的原则和技巧,懂得了好的代码就是要经过反复的设计和不断地优化来实现了的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  软件工程
相关文章推荐