实验报告_ASE_lab7

来源:互联网 发布:淘宝分销商 编辑:程序博客网 时间:2024/06/05 19:02

昵称:fuguanqi 《软件工程(C编码实践篇)》MOOC课程作业http://mooc.study.163.com/course/USTC-1000002006

实验七:将menu设计为可重用的子系统

实验要求

  • 为menu子系统设计接口,并写用户范例代码来实现原来的功能;

  • 使用make和make clean来编译程序和清理自动生成的文件;

  • 使menu子系统支持带参数的复杂命令,并在用户范例代码中自定义一个带参数的复杂命令;

  • 可以使用getopt函数获取命令行参数。

实验步骤:

编写程序代码
撰写Makefile文件
编译测试
这里写图片描述
这里写图片描述
这里写图片描述

提交git
这里写图片描述

Coding版本库URL:https://git.coding.net/fuguanqi/ASE.git

关键问题总结

  1. 输入命令时,会将换行符存入命令的结尾,需要将命令字符串最后的换行符用‘\0‘替换掉。
    这里写图片描述

  2. 多次调用Help函数时,getopt函数也会被多次调用,为了达到需求,必须在每次调用完Help函数时将getopt自身所带的全局变量optind进行归零,否则再次输入help命令或带选项的命令时,会影响程序的正常功能,并产生段错误。
    这里写图片描述

源代码

menu.c

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include "linktable.h"tLinkTable * head = NULL;int Help();#define CMD_MAX_LEN 1024#define CMD_MAX_ARGV_NUM 32#define DESC_LEN    1024#define CMD_NUM     10//char cmd[CMD_MAX_LEN];/* data struct and its operations */typedef struct DataNode{    tLinkTableNode * pNext;    char*   cmd;    char*   desc;    int     (*handler)(int argc, char *argv[]);} tDataNode;int SearchCondition(tLinkTableNode * pLinkTableNode, void * args){    char * cmd = (char*) args;    tDataNode * pNode = (tDataNode *)pLinkTableNode;    if(strcmp(pNode->cmd, cmd) == 0)    {        return  SUCCESS;      }    return FAILURE;        }/* find a cmd in the linklist and return the datanode pointer */tDataNode* FindCmd(tLinkTable * head, char * cmd){    return  (tDataNode*)SearchLinkTableNode(head,SearchCondition,(void*)cmd);}/* show all cmd in listlist */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;}// int InitMenuData(tLinkTable ** ppLinktable)// {//     *ppLinktable = CreateLinkTable();//     tDataNode* pNode = (tDataNode*)malloc(sizeof(tDataNode));//     pNode->cmd = "help";//     pNode->desc = "Menu List:";//     pNode->handler = Help;//     AddLinkTableNode(*ppLinktable,(tLinkTableNode *)pNode);//     pNode = (tDataNode*)malloc(sizeof(tDataNode));//     pNode->cmd = "version";//     pNode->desc = "Menu Program V1.0";//     pNode->handler = NULL; //     AddLinkTableNode(*ppLinktable,(tLinkTableNode *)pNode);//     pNode = (tDataNode*)malloc(sizeof(tDataNode));//     pNode->cmd = "quit";//     pNode->desc = "Quit from Menu Program V1.0";//     pNode->handler = Quit; //     AddLinkTableNode(*ppLinktable,(tLinkTableNode *)pNode);//     return 0; // }/* menu program */// tLinkTable * head = NULL;/* add cmd to menu */int MenuConfig(char * cmd, char * desc, int (*handler)(int argc, char * argv[])){    tDataNode * pNode = NULL;    if ( head== NULL)    {         head = CreateLinkTable();         pNode = (tDataNode*)malloc(sizeof(tDataNode));         pNode->cmd = "help";         pNode->desc = "Menu List:";         pNode->handler = Help;         AddLinkTableNode(head,(tLinkTableNode *)pNode);    }    pNode = (tDataNode*)malloc(sizeof(tDataNode));    pNode->cmd = cmd;    pNode->desc = desc;    pNode->handler = handler;    AddLinkTableNode(head,(tLinkTableNode *)pNode);    return 0; }/* Menu Engine Execute */int ExecuteMenu(){    //InitMenuData(&head);    /* cmd line begins */    while(1)    {        int argc = 0;        char * argv[CMD_MAX_ARGV_NUM];        char cmd[CMD_MAX_LEN];        char * pcmd = NULL;        printf("Input a cmd > ");        //scanf("%s", cmd);        //tDataNode *p = (tDataNode*)SearchLinkTableNode(head,SearchCondition,(void*)cmd);        pcmd = fgets(cmd, CMD_MAX_LEN, stdin);        if( pcmd == NULL)        {            //printf("This is a wrong cmd!\n ");            continue;        }        //        pcmd = strtok(pcmd," ");        while(pcmd != NULL && argc < CMD_MAX_ARGV_NUM)        {            argv[argc] = pcmd;            argc++;            pcmd = strtok(NULL, " ");        }        // if(argc == 1)        // {        //     int len = strlen(argv[0]);        //     *(argv[0] + len - 1) = '\0';        // }        int i;        for(i = 0 ; i < argc ; i++ )        {            if (i==argc-1)                    //replace the line break with "\0"            {                int len = strlen(argv[i]);                *(argv[i] + len - 1) = '\0';            }        }        tDataNode *p = (tDataNode*)SearchLinkTableNode(head,SearchCondition,(void*)argv[0]);        if( p == NULL)        {            printf("This is a wrong cmd!\n");            continue;        }        if(p->handler != NULL)         {             p->handler(argc,argv);        }        printf("%s - %s\n", p->cmd, p->desc);     }}static const char *optString = "abcde";int Help(int argc, char * argv[]){    ShowAllCmd(head);    int opt;    while((opt = getopt (argc, argv,optString)) != -1)    {        switch (opt)        {            case 'a' :               printf ("\nOption a\n\n" );               break ;            case 'b' :               printf ("\nOption b\n\n" );               break ;            case 'c' :               printf ("\nOption c\n\n");               break ;            case 'd' :               printf ("\nOption d\n\n" );               break ;            case 'e' :               printf ("\nOption e\n\n" );               break ;        }    }    optind=0;                //reset the function getopt    return 0; }

test.c

#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include"menu.h"int Quit(int argc, char * argv[]){    /* add XXX clean ops */    exit(0);}int main (){    MenuConfig("version","XXX V1.0(Menu program v1.0 inside)", NULL);    MenuConfig("quit","Quit from XXX", Quit);    ExecuteMenu();}

Makefile

CC_PTHREAD_FLAGS           = -lpthreadCC_FLAGS                   = -cCC_OUTPUT_FLAGS            = -oCC                         = gccRM                         = rmRM_FLAGS                   = -fTARGET   =   test1OBJS     =   linktable.o menu.o test.oall:   $(OBJS)    $(CC) $(CC_OUTPUT_FLAGS) $(TARGET) $(OBJS).c.o:    $(CC) $(CC_FLAGS) $<clean:    $(RM) $(RM_FLAGS) $(OBJS) $(TARGET) *.bak
原创粉丝点击