我的微控制器有一个RS232接口,带有一组预定义的命令。有几百个命令,例如PRESSURE 50
可以设定压力为50; LIMIT 60
可以设置为60的限制。
目前,这是使用一系列嵌套的switch语句处理的,但这似乎是一个不优雅的解决方案。
处理这些命令的建议/最有效/最可读的方法是什么? LUT会是最整洁的,但肯定会有很多空字符组合的空条目(不理想..)。
感谢任何想法..
答案 0 :(得分:2)
运行时提案:
使用排序数组struct {string,function pointer)
我希望您的平台中提供qsort()
和bsearch()
(stdlib.h
)
设计时提案:
正如评论所示,最好在设计时对数组初始化的条目进行排序。存在很多方法,从代码生成(豪华)到宏观处理(差)。
宣言的建议,一对多:
typedef unsigned char byte;
typedef char commandId_t[40];
typedef void (*commandHandler_t)( const byte * payload );
typedef struct command_s {
const commandId_t commandId;
const commandHandler_t handler;
} command_t;
static const command_t commands[] = {
#include "sortedCommandInitializers"
};
文件sortedCommandInitializers
是{"command-name", function-name},
的列表,可以按Makefile中的sort CommandInitializers.c > sortedCommandInitializers
命令排序。
对于make
,它与其他任何依赖项一样:
sortedCommandInitializers: CommandInitializers.c
sort CommandInitializers.c > sortedCommandInitializers
myProgram.o: myProgram.c myProgram.h sortedCommandInitializers
答案 1 :(得分:2)
曾经尝试过strnstr功能吗?它真的非常快。对于几百个单词,它可能比8或9个单独的strcmp()更快,其间有一些额外的代码来遍历一个树,并且需要更少的内存来存储。
我会尝试以下
a)建立一个命令列表并在开头放置最常见的命令,并为每个命令添加一个唯一的编号。
char command_names[] =
"PRESSURE 1"
"LIMIT 2"
;
int command_names_len = sizeof(command_names_str)
C编译器应该为您附加这些字符串,因此很容易将它们移动到另一个位置
b)添加的这些数字是函数指针数组的索引,每个函数应该具有相同的签名,当你允许某些函数有未使用的参数时,这可能是可能的吗? 即。
/* just an example */
void (command*)(int a, int b, int c, int d);
void command_pressure (int a, int b, int c, int d) { }
void command_limit(int a, int b, int c, int d) { }
command commands[] =
( /*notused*/ NULL
, /* 1 */ command_pressure
, /* 2 */ command_limit
);
这两个列表在视觉上也会相互匹配,使控制和维护变得更容易。注释中的数字仅用于帮助,并且应与大字符串构建中的数字与函数名称
匹配然后处理传入的命令是字符串格式非常简单
char search_command[20]; /* or whatever the longest command name is */
char* position_of_command = NULL;
int number_of_command = -1;
strncpy( search_command, incomming_command, sizeof(search_command) );
strcat( search_command, " " ); /* must end with blank */
command_position = strnstr( command_names, search_command, command_names_len );
if( command_position != NULL ) {
position_of_command += strlen(s earch_command) ; /* at beginning of number */
number_of_command = atoi( position_of_command );
}
if( number_of_command > 0 ) {
(*commands[number_of_command])(a,0,0,d);
} else {
/* unknown */
}
前段时间我写过普通的旧C,所以它可能包含语法错误,但这就是想法。
优点:
a)小内存打印:没有额外的指针或其他额外的结构开销来查找命令,很少有编程行
b)维护简单:它是“桌子”组织的
c)最常用的命令处理速度最快!
缺点:
a)请记住,不允许以相同字符串结尾的命令。可以通过在名称的开头添加空格来解决,也可以在search_command处添加空格。即。
" PRESSURE 1"
" LIMIT 2"