软件工程(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
回调函数是把函数的指针作为参数传递给另一个函数,回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。回调函数可以允许用户把需要调用的函数的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。
- 软件工程(C编码实践篇) 第五次作业实验报告
- 软件工程(C编码实践篇) 第四次作业实验报告
- 软件工程(C编码实践篇) 第七次作业实验报告
- 软件工程(C编码实践篇) 第二次作业实验报告
- 软件工程(C编码实践篇) 第三次作业实验报告
- “软件工程(C编码实践篇)”实验报告【实验一:写一个hello world小程序】
- “软件工程(C编码实践篇)”实验报告【实验二:命令行菜单小程序V1.0】
- 软件工程(C编码实践篇)”实验报告 实验二:命令行菜单小程序V1.0
- C++第五次实验--作业报告
- C++第五次实验-作业报告
- 软件工程(C编码实践篇)实验一
- 软件工程(C编码实践篇)”实验报告一:写一个hello world小程序
- 软件工程第五次实验
- “软件工程(C编码实践篇)”实验报告【实验三:内部模块化的命令行菜单小程序V2.0】
- 软件工程(C编码实践篇)”实验报告实验七:将menu设计为可重用的子系统
- “软件工程(C编码实践篇)”实验报告【实验七:将menu设计为可重用的子系统】
- [高级软件工程实验]软件工程(C编码实践篇)学习总结
- 第五次C语言上机实验报告
- ArrayList
- postgresql数据库无法连接,提示 Is the server running on host "localhost" (127.0.0.1) and accepting TCP/IP conn
- Android 录音工具
- Java通过百度地图API获取地址经纬度
- git 删除本地分支和远程分支、本地代码回滚和远程代码库回滚
- 软件工程(C编码实践篇) 第五次作业实验报告
- laucher添加widget过程
- 常见机器学习分类
- GOPS2017全球运维大会·上海站将于11月在上海举行!
- Codeforces 96D Volleyball【重构图最短路】
- mac系统移动光标&&删除快捷键
- C++获取当前时间戳,并转化成格式化时间
- Python的内置函数---ascii,abs,any
- 写于第一次参加极限编程之后