软件工程(C编码实践篇) 第五次作业实验报告

来源:互联网 发布:matlab做无标度网络 编辑:程序博客网 时间:2024/05/24 02:00

网易云课堂昵称:sa17225159
《软件工程(C编码实践篇)》MOOC课程作业 http://mooc.study.163.com/course/USTC-1000002006

实验五:用callback增强链表模块来实现命令行菜单小程序V2.8

实验要求

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

然后将lab5-1.tar.gz中的代码(即解压后lab5.1/目录下的源文件)直接放到lab5/目录下继续完成后面的实验内容

实验要求(参照视频中的具体实验过程) 本实验在提供的代码基础上进行

  • 给lab5-1.tar.gz找bug,quit命令无法运行的bug
  • 利用callback函数参数使Linktable的查询接口更加通用
  • 注意接口的信息隐藏

一定要及时提交代码以防丢失

实验过程

1. 找bug

因为实验代码lab5-1.tar.gz在实验楼的环境中,所以我先在实验楼中将代码解压,如下图
这里写图片描述
然后将代码上传至github,地址是https://github.com/libaoquan95/seClass_lab5.1.git,过程如下
这里写图片描述
这里写图片描述
这里写图片描述

然后再将代码下载至本机虚拟机中运行,这么做只是因为我不习惯实验楼的环境。
这里写图片描述
运行发现执行quit命令不能正确退出,且程序报错:

Input a cmd number > quitThis is a wrong cmd!

检查源代码,发现在menu.c的main()函数中,当p==NULL时会报此类型错误。

tDataNode *p = FindCmd(head, cmd);if( p == NULL){    printf("This is a wrong cmd!\n ");    continue;}

猜测是FindCmd()函数出现问题。

/* find a cmd in the linklist and return the datanode pointer */tDataNode* FindCmd(tLinkTable * head, char * cmd){    return  (tDataNode*)SearchLinkTableNode(head,SearchCondition);}

而FindCmd()函数仅仅是调用了linktable.c中的SearchLinkTableNode()函数,所以继续在SearchLinkTableNode()中排查错误。

/* * Search a LinkTableNode from LinkTable * int Conditon(tLinkTableNode * pNode); */tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode)){    if(pLinkTable == NULL || Conditon == NULL)    {        return NULL;    }    tLinkTableNode * pNode = pLinkTable->pHead;    while(pNode != pLinkTable->pTail)    {            if(Conditon(pNode) == SUCCESS)        {            return pNode;                           }        pNode = pNode->pNext;    }    return NULL;}

问题出现在while循环中,循环会在访问到链表最后一个节点之前退出循环,而quit命令位于链表尾部,所以执行quit命令会出现问题,将代码修改如下:

/* * Search a LinkTableNode from LinkTable * int Conditon(tLinkTableNode * pNode); */tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode)){    if(pLinkTable == NULL || Conditon == NULL)    {        return NULL;    }    tLinkTableNode * pNode = pLinkTable->pHead;    while(pNode != NULL)    {            if(Conditon(pNode) == SUCCESS)        {            return pNode;                           }        pNode = pNode->pNext;    }    return NULL;}

重新编译并运行
这里写图片描述
bug已被排除。

2. 优化代码结构

1.建立远程仓库,并下载到本地,远程仓库地址:https://github.com/libaoquan95/seClass_lab5.git

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

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

2 linktable.h

#ifndef _LINK_TABLE_H_#define _LINK_TABLE_H_#include <pthread.h>#define  SUCCESS 0#define  FAILURE (-1)/* * LinkTableNode Node Type */typedef struct LinkTableNode{    struct LinkTableNode *pNext;}tLinkTableNode;typedef struct LinkTable tLinkTable;    //声明Linktable,其内部结构不应该出现在.h的接口文件,即信息隐藏。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);tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode,void * args),void * args);#endif

3 linktable.c

#include<stdio.h>#include<stdlib.h>#include"linktable.h"typedef struct LinkTable{    tLinkTableNode *pHead;    tLinkTableNode *pTail;    int             SumOfNode;    pthread_mutex_t mutex;}tLinkTable;/* * 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, void* agrs); */tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode, void* agrs), void* agrs){    if(pLinkTable == NULL || Conditon == NULL)    {        return NULL;    }    tLinkTableNode * pNode = pLinkTable->pHead;    while(pNode != NULL)    {            if(Conditon(pNode, agrs) == 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;}

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/16 * Deacription                : This is a menu program*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <unistd.h>#include "linktable.h"#define CMD_MAX_LEN 128#define DESC_LEN 1024#define CMD_NUM 10int 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;int SearchCondition(tLinkTableNode * pLinkTableNode , void *args){    char *cmd = (char*)args;    tDataNode * pNode = (tDataNode *)pLinkTableNode;    if(strcmp(pNode->cmd, cmd) == 0)    {        return  SUCCESS;      }    return FAILURE;           }tDataNode* FindCmd(tLinkTable * head, char * cmd){    return  (tDataNode*)SearchLinkTableNode(head,SearchCondition,(void *)cmd);}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();    tDataNode *pNode0 = (tDataNode*)malloc(sizeof(tDataNode));    pNode0->cmd = "help";    pNode0->desc = "Print all command of menu";    pNode0->handler = PrintCommand;    AddLinkTableNode(*ppLinkTable, (tLinkTableNode*)pNode0);    tDataNode *pNode1 = (tDataNode*)malloc(sizeof(tDataNode));    pNode1->cmd = "time";    pNode1->desc = "Show system time";    pNode1->handler = PrintSystemTime;    AddLinkTableNode(*ppLinkTable, (tLinkTableNode*)pNode1);    tDataNode *pNode2 = (tDataNode*)malloc(sizeof(tDataNode));    pNode2->cmd = "pwd";    pNode2->desc = "Show current working directory";    pNode2->handler = PrintCurrentWorkingDirectory;    AddLinkTableNode(*ppLinkTable, (tLinkTableNode*)pNode2);    tDataNode *pNode3 = (tDataNode*)malloc(sizeof(tDataNode));    pNode3->cmd = "add";    pNode3->desc = "Calculate the summarize of the two integer numbers";    pNode3->handler = Add;    AddLinkTableNode(*ppLinkTable, (tLinkTableNode*)pNode3);    tDataNode *pNode4 = (tDataNode*)malloc(sizeof(tDataNode));    pNode4->cmd = "sub";    pNode4->desc = "Calculate the subtractions of the two integer numbers";    pNode4->handler = Sub;    AddLinkTableNode(*ppLinkTable, (tLinkTableNode*)pNode4);    tDataNode *pNode5 = (tDataNode*)malloc(sizeof(tDataNode));    pNode5->cmd = "mul";    pNode5->desc = "Calculate the multiplication of the two integer numbers";    pNode5->handler = Mul;    AddLinkTableNode(*ppLinkTable, (tLinkTableNode*)pNode5);    tDataNode *pNode6 = (tDataNode*)malloc(sizeof(tDataNode));    pNode6->cmd = "div";    pNode6->desc = "Calculate the division of the two integer numbers";    pNode6->handler = Div;    AddLinkTableNode(*ppLinkTable, (tLinkTableNode*)pNode6);    tDataNode *pNode7 = (tDataNode*)malloc(sizeof(tDataNode));    pNode7->cmd = "quit";    pNode7->desc = "Exit menu program";    pNode7->handler = Quit;    AddLinkTableNode(*ppLinkTable, (tLinkTableNode*)pNode7);    //(*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.编译程序并运行

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

这里写图片描述

6.上传至远程版本库
这里写图片描述

实验总结

远程仓库地址:
找bug的git地址:https://github.com/libaoquan95/seClass_lab5.1.git
修改代码结构的git地址:https://github.com/libaoquan95/seClass_lab5.git

回调函数是把函数的指针作为参数传递给另一个函数,回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。回调函数可以允许用户把需要调用的函数的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。

阅读全文
0 0
原创粉丝点击