实验报告7
网易云课堂昵称:哪来的妖精
网易云课堂《软件工程(C编码实践篇)》MOOC课程作业:http://mooc.study.163.com/learn/USTC-1000002006
github https://github.com/littlewulei/Software-Engineering-Lab.git
实验要求
为menu子系统设计接口,并写用户范例代码来实现原来的功能;
使用make和make clean来编译程序和清理自动生成的文件;
使menu子系统支持带参数的复杂命令,并在用户范例代码中自定义一个带参数的复杂命令;
实验步骤
创建lab7文件夹。创建Makefile文件如下:
CC_PTHREAD_FLAGS =-lpthread CC_FLAGS =-c CC_OUTPUT_FLAGS =-o CC =gcc RM =rm RM_FLAGS =-f TARGET=test OBJS=linktable.o menu.o test.o all: $(OBJS) $(CC) $(CC_OUTPUT_FLAGS) $(TARGET) $(OBJS) .c.o: $(CC) $(CC_FLAGS) $< clean: $(RM) $(RM_FLAGS) $(OBJS) $(TARGET) *.bak
需要注意的是Makefile 需要用Tab缩进,空格不行。
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 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_ */
linktable.c文件如下:
#include<stdio.h> #include<stdlib.h> #include"linktable.h" typedef struct LinkTableNode { struct LinkTableNode * pNext; }tLinkTableNode; 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); */ 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; }
menu.h :
#ifndef _MENU_H #define _MENU_H int MenuConfig(char * cmd, char * desc, void (*handler)(int argc, char *argv[])); int ExecuteMenu(); #endif
menu.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "linktable.h" #include "menu.h" #define CMD_MAX_LEN 128 #define CMD_MAX_ARGV_LEN 128 #define DESC_LEN 1024 #define CMD_NUM 10 tLinkTable * head = NULL; void Help(int argc, char *argv[]); /* data struct and its operations */ typedef struct DataNode { tLinkTableNode * pNext; char* cmd; char* desc; void (*handler)(int argc, char *argv[]); } 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 MenuConfig(char * cmd, char * desc, void (*handler)(int argc, char *argv[])) { tDataNode* pNode = NULL; if (head == NULL) { head = CreateLinkTable(); pNode = (tDataNode*)malloc(sizeof(tDataNode)); pNode->cmd = "help"; pNode->desc = "Menu List:"; 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); } int ExecuteMenu() { while(1) { int argc = 0; char *argv[CMD_MAX_ARGV_LEN]; char cmd[CMD_MAX_LEN]; char *pcmd = NULL; printf("Input a cmd number > "); pcmd = fgets(cmd, CMD_MAX_LEN, stdin); if (pcmd == NULL) { continue; } pcmd = strtok(pcmd, " "); while (pcmd != NULL && argc < CMD_MAX_ARGV_LEN) { argv[argc] = pcmd; argc++; pcmd = strtok(NULL, " "); } if (argc == 1) { int len = strlen(argv[0]); *(argv[0] + len - 1) = ‘\0‘; } 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); } } } void Help(int argc, char *argv[]) { ShowAllCmd(head); }
test.c :
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <time.h> #include "menu.h" void Quit(int argc, char *argv[]); void Version(int argc, char *argv[]); void Quit(int argc, char *argv[]) { exit(0); } void Version(int argc, char *argv[]) { printf("version7.0\n"); } void Date(int argc, char *argv[]) { system("date"); } int Add(int argc, char* argv[]) { int i,r; if(argc != 3) { printf("warning input 2 numbers\n"); return 0; } r=atoi(argv[1])+atoi(argv[2]); printf("result is %d\n",r); return 0; } int Sub(int argc, char* argv[]) { int i,r; if(argc !=3) { printf("warning input 2 numbers\n"); return 0; } r=atoi(argv[1])-atoi(argv[2]); printf("result is %d\n",r); return 0; } int Mul(int argc, char* argv[]) { int i,r; if(argc !=3) { printf("warning input 2 numbers\n"); return 0; } r=atoi(argv[1])*atoi(argv[2]); printf("result is %d\n",r); return 0; } int Divi(int argc, char* argv[]) { int i; float r; if(argc !=3) { printf("warning input 2 numbers\n"); return 0; } r=((float)atoi(argv[1]))/atoi(argv[2]); printf("result is %.2f\n",r); return 0; } int main(int argc,char* argv[]) { MenuConfig("version","XXX1.0(Menu program v7.0 inside)",NULL); MenuConfig("quit","Quit from XXX",Quit); MenuConfig("date","Show the date",Date); MenuConfig("add","return sum of the two numbers", Add); MenuConfig("sub","return difference of the two numbers", Sub); MenuConfig("mul","return product of the two numbers", Mul); MenuConfig("divi","return quotient of the two numbers", Divi); ExecuteMenu(); }
运行截图
上传GitHub
实验总结
这次实验彻底将menu小程序编写成为一个可重用的小程序供其他程序使用,实现了代码的可重用性,并且学会了使用Makefile 编译代码。
时间: 2024-10-14 23:38:14