发布闲云控制台连载系列,会不定期加入新功能~
先发一个命令解析的框架
/*********************************************************************闲云万能控制台*************************************** 作者: 闲云野鹤********* QQ: 836663997********* QQ群: 116920287 欢迎加入********* 邮箱: xianyun1230@163.com********* 博客: blog.csdn.net/xianyun2009****************** 功能会一直更新!***************************************************/#define _CRT_SECURE_NO_WARNINGS //vs中关闭安全开发周期(SDL)检测#include#include #include #include #include #include /***定义控制台的支持能力***/#define MAX_CMD 100 //支持命令的最大数目#define LEN_CMD 50 //命令中名称的最大的长度#define LEN_ARGU 50 //命令中参数的最大的长度 #define LEN_OBJ 900 //命令中命令对象的最大的长度#define LEN_SUMMARY 100 //命令简介长度/***用于处理区返回执行状态***/#define OVER_CMD 5 //命令名称太长#define OVER_ARGU 6 //命令参数太长#define OVER_OBJ 7 //命令对象太长/***用于执行区命令返回执行状态***/#define NO 0 //执行失败#define OK 1 //执行成功#define ERR_NOCMD 2 //命令错误#define ERR_ARGU 3 //参数错误#define ERR_NOOBJ 4 //对象错误typedef struct //输入命令的结构{ char Cmd_Name[LEN_CMD + 1]; //命令名称 char Cmd_Arguments[LEN_ARGU + 1]; //参数列表 char Cmd_Object[LEN_OBJ + 1]; //命令对象}Command, *pCommand;typedef int (*CMD_FUN)(pCommand);typedef struct //命令结构,存放支持的命令{ char Cmd_Name[LEN_CMD]; //命令名称 CMD_FUN _Fun; //处理函数 char Cmd_Summary[LEN_SUMMARY];}CMD_ITEM, *pCMD_ITEM;CMD_ITEM KEEP_CMD[MAX_CMD] = { 0 }; //用于存放注册命令unsigned int CUR_CMD_NUM = 0; //当前已注册命令数目/**************************************处理命令*************************** 进行转换和分发命令****************************************************//***转换命令***/int Translate_Command(char* _cmd_str, pCommand _cmd){ memset(_cmd, 0, sizeof(Command)); //_cmd全部置0 while ('\0' != *_cmd_str && isspace(*_cmd_str)) //清除命令两端空格类字符 ++_cmd_str; int _len = strlen(_cmd_str) - 1; while (_len >= 0 && isspace(*(_cmd_str + _len))) *(_cmd_str + _len--) = '\0'; //分割命令 char* p_str = strchr(_cmd_str, ' '); if (!p_str) { if (_len + 1 > LEN_CMD) //命令名称太长 return OVER_CMD; strcpy(_cmd->Cmd_Name, _cmd_str); //分离命令名称 } else { if (p_str - _cmd_str > LEN_CMD) //命令名称太长 return OVER_CMD; strncpy(_cmd->Cmd_Name, _cmd_str, p_str - _cmd_str); //分离命令名称 while ('\0' != *p_str && isspace(*p_str)) ++p_str; if ('-' == *p_str) //检测参数标识'-' { ++p_str; char* p_space = strchr(p_str, ' '); if (p_space) { if (p_space - p_str > LEN_ARGU) //命令参数太长 return OVER_ARGU; strncpy(_cmd->Cmd_Arguments, p_str, p_space - p_str); //分离参数 while ('\0' != p_space && isspace(*p_space)) ++p_space; if (strlen(p_space) > LEN_OBJ) //命令对象太长 return OVER_OBJ; strcpy(_cmd->Cmd_Object, p_space); //分离命令对象 } else { if (strlen(p_str) > LEN_ARGU) //命令参数太长 return OVER_ARGU; strcpy(_cmd->Cmd_Arguments, p_str); //分离参数 } } else { if (strlen(p_str) > LEN_OBJ) //命令对象太长 return OVER_OBJ; strcpy(_cmd->Cmd_Object, p_str); //分离命令对象 } } return OK;}/***检验命令是否已注册并返回指针***/const pCMD_ITEM Loc_Command(pCommand _cmd){ unsigned int i; for (i = 0; i < CUR_CMD_NUM; ++i) { if (0 == strcmp(_cmd->Cmd_Name, KEEP_CMD[i].Cmd_Name)) return &KEEP_CMD[i]; } return NULL; //无此命令}/***分发命令***/int Dispatch_Command(pCommand _cmd){ //printf("Dispatch command:%s<-\targu:%s<-\tobj:%s<-\n", _cmd->Cmd_Name, _cmd->Cmd_Arguments, _cmd->Cmd_Object); const pCMD_ITEM ploc = Loc_Command(_cmd); if (NULL == ploc) return ERR_NOCMD; return ploc->_Fun(_cmd);}/*******************************************命令处理区 命令的执行区,对每个命令进行各自的处理 ****需不断添加功能**** 每个函数格式都应为 int NAME(pCommand ); NAME为函数名 注意:!每个函数都应返回一个执行状态,状态详细 内容见上方'执行区命令返回状态'!****************************************/int Hello(pCommand b){ printf("\t\t欢迎来到闲云万能控制台!\n\t Welcome to xianyun Super Console!\n"); return OK;}int Help(pCommand b){ Hello(b); printf("\n"); printf(" 命令\t\t简介\n"); int i; for (i = 0; i < CUR_CMD_NUM; i++) { printf(" %s\t\t%s\n", KEEP_CMD[i].Cmd_Name, KEEP_CMD[i].Cmd_Summary); } printf("\n 命令格式: 命令名称 [-参数] [对象] 例如:help -arv hello 参数和对象可省略\n"); printf(" 注意参数中每个字符都算作一个一个参数,即例子中有三个参数a、r、v\n"); return OK;}/*************************************************注册区 每个命令都应在这里注册******************** 每个在命令处理区定义的命令都应仿照 _register_one_cmd("命令名称", 映射函数名称, "功能简介"); 格式在下面注册,否则将无法识别 注意: 命令名称大小写敏感!***********************************************/void _register_one_cmd(char* _cmd_name, CMD_FUN _fun, char* _cmd_summary);void Register_Cmd(){ _register_one_cmd("hello", Hello, "显示欢迎信息"); _register_one_cmd("help", Help, "显示帮助信息");}void _register_one_cmd(char* _cmd_name, CMD_FUN _fun, char* _cmd_summary){ strcpy(KEEP_CMD[CUR_CMD_NUM].Cmd_Name, _cmd_name); strcpy(KEEP_CMD[CUR_CMD_NUM].Cmd_Summary, _cmd_summary); KEEP_CMD[CUR_CMD_NUM]._Fun = _fun; ++CUR_CMD_NUM;}/*************************************************信息提示区 用于各种错误、返回值的处理和交互***********************************************/void ResultVal_Deal(int re){ switch (re) { case OK: return; case NO: printf("命令未能成功执行,请检测您的指令是否正确!\n"); return; case ERR_NOCMD: printf("命令无法识别!\n"); return; case ERR_ARGU: printf("命令参数错误!\n"); return; case ERR_NOOBJ: printf("命令对象错误!\n"); return; case OVER_CMD: printf("命令名称太长!\n"); return; case OVER_ARGU: printf("命令参数太长!\n"); return; case OVER_OBJ: printf("命令对象太长!\n"); return; }}int main(){ char cmd_str[1024]; int result = 0; Command _cmd; Register_Cmd(); Help(&_cmd); while (1) { printf(">"); gets(cmd_str); result = Translate_Command(cmd_str, &_cmd); ResultVal_Deal(result); if (OK == result) { result = Dispatch_Command(&_cmd); ResultVal_Deal(result); } } return 0;}