发布闲云控制台连载系列,会不定期加入新功能~
先发一个命令解析的框架
/**************************************************
*******************闲云万能控制台*********************
*********
********* 作者: 闲云野鹤
********* QQ: 836663997
********* QQ群: 116920287 欢迎加入
********* 邮箱: xianyun1230@163.com
********* 博客: blog.csdn.net/xianyun2009
*********
********* 功能会一直更新!
***************************************************/
#define _CRT_SECURE_NO_WARNINGS //vs中关闭安全开发周期(SDL)检测
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <memory.h>
#include <conio.h>
/***定义控制台的支持能力***/
#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;
}