软件工程:C编码实践篇学习总结
程序员文章站
2022-06-24 20:42:12
实验四:用可重用的链表模块来实现命令行菜单小程序V2.5
实验要求
用可重用的链表模块来实现命令行菜单小程序,执行某个命令时调用一个特定的函数作为执行动作; 链表模块的接...
实验四:用可重用的链表模块来实现命令行菜单小程序V2.5
实验要求
用可重用的链表模块来实现命令行菜单小程序,执行某个命令时调用一个特定的函数作为执行动作; 链表模块的接口设计要足够通用,命令行菜单小程序的功能保持不变; 可以将通用的Linktable模块集成到我们的menu程序中;
接口规范; 实验过程
接口规范; 实验过程
1.建立远程仓库,并下载到本地
git clone https://github.com/libaoquan95/seClass_lab4.git
并进入版本库并创建 menu.c linktable.h linktable.c 文件
2 linktable.h
#ifndef _LINK_TABLE_H_ #define _LINK_TABLE_H_ #include#define SUCCESS 0 #define FAILURE (-1) /* * LinkTableNode Node Type */ typedef struct LinkTableNode { struct LinkTableNode *pNext; }tLinkTableNode; /* * LinkTableNode Type */ typedef struct LinkTable { tLinkTableNode * pHead; tLinkTableNode * pTail; int SumOfNode; }tLinkTable; 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); #endif
3 linktable.c
#include #include #include #include "linktable.h" tLinkTable * CreateLinkTable() { tLinkTable *pLinkTable=(tLinkTable*)malloc(sizeof(tLinkTable)); if (pLinkTable == NULL) { return NULL; printf("create linktable failure! "); } pLinkTable->pHead = NULL; pLinkTable->pTail = NULL; pLinkTable->SumOfNode = 0; return pLinkTable; } int DelLinkTable(tLinkTable* pLinkTable) { if(pLinkTable == NULL) { return FAILURE; } while(pLinkTable->pHead != NULL) { tLinkTableNode *p = pLinkTable->pHead; pLinkTable->pHead = p->pNext; free(p); } pLinkTable->pHead = NULL; pLinkTable->pTail = NULL; pLinkTable->SumOfNode = 0; free(pLinkTable); return SUCCESS; } int AddLinkTable(tLinkTable* pLinkTable,tLinkTableNode *pNode) { if(pLinkTable == NULL || pNode == NULL) { return FAILURE; } if(pLinkTable->pHead == NULL && pLinkTable->pTail == NULL) { pLinkTable->pHead = pNode; pLinkTable->pTail = pNode; pLinkTable->pTail = NULL; pLinkTable->SumOfNode = 1; } else { pLinkTable->pTail->pNext = pNode; pLinkTable->pTail = pNode; pLinkTable->pTail->pNext = NULL; pLinkTable->SumOfNode ++; } return SUCCESS; } int DelLinkTableNode(tLinkTable* pLinkTable,tLinkTableNode *pNode) { if (pLinkTable == NULL) { return FAILURE; } tLinkTableNode *pWork = pLinkTable->pHead; tLinkTableNode *pre = pWork; if (pLinkTable->pHead == pNode) { pLinkTable->pHead = pWork->pNext; free(pWork); return SUCCESS; } while (pWork != NULL) { if(pWork == pNode) { pre->pNext = pWork->pNext; free(pWork); return SUCCESS; } pre = pWork; pWork = pWork->pNext; } return FAILURE; } tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable) { if (pLinkTable->pHead == NULL) { printf("LinkTable is empty\n"); return NULL; } return pLinkTable->pHead; } tLinkTableNode * GetNextLinkTableNode(tLinkTable* pLinkTable,tLinkTableNode *pNode) { if (pLinkTable == NULL || pNode == NULL) { printf("LinkTable is empty\n"); return NULL; } tLinkTableNode *pWork = pLinkTable->pHead; while(pWork != NULL) { if(pWork == pNode) return pWork->pNext; pWork = pWork->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/09 * Deacription : This is a menu program */ #include #include #include #include #include #include "linktable.h" #define CMD_MAX_LEN 128 #define DESC_LEN 1024 #define CMD_NUM 10 int 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; tDataNode * FindCmd(tLinkTable *head, char *cmd) { tDataNode *pNode = (tDataNode*)GetLinkTableHead(head); while(pNode != NULL) { if(strcmp(pNode->cmd, cmd) == 0) { return pNode; } pNode = (tDataNode*)GetNextLinkTableNode(head, (tLinkTableNode*)pNode); } return NULL; } 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], "p", "Calculate the pision of the two integer numbers", Div}, {(tLinkTableNode*)NULL, "quit", "Exit menu program", Quit} }; int InitMenuData(tLinkTable **ppLinkTable) { *ppLinkTable = CreateLinkTable(); (*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 p 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 pision 0\n"); } return 0; } /** * quit command * @param none * @return none */ int Quit() { exit(0); return 0; }
5.编译程序并运行
5.1 编译
gcc linktable.h linktable.c menu.c -o menu ./menu
5.2 运行
help 命令
time 命令
pwd 命令
add 命令
sub 命令
mul 命令
p 命令
错误的命令
quit 命令
6.上传至远程版本库
通过这次菜单程序模块化设计使我学会了许多的软件工程思想,体会到了模块化的巨大作用
本次实验设计了一个通用的链表模块,在调用时指定了具体的数据类型,体现了高类聚低耦合的思想,接口更加规范,使我们的代码更具有通用性并且更容易管理。
在实验中体会到了函数接口规范对于可重用的重要性,以及代码设计规范的一些方法。在编译的过程中也学习了链接的相关知识,对gcc编译器有了进一步的理解.
上一篇: 使用redis管理用户登录会话的方法
下一篇: oracle一行变多行实现教程