一、实验思路
1.观看学习云课堂相关视频,学习怎样为整个menu子系统设计接口。
2.搭建实验环境。
3.学习、使用make和make clean来编译程序和清理自动生成的文件修改menu程序。
3.修改代码,使menu子系统支持带参数的复杂命令,并在用户范例代码中自定义一个带参数的复杂命令。
4.查漏补缺,上传至代码库,完成实验报告。
二、实验过程
1.试验环境搭建
2.实验代码
menu.h
#ifndef _menu #define _menu int MenuConfig(char* cmd, char* desc, int (*handler)()); int ExecuteMenu(); #endif
menu.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include "linktable.h" int Help(int argc, char* argv[]); extern char* optarg; extern int optind; #define CMD_MAX_LEN 128 #define CMD_MAX_ARGV 128 #define DESC_LEN 1024 #define CMD_NUM 10 /* data struct and its operations */ tLinkTable* head = NULL; typedef struct DataNode { tLinkTableNode * pNext; char* cmd; char* desc; int (*handler)(int argc, char* argv[]); } tDataNode; int SearchCondition(tLinkTableNode * pLinkTableNode, void * args) { tDataNode * pNode = (tDataNode *)pLinkTableNode; char * tempchar = args; if(strcmp(pNode->cmd, args) == 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, 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 ReceiveCMD(char* cmd, int* argc, char* argv[]) { char* pcmd = NULL; pcmd = fgets(cmd, CMD_MAX_LEN, stdin); int len = strlen(cmd); *(cmd + len - 1) = '\0'; pcmd = strtok(pcmd, " "); while(pcmd == NULL) { return -1; } while(pcmd != NULL && (*argc) < CMD_MAX_ARGV) { argv[*argc] = pcmd; (*argc)++; pcmd = strtok(NULL, " "); } return 0; } int MenuConfig(char* cmd, char* desc, int (*handler)(int argc, char* argv[])) { tDataNode* pNode = NULL; if(head == NULL) { head = CreateLinkTable(); pNode = (tDataNode*)malloc(sizeof(tDataNode)); pNode->cmd = "help"; pNode->desc = "list all cmds"; pNode->handler = Help; AddLinkTableNode(head, (tLinkTableNode*)pNode); } pNode = (tDataNode*)malloc(sizeof(tDataNode)); pNode->cmd = cmd; pNode->desc = desc; pNode->handler = handler; AddLinkTableNode(head, (tLinkTableNode*)pNode); return 0; } /* menu program */ int ExecuteMenu() { /* cmd line begins */ while(1) { int argc = 0; char* argv[CMD_MAX_ARGV]; char cmd[CMD_MAX_LEN]; printf("Input a cmd number > "); if(ReceiveCMD(cmd, &argc, argv) == -1) { continue; } //scanf("%s", cmd); tDataNode *p = FindCmd(head, argv[0]); 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(argc, argv); } } } int Help(int argc, char* argv[]) { int ch; char* ch_prom; if(argc == 1) { ShowAllCmd(head); return 0; } while((ch = getopt(argc, argv, "shl:")) != -1) { switch(ch) { case 's': printf("This is \"-s\" mode help\n"); ShowAllCmd(head); break; case 'h': printf("This is \"-h\" mode help\n"); ShowAllCmd(head); break; case 'l': ch_prom = optarg; printf("This is \"-l\" mode help with %s\n", ch_prom); ShowAllCmd(head); break; case '?': printf("Wrong argument!\n"); } } optind = 1; return 0; }
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 { tLinkTableNode *pHead; tLinkTableNode *pTail; int SumOfNode; pthread_mutex_t mutex; }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_ */
linktable.c
#include<stdio.h> #include<stdlib.h> #include"linktable.h" /* * 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; }
test.c
#include "menu.h" #include <stdio.h> #include <stdlib.h> int version(int argc, char* argv); int quit(int argc, char* argv); int main() { char* cmd = "version"; char* desc = "version information"; MenuConfig(cmd, desc, version); cmd = "quit"; desc = "type \"quit\" to exit"; MenuConfig(cmd, desc, quit); ExecuteMenu(); return 0; } int version(int argc, char* argv) { printf("v1.0\n"); return 0; } int quit(int argc, char* argv) { exit(0); return 0; }
三.编译及运行
1.makefile文件
2.编译
3.执行
四.实验代码上传
五.总结
本次实验首先了解了makefile文件的使用,可以较方便的对整个项目进行管理,也使得调试过程更为方便。 随后将程序继续改进,加入了带参数的命令输入方式。这七次实验,一步步将menu程序做的更为完善。