命令解析器(使用红黑树实现)

本文介绍了如何使用红黑树设计命令解析器,通过将命令名作为红黑树键值,实现命令的注册、注销及功能调用。通过函数指针实现模块去耦合,降低后期维护成本。详细讲解了底层框架的注册、注销、功能调用函数以及比较函数的实现,并给出了应用实例。

1.设计思路

前段时间研究了一下红黑树,趁着今天有时间,就使用红黑树实现了一下命令解析器。

        命令解析器的原则是根据输入的命令,调用相关命令的功能。命令的名字作为红黑树的键值,而相关命令的功能实现则设计为键值。因此红黑树的实现作为了命令解析器的数据结构组织手段。

增加和减少命令时,尽量不需要跨文件的修改(如果只有几个命令,可能可以接受,但是后期维护也是相当大的工作量)。

        命令的相关功能调用,为了达到相关文件以及模块的去耦合作用,使用函数指针进行实现。

底层的框架实现命令的注册以及注销,相关命令的功能调用等。而使用这些调用接口的则将会在具体的功能文件中进行,这样达到了增删等动作不需要改动底层的框架,而只需要在自己的功能文件中进行即可。

2.具体实现

红黑树的实现可参照之前的实现。

2.1底层框架(cmd)

底层框架只需要给功能函数提供注册,注销,命令功能函数的调用,以及添加到红黑树时的比较规则函数即可。

2.1.1 注册函数

注册函数就是调用了红黑树的put函数,将命令存放到红黑树中。
void register_cmd(struct entry ** cmds_node, char *name, handler cmd_operate)
{
	put(cmds_node, (void *)name, (void *) cmd_operate);
}

2.1.2注销函数

注销函数就是调用了红黑树的delete函数,将命令从红黑树中删除。
void unregister_cmd(struct entry ** cmds_node, char *name)
{
	struct entry * p = NULL;
	p = get(*cmds_node, (void *)name);
	if(NULL != p)
		delete_entry(cmds_node, p);
	else
		printf("unregister cmd (the cmd is not in the cmds node!\n");
}

2.1.3 调用命令的功能函数

通过键获取节点的值,直接调用该功能函数即可。

void match_cmd(struct entry * cmds_node, char * name)
{
	struct entry * x;
	x = get(cmds_node, (void *)name);
	if(NULL != x) {
		handler cmd_operate = (handler)x->data;
		cmd_operate((void *)name);	
	} else {
		printf("match cmd(the cmd is not in the cmds node!\n");
	}
}

2.1.4 比较函数

因为输入的命令都是字符串,因此红黑树中的比较函数需要实现为字符串的比较。

int string_cmp(void * str1, void * str2)
{
	assert(NULL != str1 && NULL != str2);
	return strncmp((char*)str1, (char*)str2, strlen(str1) >= strlen(str2) ? strlen(str1):strlen(str2));
}

3.应用实例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "cmd.h"
static void cmd_1(void * data)
{
	printf("this is the the cmd %s!\n", (char *)data);
}

static void cmd_2(void * data)
{
	printf("this is the the cmd %s!\n", (char *)data);
}

static void cmd_3(void * data)
{
	printf("this is the the cmd %s!\n", (char *)data);
}

static void cmd_4(void * data)
{
	printf("this is the the cmd %s!\n", (char *)data);
}

static void cmd_5(void * data)
{
	printf("this is the the cmd %s!\n", (char *)data);
}
int main(void)
{
	struct entry * tree = NULL;//定义指针的时候需要赋初值,不然可能造成错误
	char str_cmd[30] = {0};
	register_cmd(&tree, (void *)"cmd_1", (handler)cmd_1);
	tree->cmp = string_cmp;
	register_cmd(&tree, (void *)"cmd_2", (handler)cmd_2);
	register_cmd(&tree, (void *)"cmd_3", (handler)cmd_3);
	register_cmd(&tree, (void *)"cmd_4", (handler)cmd_4);
	register_cmd(&tree, (void *)"cmd_5", (handler)cmd_5);
	while(1) {
		scanf("%s", str_cmd);
		if(!strncmp(str_cmd, "done", strlen("done"))){
			printf("this is done\n");
			break;
		}
		match_cmd(tree, str_cmd);
	}
	return 0;
}
在实际的应用中,功能的文件肯定不止一个,因此最开始的红黑树肯定需要作为所以文件的共有变量。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值