[高级软件工程实验]用可重用的链表模块来实现命令行菜单小程序V2.5

版本库URL:https://github.com/swagnhen/Advanced-Software-Engineering-Exercise.git

实验要求

1)用可重用的链表模块来实现命令行菜单小程序,执行某个命令时调用一个特定的函数作为执行动作;
2)链表模块的接口设计要足够通用,命令行菜单小程序的功能保持不变;
3)可以将通用的Linktable模块集成到我们的menu程序中;
4)接口规范;

实验内容

可重用链表实现包含于linkedlist.h与linkedlist.c中
shell中各命令功能的实现包含在cmdopt.h与cmdopt.c中
main函数包含于shelllet.c中

通过gcc编译时请使用命令

gcc linkedlist.c cmdopt.c shelllet.c -o shelllet

可重用链表设计

typedef struct Node
{
    struct Node *next;
} Node;

typedef struct LinkedList
{
    Node *head;  /*指向链表头结点*/
    Node *tail;  /*指向链表尾节点*/
    int len;  /*记录链表长度*/
} LinkedList;

LinkedList *initLinkedList();  /*初始化整个链表*/

int delLinkedList(LinkedList *l);  /*删除整个链表*/

int addNode(LinkedList *l, Node *n);  /*向链表尾添加一个节点*/

int delNode(LinkedList *l, Node *n);  /*删除某一节点*/

Node *getHeadNode(LinkedList *l);  /*取链表头结点*/

Node *getNextNode(LinkedList *l, Node *n);  /*取节点n的下一个节点*/

功能指令链表节点设计

typedef struct CmdNode
{
    Node *next;
    char *cmd;  /*该节点所对应指令*/
    int (*handler)();  /*指令cmd所对应的功能函数*/
} CmdNode;

int initMenuData(LinkedList **l);  /*初始化功能指令链表*/

CmdNode *findCmd(LinkedList *head, char *cmd);  /*根据cmd字段寻找某一功能指令节点*/

具体实现
linkedlist.c

#include <stdio.h>
#include <stdlib.h>
#include "linkedlist.h"

LinkedList *initLinkedList()
{
    LinkedList *l = (LinkedList *)malloc(sizeof(LinkedList));
    if (l == NULL)
    {
        return NULL;
    }
    l->head = NULL;
    l->tail = NULL;
    l->len = 0;
    return l;
}

int delLinkedList(LinkedList *l)
{
    if (l == NULL)
    {
        return -1;
    }
    while (l->head != NULL)
    {
        Node *p = l->head;
        l->head = l->head->next;
        free(p);
        l->len--;
    }
    l->head = NULL;
    l->tail = NULL;
    l->len = 0;
    free(l);
    return 0;
}

int addNode(LinkedList *l, Node *n)
{
    if (l == NULL || n == NULL)
    {
        return -1;
    }
    if (l->head == NULL)
    {
        l->head = n;
    }
    if (l->tail == NULL)
    {
        l->tail = n;
    }
    else
    {
        l->tail->next = n;
        l->tail = n;
        l->tail->next = NULL;
    }
    l->len++;
    return 0;
}

int delNode(LinkedList *l, Node *n)
{
    if (l == NULL || n == NULL)
    {
        return -1;
    }
    if (l->head == n)
    {
        l->head = l->head->next;
        l->len--;
        if (l->len == 0)
        {
            l->tail = NULL;
        }
        return 0;
    }
    Node *temp = l->head;
    while (temp != NULL)
    {
        if (temp->next == n)
        {
            temp->next = temp->next->next;
            l->len--;
            if (l->len == 0)
            {
                l->tail = NULL;
            }
            return 0;
        }
        temp = temp->next;
    }
    return -1;
}

Node *getHeadNode(LinkedList *l)
{
    if (l == NULL || l->head == NULL)
    {
        return NULL;
    }
    return l->head;
}

Node *getNextNode(LinkedList *l, Node *n)
{
    if (l == NULL || n == NULL)
    {
        return NULL;
    }
    Node *temp = l->head;
    while (temp != NULL)
    {
        if (temp == n)
        {
            return temp->next;
        }
        temp = temp->next;
    }
    return NULL;
}

cmdopt.c

#include "cmdopt.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int initMenuData(LinkedList **l)
{
    *l = initLinkedList();

    CmdNode *p = (CmdNode *)malloc(sizeof(CmdNode));
    p->cmd = "add";
    p->handler = cmdAdd;
    addNode(*l, (Node *)p);

    p = (CmdNode *)malloc(sizeof(CmdNode));
    p->cmd = "minus";
    p->handler = cmdMinus;
    addNode(*l, (Node *)p);

    p = (CmdNode *)malloc(sizeof(CmdNode));
    p->cmd = "multiply";
    p->handler = cmdMultiply;
    addNode(*l, (Node *)p);

    p = (CmdNode *)malloc(sizeof(CmdNode));
    p->cmd = "divide";
    p->handler = cmdDivide;
    addNode(*l, (Node *)p);

    p = (CmdNode *)malloc(sizeof(CmdNode));
    p->cmd = "quit";
    p->handler = cmdQuit;
    addNode(*l, (Node *)p);

    p = (CmdNode *)malloc(sizeof(CmdNode));
    p->cmd = "showuid";
    p->handler = cmdShowUID;
    addNode(*l, (Node *)p);

    p = (CmdNode *)malloc(sizeof(CmdNode));
    p->cmd = "help";
    p->handler = cmdHelp;
    addNode(*l, (Node *)p);

    p = (CmdNode *)malloc(sizeof(CmdNode));
    p->cmd = "hello";
    p->handler = cmdHello;
    addNode(*l, (Node *)p);

    p = (CmdNode *)malloc(sizeof(CmdNode));
    p->cmd = "";
    p->handler = cmdElse;
    addNode(*l, (Node *)p);

    return 0;
}

CmdNode *findCmd(LinkedList *l, char *cmd)
{
    if (l == NULL || cmd == NULL)
    {
        return NULL;
    }
    CmdNode *p = (CmdNode *)getHeadNode(l);
    while (p != NULL)
    {
        if (strcmp(p->cmd, cmd) == 0)
        {
            return p;
        }
        p = (CmdNode *)getNextNode(l, (Node *)p);
    }
    p = l->tail;
    return p;
}

void cmdAdd()
{
    int a, b;
    printf(">>>");
    scanf("%i", &a);
    printf(">>>");
    scanf("%i", &b);
    printf(">>>%i\n", a + b);
}

void cmdMinus()
{
    int a, b;
    printf(">>>");
    scanf("%i", &a);
    printf(">>>");
    scanf("%i", &b);
    printf(">>>%i\n", a - b);
}

void cmdMultiply()
{
    int a, b;
    printf(">>>");
    scanf("%i", &a);
    printf(">>>");
    scanf("%i", &b);
    printf(">>>%i\n", a * b);
}

void cmdDivide()
{
    int a, b;
    printf(">>>");
    scanf("%i", &a);
    printf(">>>");
    scanf("%i", &b);
    printf(">>>%i\n", a / b);
}

void cmdHello()
{
    printf(">>>Welcome to shelllet!\n");
}

void cmdQuit()
{
    printf("**********Shelllet End**********\n");
    exit(0);
}

void cmdShowUID()
{
    printf(">>>UID: %i\n", getuid());
}

void cmdHelp()
{
    printf("|help\n");
    printf("|hello\n");
    printf("|add\n");
    printf("|minus\n");
    printf("|multiply\n");
    printf("|divide\n");
    printf("|showuid\n");
    printf("|quit\n");
}

void cmdElse()
{
    printf(">>>Wrong Commend\n");
}

shelllet.c

#include "cmdopt.h"
#include <stdio.h>
#include <string.h>

int main()
{
    LinkedList *l = NULL;
    initMenuData(&l);
    char cmd[128];
    printf("**********Shelllet Running**********\n");
    while (1)
    {
        printf(">>>");
        scanf("%s", cmd);
        CmdNode *p = findCmd(l, cmd);
        if (p != NULL && p->handler != NULL)
            p->handler();
    }
    return 0;
}

运行效果
这里写图片描述

实验总结与问题

上周没看视频没想到居然分离是指加个链表,真是失败
我就一直在想为什么要弄个链表,链表本身是动态扩充的,但是到我们这个项目里链表所包含的内容(命令行的各种函数)都是写死在代码段里的,动态容器存储静态内容,加功能还是得重新编译,这不是南辕北辙么?
不过孟大师是厉害,这课上的总能有意想不到的收获
后来想考虑Linux的shell实现,它的各种功能都对应一个文件。建一个链表,每次都扫描某一目录中的所有文件,这样就比较合理,还能直接通过增减文件控制shell功能
不过这样可能就比较复杂,还是得用系统调用
所以简化了一下这个简单shell就变成这样了吧

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值