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

来源:互联网 发布:小米账号破解软件 编辑:程序博客网 时间:2024/06/08 00:56

版本库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
原创粉丝点击