我的微控制器有一个 RS232 接口,带有一组预定义的命令。有数百个命令,例如PRESSURE 50
可以将压力设置为 50;LIMIT 60
可以设置一些限制为60。
当前,这是使用一系列嵌套的 switch 语句处理的,但这似乎是一个不雅的解决方案。
处理这些命令的推荐/最有效/最易读的方式是什么?LUT 将是最整洁的,但肯定会有很多不存在的字母组合的空条目(不理想..)。
感谢您的任何想法..
我的微控制器有一个 RS232 接口,带有一组预定义的命令。有数百个命令,例如PRESSURE 50
可以将压力设置为 50;LIMIT 60
可以设置一些限制为60。
当前,这是使用一系列嵌套的 switch 语句处理的,但这似乎是一个不雅的解决方案。
处理这些命令的推荐/最有效/最易读的方式是什么?LUT 将是最整洁的,但肯定会有很多不存在的字母组合的空条目(不理想..)。
感谢您的任何想法..
试过 strnstr 函数吗?它真的非常快。对于几个 100 个单词,它可能会比 8 或 9 个单独的 strcmp() 更快,中间有一些额外的代码来遍历一棵树,并且需要更少的内存来存储。
我会尝试以下
a) 建立一个命令列表并将最常用的放在开头,并为每个 ie 添加一个唯一编号
char command_names[] =
"PRESSURE 1"
"LIMIT 2"
;
int command_names_len = sizeof(command_names_str)
C 编译器应该为您附加这些字符串,因此很容易将它们移动到另一个位置
b)添加的这些数字是函数指针数组的索引,每个函数都应该具有相同的签名,当您允许某些函数具有未使用的参数时,这可能是可能的吗?IE
/* 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 中添加空格来克服。IE
" PRESSURE 1"
" LIMIT 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},
,可以通过sort CommandInitializers.c > sortedCommandInitializers
Makefile 中的命令对其进行排序。
因为make
它像其他任何依赖项一样:
sortedCommandInitializers: CommandInitializers.c
sort CommandInitializers.c > sortedCommandInitializers
myProgram.o: myProgram.c myProgram.h sortedCommandInitializers