软件工程(C编码实践篇) 第七次作业实验报告

来源:互联网 发布:淘宝女士春装 编辑:程序博客网 时间:2024/06/07 10:49

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

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

实验要求

  • 为menu子系统设计接口,并写用户范例代码来实现原来的功能;
  • 使用make和make clean来编译程序和清理自动生成的文件;
  • 使menu子系统支持带参数的复杂命令,并在用户范例代码中自定义一个带参数的复杂命令;
  • 可以使用getopt函数获取命令行参数。

实验过程

1.建立远程仓库,并下载到本地,远程仓库地址:https://github.com/libaoquan95/seClass_lab7.git

git clone https://github.com/libaoquan95/seClass_lab7.git

并进入版本库并创建相关文件
这里写图片描述

2 linktable.h

#ifndef _LINK_TABLE_H_#define _LINK_TABLE_H_#include <pthread.h>#define SUCCESS 0#define FAILURE (-1)/* * LinkTable Node Type */typedef struct LinkTableNode tLinkTableNode;/* * LinkTable Type */typedef struct LinkTable tLinkTable;/* * Create a LinkTable */tLinkTable * CreateLinkTable();/* * Delete a LinkTable */int DeleteLinkTable(tLinkTable *pLinkTable);/* * Add a LinkTableNode to LinkTable */int AddLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);/* * Delete a LinkTableNode from LinkTable */int DelLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);/* * Search a LinkTableNode from LinkTable * int Conditon(tLinkTableNode * pNode); */tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable,                                      int Conditon(tLinkTableNode * pNode,                                                   void * args),                                      void * args);/* * get LinkTableHead */tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable);/* * get next LinkTableNode */tLinkTableNode * GetNextLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);#endif /* _LINK_TABLE_H_ */

3 linktable.c

#include<stdio.h>#include<stdlib.h>#include"linktable.h"typedef struct LinkTableNode{    struct LinkTableNode * pNext;}tLinkTableNode;typedef struct LinkTable{    tLinkTableNode *pHead;    tLinkTableNode *pTail;    int            SumOfNode;    pthread_mutex_t mutex;}tLinkTable;/* * Create a LinkTable */tLinkTable * CreateLinkTable(){    tLinkTable * pLinkTable = (tLinkTable *)malloc(sizeof(tLinkTable));    if(pLinkTable == NULL)    {        return NULL;    }    pLinkTable->pHead = NULL;    pLinkTable->pTail = NULL;    pLinkTable->SumOfNode = 0;    pthread_mutex_init(&(pLinkTable->mutex), NULL);    return pLinkTable;}/* * Delete a LinkTable */int DeleteLinkTable(tLinkTable *pLinkTable){    if(pLinkTable == NULL)    {        return FAILURE;    }    while(pLinkTable->pHead != NULL)    {        tLinkTableNode * p = pLinkTable->pHead;        pthread_mutex_lock(&(pLinkTable->mutex));        pLinkTable->pHead = pLinkTable->pHead->pNext;        pLinkTable->SumOfNode -= 1 ;        pthread_mutex_unlock(&(pLinkTable->mutex));        free(p);    }    pLinkTable->pHead = NULL;    pLinkTable->pTail = NULL;    pLinkTable->SumOfNode = 0;    pthread_mutex_destroy(&(pLinkTable->mutex));    free(pLinkTable);    return SUCCESS;        }/* * Add a LinkTableNode to LinkTable */int AddLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode){    if(pLinkTable == NULL || pNode == NULL)    {        return FAILURE;    }    pNode->pNext = NULL;    pthread_mutex_lock(&(pLinkTable->mutex));    if(pLinkTable->pHead == NULL)    {        pLinkTable->pHead = pNode;    }    if(pLinkTable->pTail == NULL)    {        pLinkTable->pTail = pNode;    }    else    {        pLinkTable->pTail->pNext = pNode;        pLinkTable->pTail = pNode;    }    pLinkTable->SumOfNode += 1 ;    pthread_mutex_unlock(&(pLinkTable->mutex));    return SUCCESS;        }/* * Delete a LinkTableNode from LinkTable */int DelLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode){    if(pLinkTable == NULL || pNode == NULL)    {        return FAILURE;    }    pthread_mutex_lock(&(pLinkTable->mutex));    if(pLinkTable->pHead == pNode)    {        pLinkTable->pHead = pLinkTable->pHead->pNext;        pLinkTable->SumOfNode -= 1 ;        if(pLinkTable->SumOfNode == 0)        {            pLinkTable->pTail = NULL;            }        pthread_mutex_unlock(&(pLinkTable->mutex));        return SUCCESS;    }    tLinkTableNode * pTempNode = pLinkTable->pHead;    while(pTempNode != NULL)    {            if(pTempNode->pNext == pNode)        {            pTempNode->pNext = pTempNode->pNext->pNext;            pLinkTable->SumOfNode -= 1 ;            if(pLinkTable->SumOfNode == 0)            {                pLinkTable->pTail = NULL;                }            pthread_mutex_unlock(&(pLinkTable->mutex));            return SUCCESS;                            }        pTempNode = pTempNode->pNext;    }    pthread_mutex_unlock(&(pLinkTable->mutex));    return FAILURE;        }/* * Search a LinkTableNode from LinkTable * int Condition(tLinkTableNode * pNode); */tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Condition(tLinkTableNode * pNode, void * args), void * args){    if(pLinkTable == NULL || Condition == NULL)    {        return NULL;    }    tLinkTableNode * pNode = pLinkTable->pHead;    while(pNode != NULL)    {            if(Condition(pNode, args) == SUCCESS)        {            return pNode;                            }        pNode = pNode->pNext;    }    return NULL;}/*  * get LinkTableHead*/tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable){    if(pLinkTable == NULL)    {        return NULL;    }        return pLinkTable->pHead;}/* * get next LinkTableNode */tLinkTableNode * GetNextLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode){    if(pLinkTable == NULL || pNode == NULL)    {        return NULL;    }    tLinkTableNode * pTempNode = pLinkTable->pHead;    while(pTempNode != NULL)    {            if(pTempNode == pNode)        {            return pTempNode->pNext;                            }        pTempNode = pTempNode->pNext;    }    return NULL;}

4 menu.h

#ifndef _menu#define _menuint MenuConfig(char * cmd, char * desc, void (*handler)(int argc, char *argv[]));int ExecuteMenu();#endif

5 menu.c

#include <stdio.h>#include <stdlib.h>#include <string.h>#include "linktable.h"#include "menu.h"#define CMD_MAX_LEN      128#define CMD_MAX_ARGV_LEN 128#define DESC_LEN         1024#define CMD_NUM          10tLinkTable * head = NULL;void Help(int argc, char *argv[]);/* data struct and its operations */typedef struct DataNode{    tLinkTableNode * pNext;    char*   cmd;    char*   desc;    void     (*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);    printf("-------------------------------------------------------------------\n");    while(pNode != NULL)    {        printf("\t\t %s: \t\t %s\n", pNode->cmd, pNode->desc);        pNode= (tDataNode*)GetNextLinkTableNode(head, (tLinkTableNode*)pNode);    }    printf("-------------------------------------------------------------------\n");    return 0;}int MenuConfig(char * cmd, char * desc, void (*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);}int ExecuteMenu(){    while(1)    {        int argc = 0;        char *argv[CMD_MAX_ARGV_LEN];        char cmd[CMD_MAX_LEN];        char *pcmd = NULL;        printf("Input command > ");        pcmd = fgets(cmd, CMD_MAX_LEN, stdin);        if (pcmd == NULL)        {            continue;        }        pcmd = strtok(pcmd, " ");        while (pcmd != NULL && argc < CMD_MAX_ARGV_LEN)        {            argv[argc] = pcmd;            argc++;            pcmd = strtok(NULL, " ");        }        if (argc == 1)        {            int len = strlen(argv[0]);            *(argv[0] + len - 1) = '\0';        }        tDataNode *p = FindCmd(head, argv[0]);        if( p == NULL)        {            printf("This is a wrong cmd!\n ");            continue;        }        printf("%s - %s\n", p->cmd, p->desc);         if(p->handler != NULL)         {             p->handler(argc, argv);        }    }}void Help(int argc, char *argv[]){    ShowAllCmd(head);}

6.mymenu.c
mymenu.c 利用通用的menu,生成自己的命令行程序。利用argv 和 argc ,实现从输入的命令中提取参数,实现带参数的命令的设计。

/* * Copyright (C) libaoquan95@github.com, 2017-2018 * * File name                  : mymenu.c * Principal author           : libaoquan95 * Subsystem name             : mymenu * Module name                : mymenu * Language                   : C  * Date of first release      : 2017/10/28 * Deacription                : This is a mymenu program*/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <time.h>#include "menu.h"void PrintSystemTime(int argc, char *argv[]);void PrintCurrentWorkingDirectory(int argc, char *argv[]);void Add(int argc, char *argv[]);void Sub(int argc, char *argv[]);void Mul(int argc, char *argv[]);void Div(int argc, char *argv[]);void Quit(int argc, char *argv[]);int main(int argc,char* argv[]){    MenuConfig("time", "Show system time",                           PrintSystemTime);    MenuConfig("pwd", "Show current working directory",              PrintCurrentWorkingDirectory);    MenuConfig("pwd", "Show current working directory",              PrintCurrentWorkingDirectory);    MenuConfig("add", "Calculate the summarize of the two integer numbers",      Add);    MenuConfig("sub", "Calculate the subtractions of the two integer numbers",   Sub);    MenuConfig("mul", "Calculate the multiplication of the two integer numbers", Mul);    MenuConfig("div", "Calculate the division of the two integer numbers",       Div);    MenuConfig("quit", "Exit menu program",                         Quit);    ExecuteMenu();}/** * print current time * @param none * @return none */void  PrintSystemTime(int argc, char *argv[]){    struct tm *ptr;    time_t it;    it = time(NULL);    ptr = localtime(&it);    printf("%4d年%02d月%02d日  %d:%d:%d\n", ptr->tm_year + 1900, ptr->tm_mon + 1, ptr->tm_mday,                                           ptr->tm_hour, ptr->tm_min,ptr->tm_sec);}/** * print current working directory path * @param none * @return none */void  PrintCurrentWorkingDirectory(int argc, char *argv[]){    char buf[256];    getcwd(buf, sizeof(buf));    printf("当前路径:  %s\n", buf);}/** * calculate add of two interage numbers * @param none * @return calculate result */ void  Add(int argc, char *argv[]) {    if(argc != 3)    {        printf("error count of calculate\n");    }    int num1 = atoi(argv[1]), num2 = atoi(argv[2]);    printf("%d + %d = %d\n", num1, num2, num1 + num2); } /**  * calculate sub of two interage numbers  * @param none  * @return calculate result  */ void  Sub(int argc, char *argv[]) {    if(argc != 3)    {        printf("error count of calculate\n");    }    int num1 = atoi(argv[1]), num2 = atoi(argv[2]);    printf("%d - %d = %d\n", num1, num2, num1 - num2); } /**  * calculate mul of two interage numbers  * @param none  * @return calculate result  */ void  Mul(int argc, char *argv[]) {    if(argc != 3)    {        printf("error count of calculate\n");    }    int num1 = atoi(argv[1]), num2 = atoi(argv[2]);    printf("%d * %d = %d\n", num1, num2, num1 * num2); } /**  * calculate div of two interage numbers  * @param none  * @return calculate result  */ void  Div(int argc, char *argv[]) {    if(argc != 3)    {        printf("error count of calculate\n");    }    int num1 = atoi(argv[1]), num2 = atoi(argv[2]);    if(num2 != 0)    {        printf("%d / %d = %d\n", num1, num2, num1 / num2);    }    else    {        printf("ERROR: don't division 0\n");    } } /**  * quit command  * @param none  * @return none  */ void  Quit(int argc, char *argv[]) {     exit(0); }

7.makefile
makefile文件中,缩进要用tab键,使用空格缩进会产生错误。

CC_PTHREAD_FLAGS   = -lpthreadCC_FLAGS           = -cCC_OUTPUT_FLAGS    = -oCC                 = gccRM                 = rmRM_FLAGS           = -fTARGET             = mymenuOBJS               = linktable.o menu.o mymenu.oall:    $(OBJS)    $(CC) $(CC_OUTPUT_FLAGS) $(TARGET) $(OBJS).c.o:    $(CC) $(CC_FLAGS) $<clean:    $(RM) $(RM_FLAGS) $(OBJS) $(TARGET) *.bak  

8.编译程序并运行
这里写图片描述
这里写图片描述
9.上传至远程版本库
这里写图片描述
这里写图片描述


实验总结

远程仓库地址:https://github.com/libaoquan95/seClass_lab7.git

  • makefile 文件
  • 因为Makefile文件的存在,所以可以使用make命令来编译。makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。主要是三部分内容,先是为menu子系统设计接口,将menu设计为可重用的子系统。然后是Makefile,使得编译的时候不需要再去敲打命令,麻烦,直接执行make就可以了,而且还可以make clean删除编译产生出的文件。

  • 可重用设计

  • menu作为一个子系统的可重用接口设计:(1)手里有把锤子,看哪里都是钉子;(2)够用就好—不要太具体,也不要太通用。

  • 支持带参数的复杂命令的方法

  • shell将命令行解析成argc和argv传递给执行程序;
  • 定义一个函数将命令行转换成argc和argv;(3)自定义处理函数内部可以使用getopt函数来获取参数。
阅读全文
0 0