火页凡 + 《软件工程(C编码实践篇)》MOOC课程作业http://mooc.study.163.com/course/USTC-1000002006
一. 实验过程
Clonegithub库:github.com/wangyufan/SE.git到实验环境
1.进入实验目录并创建实验一文件夹lab4
2.编写linktable.h,linktable.c文件,修改实验3中的menu.c文件,实验代码如下:
#define SUCCESS 0
#define FAILURE (-1)
typedef struct LinkTableNode
{
struct LinkTableNode* pNext;
}tLinkTableNode;
typedef struct LinkTable
{
tLinkTableNode *pHead;
tLinkTableNode *pTail;
int sumOfNode;
pthread_mutex_t mutex;
}tLinkTable;
tLinkTable* CreateLinkTable();
int DeleteLinkTable(tLinkTable* pLinkTable);
int AddLinkTableNode(tLinkTable* pLinkTable, tLinkTableNode* pNode);
int DelLinkTableNode(tLinkTable* pLinkTable, tLinkTableNode* pNode);
tLinkTableNode* GetLinkTableHead(tLinkTable* pLinkTable);
tLinkTableNode* GetNextLinkTableNode(tLinkTable* pLinkTable, tLinkTableNode* pNode);#include
#include
#include "linktable.h"
tLinkTable* CreateLinkTable()
{
tLinkTable* pLinkTable = (tLinkTable*)malloc(sizeof(tLinkTable));
if(pLinkTable == NULL)
{
return NULL;
}
pLinkTable->pHead = NULL;
pLinkTable->pTail = NULL;
pLinkTable->sumOfNode = 0;
return pLinkTable;
}
int DeleteLinkTable(tLinkTable* pLinkTable)
{
if(pLinkTable == NULL)
{
return FAILURE;
}
while(pLinkTable->pHead != NULL)
{
tLinkTableNode* pNode = pLinkTable->pHead;
pLinkTable->pHead = pLinkTable->pHead->pNext;
free(pNode);
}
pLinkTable->pHead = NULL;
pLinkTable->pTail = NULL;
pLinkTable->sumOfNode = -1;
free(pLinkTable);
return SUCCESS;
}
int AddLinkTableNode(tLinkTable* pLinkTable, tLinkTableNode* pNode)
{
if (pLinkTable == NULL || pNode == NULL)
{
return FAILURE;
}
pNode->pNext = NULL;
if (pLinkTable->pHead == NULL)
{
pLinkTable->pHead = pNode;
}
if (pLinkTable->pTail == NULL)
{
pLinkTable->pTail = pNode;
}
else
{
pLinkTable->pTail->pNext = pNode;
pLinkTable->pTail = pNode;
}
pLinkTable->sumOfNode = pLinkTable->sumOfNode + 1;
return SUCCESS;
}
int DelLinkTableNode(tLinkTable* pLinkTable, tLinkTableNode* pNode)
{
if (pLinkTable == NULL || pNode == NULL)
{
return FAILURE;
}
if (pLinkTable->pHead == pNode)
{
pLinkTable->pHead = pLinkTable->pHead->pNext;
pLinkTable->sumOfNode = pLinkTable->sumOfNode - 1;
if (pLinkTable->sumOfNode == 0)
{
pLinkTable->pTail == NULL;
}
return SUCCESS;
}
tLinkTableNode* p = pLinkTable->pHead;
while (p != NULL)
{
if (p->pNext == pNode)
{
p->pNext = p->pNext->pNext;
pLinkTable->sumOfNode = pLinkTable->sumOfNode - 1;
if (pLinkTable->sumOfNode == 0)
{
pLinkTable->pTail = NULL;
}
return SUCCESS;
}
p = p->pNext;
}
return FAILURE;
}
tLinkTableNode* GetLinkTableHead(tLinkTable* pLinkTable)
{
if (pLinkTable == NULL || pLinkTable->pHead == NULL)
{
return NULL;
}
return pLinkTable->pHead;
}
tLinkTableNode* GetNextLinkTableNode(tLinkTable* pLinkTable, tLinkTableNode* pNode)
{
if (pLinkTable == NULL || pNode == NULL)
{
return NULL;
}
tLinkTableNode* p = pLinkTable->pHead;
while (p != NULL)
{
if (p == pNode)
{
return p->pNext;
}
p = p->pNext;
}
return NULL;
}#include
#include
#include
#include "linktable.h"
void help();
void upper();
void version();
void lower();
void add();
void sub();
void multi();
void quit();
#define CMD_MAX_LENGTH 128
typedef struct Node
{
tLinkTableNode* pNext;
char* cmd;
char* desc;
void (*handler)();
}tNode;
tNode* FindCmd(tLinkTable* head, char* cmd)
{
tNode* pNode = (tNode*)GetLinkTableHead(head);
while(pNode != NULL)
{
if(strcmp(pNode->cmd, cmd) == 0)
{
return pNode;
}
pNode = (tNode*)GetNextLinkTableNode(head, (tLinkTableNode*)pNode);
}
return NULL;
}
int ShowAllCmd(tLinkTable* head)
{
tNode* pNode = (tNode*) GetLinkTableHead(head);
while(pNode != NULL)
{
printf("%10s ----- %s\n", pNode->cmd, pNode->desc);
pNode = (tNode*)GetNextLinkTableNode(head, (tLinkTableNode*)pNode);
}
return 0;
}
typedef struct DataNode
{
char* cmd;
char* desc;
void (*handler)();
struct DataNode *next;
}tDataNode;
tDataNode Head[] =
{
{"help", "cmd tips.", help, &Head[1]},
{"version","show version of this menu.", version, &Head[2]},
{"quit", "exit cmd.", quit, &Head[3]},
{"upper", "change the case into uppercase Letters.", upper, &Head[4]},
{"lower", "change the case into lowercase Letters.", lower, &Head[5]},
{"sub", "subtraction of two numbers.", sub, &Head[6]},
{"add", "addition of two numbers.", add, &Head[7]},
{"multi", "multiplication of two numbers.", multi, NULL}
};
tLinkTable* InitMenuData(tDataNode* Head, int length)
{
tLinkTable* pLinkTable = CreateLinkTable();
int i;
for(i=0; pLinkTable->sumOfNode < length; i++)
{
tNode* pNode = (tNode*)malloc(sizeof(tNode));
pNode->cmd = Head[i].cmd;
pNode->desc = Head[i].desc;
pNode->handler = Head[i].handler;
AddLinkTableNode(pLinkTable, (tLinkTableNode*)pNode);
}
return pLinkTable;
}
int main()
{
int i;
tLinkTable* head = InitMenuData(Head, 8);
char cmd[CMD_MAX_LENGTH];
while(1)
{
printf("menu cmd-> ");
scanf("%s", cmd);
tNode* p = FindCmd(head, cmd);
if(p == NULL)
{
printf("error: Wrong command!\n");
}
else
{
p->handler();
}
}
return 0;
}
void help()
{
printf("+--------+---------------------------------+\n");
printf("+ help + cmd tips +\n");
printf("+ quit + exit cmd +\n");
printf("+ version+ show version +\n");
printf("+ upper + change the case into uppercase Letters +\n");
printf("+ lower + change the case into lowercase Letters +\n");
printf("+ sub + subtraction of two numbers +\n");
printf("+ add + addition of two numbers +\n");
printf("+ multi + multiplication of two numbers +\n");
printf("+--------+---------------------------------+\n");
}
void quit()
{
exit(0);
}
void upper()
{
int i;
char arr[100];
printf("please input contents:");
scanf("%s", arr);
for(i=0; arr[i]!='\0'; i++)
{
if(arr[i]>='A'&&arr[i]<='Z')
arr[i]+=32;
}
printf("%s\n", arr);
}
void lower()
{
int i;
char arr[100];
printf("please input contents:");
scanf("%s", arr);
for(i=0; arr[i]!='\0'; i++)
{
if(arr[i]>='a'&&arr[i]<='z')
arr[i]-=32;
}
printf("%s\n", arr);
}
void version()
{
printf("the version is 1.0.0\n");
}
void add()
{
double num1,num2,count;
printf("+-------*--------*--------*--------*-------+\n");
printf("please input two numbers:");
scanf("%lf %lf",&num1, &num2);
char a;
count = num1 + num2;
a = '+';
printf("%lf %c %lf = %lf \n",num1, a, num2, count);
}
void sub()
{
double num1,num2,count;
printf("+-------*--------*--------*--------*-------+\n");
printf("please input two numbers:");
scanf("%lf %lf",&num1, &num2);
char a;
count = num1 - num2;
a = '-';
printf("%lf %c %lf = %lf \n",num1, a, num2, count);
}
void multi()
{
double num1,num2,count;
printf("+-------*--------*--------*--------*-------+\n");
printf("please input two numbers:");
scanf("%lf %lf",&num1, &num2);
char a;
count = num1 * num2;
a = '*';
printf("%lf %c %lf = %lf \n",num1, a, num2, count);
}
3实验结果
实现的命令8个:
help帮助
version版本号
quit退出
upper将字符串中大写字母变小写
lower将字符串中小写字母变大写
add
sub
mult 分别计算两个数的加减乘
4.提交代码到版本库
二. 实验总结
1. 用可重用的链表模块来实现命令行菜单小程序,链表模块的接口设计足够通用
2.学习用Call-in函数方式遍历链表接口
3.学习DVT开发者验证模式
4.用for循环改进了视频中对于每一个命令都AddLinkTableNode一次的代码模式。。
5.解决了了实验过程中的bug,linktable.c忘了gcc编译..导致menu.c调用时找不到linktable.c里定义的方法