首页 > 代码库 > 闲云控制台(一)控制台命令解析框架

闲云控制台(一)控制台命令解析框架

发布闲云控制台连载系列,会不定期加入新功能~

先发一个命令解析的框架


/**************************************************
*******************闲云万能控制台*********************
*********
*********    作者: 闲云野鹤
*********     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 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;					//处理函数
}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)
{
	for (unsigned int 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);
}
/****************************************
***命令处理区
      命令的执行区,对每个命令进行各自的处理
	  ****需不断添加功能****
	  Help函数里的帮助信息建议实时更新~
	  每个函数格式都应为
		 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");
	printf("    help\t\t显示帮助信息\n");
	printf("    hello\t\t显示欢迎信息\n");
	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);
void Register_Cmd()
{
	_register_one_cmd("hello", Hello);
	_register_one_cmd("help", Help);
}
void _register_one_cmd(char* _cmd_name, CMD_FUN _fun)
{
	strcpy(KEEP_CMD[CUR_CMD_NUM].Cmd_Name, _cmd_name);
	KEEP_CMD[CUR_CMD_NUM]._Fun = _fun;
	++CUR_CMD_NUM;
}
/**********************************************
***信息提示区
		用于各种错误、返回值的处理和交互
***********************************************/
void ResultVal_Deal(int re)
{
	switch (re)
	{
	case OK:
		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;
	}
}
void 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;
}

闲云控制台(一)控制台命令解析框架