实验五:用callback增强链表模块来实现命令行菜单小程序V2.8
来源:互联网 发布:唐狮质量怎么样 知乎 编辑:程序博客网 时间:2024/06/05 15:55
【shawn520 + 《软件工程(C编码实践篇)》MOOC课程作业http://mooc.study.163.com/course/USTC-1000002006 】
【代码仓库】https://github.com/shawn520/SE.git
实验内容
新创建一个目录lab5完成实验。
然后将lab5-1.tar.gz中的代码(即解压后lab5.1/目录下的源文件)直接放到lab5/目录下继续完成后面的实验内容
实验要求
本实验在提供的代码基础上进行
- 给lab5-1.tar.gz找bug,quit命令无法运行的bug
- 利用callback函数参数使Linktable的查询接口更加通用
- 注意接口的信息隐藏
实验报告要求
完成实验报告并公开发表(公开可访问博客或实验楼的实验报告),具体要求如下:
- 简述自己的实验的思路和具体过程;
- 引用实验中自己添加或修改的部分关键代码;
- 至少有一张实验关键代码截图,至少有一张实验运行结果截图;
- 将自己在实验中遇到疑惑和困难,以及自己的处理方法,实验心得等写入实验报告;
- 实验报告的最后做一个简要的实验总结;
- 重现实验的具体操作指南(参见下面的小节)*[特别重要,评阅实验报告时要根据您的操作指南进行实验验证]
- 将实验报告的URL提交到网易云课堂MOOC平台,编辑成一个链接可以直接点击打开。
- 测试自己的实验代码,复审自己的实验报告
请务必确认您提交的实验报告中的实验代码可以直接进行如下操作,并将如下操作放入实验报告的显著位置便于报告评审
实验的思路和具体过程
运行lab5中的代码,
寻找lab5中quit命令无法运行的bug
发现quit命令错误的原因在于SearchLinkTableNode函数最后一项循环体条件设置错误
while(pNode != pLinkTable->pTail)
3. 应修改为
while(pNode != NULL)
4. 运行结果
5. 添加接口参数,使接口更通用
主要是为了使用更方便和安全,将cmd由全局变量修改在main函数定义,为此,修改了menu.c中的FindCmd和SearchCondition函数中传入的参数,将字符指针cmd强制转换为空指针,为此,也修改了linktable.c中的SearchLinkTableNode函数,使其与menu中的函数匹配。同时为了隐藏结构体特征,我们在linktable.h中只声明了tLinkTable,具体定义放入了linktable.c中,上面提到的函数在linktable.h中的声明也做了相应的修改。
关键代码
menu.c
#include <stdio.h>#include <stdlib.h>#include "linktable.h"int Help();int Quit();#define CMD_MAX_LEN 128#define DESC_LEN 1024#define CMD_NUM 10/* 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 = "Menu List:"; pNode->handler = Help; AddLinkTableNode(*ppLinktable,(tLinkTableNode *)pNode); pNode = (tDataNode*)malloc(sizeof(tDataNode)); pNode->cmd = "version"; pNode->desc = "Menu Program V1.0"; pNode->handler = NULL; AddLinkTableNode(*ppLinktable,(tLinkTableNode *)pNode); pNode = (tDataNode*)malloc(sizeof(tDataNode)); pNode->cmd = "quit"; pNode->desc = "Quit from Menu Program V1.0"; 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("Input a cmd number > "); 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(); } }}int Help(){ ShowAllCmd(head); return 0; }int Quit(){ exit(0);}
linktable.c
#include<stdio.h>#include<stdlib.h>#include"linktable.h"/* * Create a LinkTable */typedef struct LinkTable{ tLinkTableNode *pHead; tLinkTableNode *pTail; int SumOfNode; pthread_mutex_t mutex;}tLinkTable;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
#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_ */
实验关键代码截图
实验运行结果截图
完成后提交到git
git add linktable.c linktable.h menu.c git commit -m 'menu_v2.8'git push
实验总结
这次实验学习了如何通过回调函数来使得查询接口更加便捷,以及隐藏部分结构体的声明来隐藏数据。
复审实验报告
本实验的代码可通过如下方式下载并运行
git clone https://github.com/shawn520/SE.git cd lab5gcc menu.c linklist.c -o menu./menu
欢迎大家访问我的——
- GitHub主页: https://github.com/shawn520/SE
- CSDN博客: http://blog.csdn.net/liushawn520
- 新浪微博 @奔跑中的Shawn
- 实验五.用callback增强链表模块来实现命令行菜单小程序V2.8
- 实验五:用callback增强链表模块来实现命令行菜单小程序V2.8
- 实验五:用callback增强链表模块来实现命令行菜单小程序V2.8
- 实验五:用callback增强链表模块来实现命令行菜单小程序V2.8
- 实验五:用callback增强链表模块来实现命令行菜单小程序V2.8
- 实验五:用callback增强链表模块来实现命令行菜单小程序V2.8
- 实验五:用callback增强链表模块来实现命令行菜单小程序V2.8
- 实验五:用callback增强链表模块来实现命令行菜单小程序V2.8
- 实验五:用callback增强链表模块来实现命令行菜单小程序V2.8
- 实验五:用callback增强链表模块来实现命令行菜单小程序V2.8
- 实验报告五:用callback增强链表模块来实现命令行菜单小程序V2.8
- 实验报告五:用callback增强链表模块来实现命令行菜单小程序V2.8
- 软件工程(C编码实践篇)”实验报告 实验五:用callback增强链表模块来实现命令行菜单小程序V2.8
- “软件工程(C编码实践篇)”实验报告【实验五:用callback增强链表模块来实现命令行菜单小程序V2.8】
- [高级软件工程实验]用callback增强链表模块来实现命令行菜单小程序V2.8
- 软件工程(C编码实践篇) 实验五:用callback增强链表模块来实现命令行菜单小程序V2.8
- 用callback增强链表模块来实现命令行菜单小程序V2.8
- 用callback增强链表模块来实现命令行菜单小程序V2.8
- TCP三次握手与四次挥手的理解和场景举例
- 1. Two Sum
- Android VideoView播放视频只有声音没有图像黑屏
- log4j,logback,sl4j常用日志格式详解
- 哲学家就餐问题
- 实验五:用callback增强链表模块来实现命令行菜单小程序V2.8
- 数据库方言Dialect
- SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系
- jzoj1481. 偷懒的西西
- 55. Jump Game
- 管理输入和输出及vim的简单用法
- [使用手册] 欢迎使用CSDN-markdown编辑器
- React Native 原生平台调用React Native组件
- PAT 1004. To Buy or Not to Buy