3

我的微控制器有一个 RS232 接口,带有一组预定义的命令。有数百个命令,例如PRESSURE 50可以将压力设置为 50;LIMIT 60可以设置一些限制为60。

当前,这是使用一系列嵌套的 switch 语句处理的,但这似乎是一个不雅的解决方案。

处理这些命令的推荐/最有效/最易读的方式是什么?LUT 将是最整洁的,但肯定会有很多不存在的字母组合的空条目(不理想..)。

感谢您的任何想法..

4

2 回答 2

3

试过 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"
于 2013-05-15T19:45:02.407 回答
3
  1. 运行时建议:

    使用 struct { string, function pointer ) 的排序数组

    我希望qsort()并且bsearch()可以在您的平台上使用 ( stdlib.h)

  2. 设计时提案:

    正如评论所暗示的,最好在设计时对数组初始化的条目进行排序。存在很多方法,从代码生成(豪华)到宏处理(差)。

    申报建议,一对多:

    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 > sortedCommandInitializersMakefile 中的命令对其进行排序。

    因为make它像其他任何依赖项一样:

    sortedCommandInitializers: CommandInitializers.c
        sort CommandInitializers.c > sortedCommandInitializers
    
    myProgram.o: myProgram.c myProgram.h sortedCommandInitializers
    
于 2013-05-15T18:47:39.610 回答