软件工程(C编码实践篇) 第七次作业实验报告
来源:互联网 发布:淘宝女士春装 编辑:程序博客网 时间:2024/06/07 10:49
网易云课堂昵称:sa17225159
《软件工程(C编码实践篇)》MOOC课程作业 http://mooc.study.163.com/course/USTC-1000002006
实验七:将menu设计为可重用的子系统
实验要求
- 为menu子系统设计接口,并写用户范例代码来实现原来的功能;
- 使用make和make clean来编译程序和清理自动生成的文件;
- 使menu子系统支持带参数的复杂命令,并在用户范例代码中自定义一个带参数的复杂命令;
- 可以使用getopt函数获取命令行参数。
实验过程
1.建立远程仓库,并下载到本地,远程仓库地址:https://github.com/libaoquan95/seClass_lab7.git
git clone https://github.com/libaoquan95/seClass_lab7.git
并进入版本库并创建相关文件
2 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_ */
3 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 Condition(tLinkTableNode * pNode); */tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Condition(tLinkTableNode * pNode, void * args), void * args){ if(pLinkTable == NULL || Condition == NULL) { return NULL; } tLinkTableNode * pNode = pLinkTable->pHead; while(pNode != NULL) { if(Condition(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;}
4 menu.h
#ifndef _menu#define _menuint MenuConfig(char * cmd, char * desc, void (*handler)(int argc, char *argv[]));int ExecuteMenu();#endif
5 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 10tLinkTable * 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); 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;}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 command > "); 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);}
6.mymenu.c
mymenu.c 利用通用的menu,生成自己的命令行程序。利用argv 和 argc ,实现从输入的命令中提取参数,实现带参数的命令的设计。
/* * Copyright (C) libaoquan95@github.com, 2017-2018 * * File name : mymenu.c * Principal author : libaoquan95 * Subsystem name : mymenu * Module name : mymenu * Language : C * Date of first release : 2017/10/28 * Deacription : This is a mymenu program*/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <time.h>#include "menu.h"void PrintSystemTime(int argc, char *argv[]);void PrintCurrentWorkingDirectory(int argc, char *argv[]);void Add(int argc, char *argv[]);void Sub(int argc, char *argv[]);void Mul(int argc, char *argv[]);void Div(int argc, char *argv[]);void Quit(int argc, char *argv[]);int main(int argc,char* argv[]){ MenuConfig("time", "Show system time", PrintSystemTime); MenuConfig("pwd", "Show current working directory", PrintCurrentWorkingDirectory); MenuConfig("pwd", "Show current working directory", PrintCurrentWorkingDirectory); MenuConfig("add", "Calculate the summarize of the two integer numbers", Add); MenuConfig("sub", "Calculate the subtractions of the two integer numbers", Sub); MenuConfig("mul", "Calculate the multiplication of the two integer numbers", Mul); MenuConfig("div", "Calculate the division of the two integer numbers", Div); MenuConfig("quit", "Exit menu program", Quit); ExecuteMenu();}/** * print current time * @param none * @return none */void PrintSystemTime(int argc, char *argv[]){ 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);}/** * print current working directory path * @param none * @return none */void PrintCurrentWorkingDirectory(int argc, char *argv[]){ char buf[256]; getcwd(buf, sizeof(buf)); printf("当前路径: %s\n", buf);}/** * calculate add of two interage numbers * @param none * @return calculate result */ void Add(int argc, char *argv[]) { if(argc != 3) { printf("error count of calculate\n"); } int num1 = atoi(argv[1]), num2 = atoi(argv[2]); printf("%d + %d = %d\n", num1, num2, num1 + num2); } /** * calculate sub of two interage numbers * @param none * @return calculate result */ void Sub(int argc, char *argv[]) { if(argc != 3) { printf("error count of calculate\n"); } int num1 = atoi(argv[1]), num2 = atoi(argv[2]); printf("%d - %d = %d\n", num1, num2, num1 - num2); } /** * calculate mul of two interage numbers * @param none * @return calculate result */ void Mul(int argc, char *argv[]) { if(argc != 3) { printf("error count of calculate\n"); } int num1 = atoi(argv[1]), num2 = atoi(argv[2]); printf("%d * %d = %d\n", num1, num2, num1 * num2); } /** * calculate div of two interage numbers * @param none * @return calculate result */ void Div(int argc, char *argv[]) { if(argc != 3) { printf("error count of calculate\n"); } int num1 = atoi(argv[1]), num2 = atoi(argv[2]); if(num2 != 0) { printf("%d / %d = %d\n", num1, num2, num1 / num2); } else { printf("ERROR: don't division 0\n"); } } /** * quit command * @param none * @return none */ void Quit(int argc, char *argv[]) { exit(0); }
7.makefile
makefile文件中,缩进要用tab键,使用空格缩进会产生错误。
CC_PTHREAD_FLAGS = -lpthreadCC_FLAGS = -cCC_OUTPUT_FLAGS = -oCC = gccRM = rmRM_FLAGS = -fTARGET = mymenuOBJS = linktable.o menu.o mymenu.oall: $(OBJS) $(CC) $(CC_OUTPUT_FLAGS) $(TARGET) $(OBJS).c.o: $(CC) $(CC_FLAGS) $<clean: $(RM) $(RM_FLAGS) $(OBJS) $(TARGET) *.bak
8.编译程序并运行
9.上传至远程版本库
实验总结
远程仓库地址:https://github.com/libaoquan95/seClass_lab7.git
- makefile 文件
因为Makefile文件的存在,所以可以使用make命令来编译。makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。主要是三部分内容,先是为menu子系统设计接口,将menu设计为可重用的子系统。然后是Makefile,使得编译的时候不需要再去敲打命令,麻烦,直接执行make就可以了,而且还可以make clean删除编译产生出的文件。
可重用设计
menu作为一个子系统的可重用接口设计:(1)手里有把锤子,看哪里都是钉子;(2)够用就好—不要太具体,也不要太通用。
支持带参数的复杂命令的方法
- shell将命令行解析成argc和argv传递给执行程序;
- 定义一个函数将命令行转换成argc和argv;(3)自定义处理函数内部可以使用getopt函数来获取参数。
- 软件工程(C编码实践篇) 第七次作业实验报告
- 软件工程(C编码实践篇) 第四次作业实验报告
- 软件工程(C编码实践篇) 第五次作业实验报告
- 软件工程(C编码实践篇) 第二次作业实验报告
- 软件工程(C编码实践篇) 第三次作业实验报告
- “软件工程(C编码实践篇)”实验报告【实验一:写一个hello world小程序】
- “软件工程(C编码实践篇)”实验报告【实验二:命令行菜单小程序V1.0】
- 软件工程(C编码实践篇)”实验报告 实验二:命令行菜单小程序V1.0
- C++第七次实验---作业报告
- 软件工程(C编码实践篇)实验一
- 软件工程第七次实验
- 软件工程(C编码实践篇)”实验报告一:写一个hello world小程序
- C程序设计课程-第七次实验报告
- c程序设计第七次上机实验报告
- 第七次C程序设计实验报告
- 第七次c语言上机实验报告
- “软件工程(C编码实践篇)”实验报告【实验三:内部模块化的命令行菜单小程序V2.0】
- 软件工程(C编码实践篇)”实验报告实验七:将menu设计为可重用的子系统
- 打造一款好手机 360°全面解析OPPO A53
- hive 正则表达式详解
- Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) D
- 记录Studio 初始上传项目的步骤
- 命令模式
- 软件工程(C编码实践篇) 第七次作业实验报告
- 数据库常用语法详解
- Github常用命令
- 更新--学习笔记 凸包 && K短路
- 掌网科技李炜:着力发烧级VR迎接市场爆发!
- 中交兴路车联网谈物流O2O三大关键词:产业链、大数据、生态化
- 一元众筹X6Plus 够快才畅快vivo X6送豪礼电商首销
- 散列的实现(1)
- BP神经网络(输出层采用Softmax激活函数、交叉熵损失函数)公式推导