用可重用的链表模块来实现命令行菜单小程序V2.5

这一篇对应课程的第四次实验。

网易云课堂:http://mooc.study.163.com/learn/USTC-1000002006?tid=1000081002#/learn/announce
实验楼:https://www.shiyanlou.com/courses/122
代码库:http://git.shiyanlou.com/chenxu/shiyanlou_cs122

实验思路

实现一个通用链表,并实现创建链表以及增、删、查找节点等功能,在menu.c中使用这个链表保存命令信息, 通过链表提供的方法实现数据节点的初始化和查找。

实验过程

  • 首先在linktable.h文件中定义链表节点和链表,再声明初始化链表函数、增加节点函数、删除节点函数、返回下一个节点的函数(用于遍历)等;
  • 初始化链表函数CreateLinkTable,创建一个链表头指针并开辟内存空间,把它的头节点和尾节点设为空,返回链表指针;
  • 插入节点函数AddLinkTableNode,将给定节点插入到链表尾部;
  • 删除节点函数DelLinkTableNode,先查找节点的前置节点,如果找到则利用前置节点将待删除节点从链表上去除,并释放节点空间;
  • 在menu.c中,先初始化命令链表,将命令节点强转成链表节点逐个添加到链表中,在遍历链表时需要将链表节点强转成命令节点。然后读取节点中信息。

实验难点

双指针

int initMenu(tLinkTable** ppLinkTable) 中使用了双指针,具体调用时 initMenu(&head); 使用了head的地址。原因如下:

  • head在声明时 tLinkTable* head = NULL; 是NULL,不能直接使用,但是head本身的地址不为空(使用&取地址符获得);
  • 在initMenu函数中用head接受CreateLinkTable函数返回的指针( *ppLinkTable = CreateLinkTable() );

CreateLinkTable的函数定义:

tLinkTable * CreateLinkTable()
{
    tLinkTable * head = (tLinkTable*)malloc(sizeof(tLinkTable));
    if (head == NULL)
    {
        return NULL;
    }
    head->pHead = head->pTail = NULL;
    head->SumOfNode = 0;
    //head->mutex = PTHREAD_MUTEX_INITIALIZER;
    return head;
}

head指向新分配的内存空间,然后将空间首地址返回。

指针转换

在 initMenu 添加节点时,先创建 tDataNode 类型的节点,存上数据,再强转成 tLinkTableNode 类型的节点加入到链表中:

tDataNode* pNode = (tDataNode*)malloc(sizeof(tDataNode));
pNode->cmd = "help";
pNode->desc = "Menu List:";
pNode->handler = Help;
AddLinkTableNode(*ppLinkTable, (tLinkTableNode *)pNode);

在遍历链表获取节点信息时,再将 tLinkTableNode 类型转化为 tDataNode 类型:

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;
}

其实转化的只是节点的指针类型(节点声明的struct里要把pNext放在第一项),在访问时根据地址和数据长度可以读取到对应的数据。

函数指针

DataNode的数据结构:

typedef struct DataNode
{
    tLinkTableNode *pNext;
    char*  cmd;
    char*  desc;
    int    (*handler)();
} tDataNode;

其中handler是指向返回值为 int 、参数为空的函数的指针,通过函数名可以调用的对应的函数。

实验结论

这次实验的链表更具有通用性和复用性,所有与命令小程序有关的操作都在menu.c中实现。本次实验的难点在于链表函数的编写,以及将命令节点和链表节点之间进行转换的理解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值