2

我正在为我的 Pic32 编写一个小源文件函数,但我被困在一件事上。它基本上是一个实用程序,应该将char传入数据存储到缓冲区中,然后,如果'\r'收到,它将缓冲区与命令列表(在数组中names)进行比较,如果找到匹配项,则返回项目的索引。

这部分来自标题:

#define NAMECNT 6    
static const char names[NAMESCNT][10] = {   // 6commands, max 10 char each
        "korr",         // 1
        "adc",          // 2
        "fft",          // 3
        "data",         // 4 
        "pr",           // 5
        "prsc"};        // 6

/* functions */
extern int comm(char cdata);

在主文件中,有一个大开关:

switch( comm(recieved_ch) ){
case 1: foo1(); break; 
case 2: foo2(); break;
...
}

现在,为了更清楚起见,我想使用原始名称(如 )而不是 1、2、...,case KORR: case ADC:所以我为它们中的每一个都写了定义

#define KORR 1
#define ADC 2

但我不喜欢那个解决方案,因为我想在更多项目中使用这个源文件,并且每个项目都有不同的命令列表。有什么办法可以做到这一点?最好的办法是在预处理器中创建数组名称,但我怀疑这是否可能。我正在考虑使用 enum 类型(它与命令列表具有相同的项目names),但我不确定它会如何进行。

4

2 回答 2

2

我认为,预处理器可以使事情在这里更清楚,使用连接运算符##,但它不会产生性能优势。编译器switch可以优化语句,但这取决于实现。

不要使用“一个大开关”,而是使用函数指针数组。就像是

func_ptrs[comm(received_ch) - 1]();

将调用相应的函数,其中foo1是 at index 0foo2at1等。要添加命令,只需将命令名称附加到命令列表和函数指针func_ptrs

毕竟,你用一块石头杀死了两只鸟:你创造了一种简单的方法来添加命令和提高性能。


此外,通过字符串数组进行线性搜索是非常低效的。哈希表会产生性能优势。

于 2016-09-05T13:26:21.257 回答
2

您可以使用X-macros构建enum并填充数组,然后可以使用以下enumswitch

#define VARS \
    X(korr) \
    X(adc)  \
    X(fft)  \
    X(data) \
    X(pr)   \
    X(prsc)

static const char names[][10] = {   // 6commands, max 10 char each
#define X(name) #name,
    VARS
#undef X
};

enum evars {
#define X(name) name, 
    VARS
#undef X
};

extern int comm(char cdata);

int main(void)
{
    char x = 1;

    switch (comm(x)) {
        case korr:
            printf("korr");
            break;
        case adc:
            printf("adc");
            break;
        /* ... and so on */
    }
    return 0;
}

的展开X为:

static const char names[][10] = {

 "korr", "adc", "fft", "data", "pr", "prsc",

};

enum evars {

 korr, adc, fft, data, pr, prsc,

};

编辑:正如@5gon12eder 所指出的,您不需要在数组的第一维中硬编码 6(您可以不指定)。

于 2016-09-05T13:49:41.987 回答