【问题标题】:Is this way of switching strings efficient? Are there more efficient ones? [closed]这种切换字符串的方式有效吗?有没有更高效的? [关闭]
【发布时间】:2017-09-04 17:13:14
【问题描述】:

我想编写一个程序来切换多个字符串以避免 if-else-ladder。

我的想法是创建一个链表并删除每个位置不同的节点。然后我可以返回它是什么参数并切换这个数字。

我的代码

int str_switch(char* query, int arg_count, ...) {
    //Variables
    int i, j;
    struct node* args = (struct node*)calloc(arg_count, sizeof(struct node));
    va_list list;

    //va_list -> array
    int start = 0;
        //data
    va_start(list, arg_count);
    for (i = 0; i < arg_count; i++) {
        args[i].data = va_arg(list, char*);
        args[i].prev = i - 1;
        args[i].next = i + 1;
    }
    va_end(list);
        //start
    args[0].prev = -1;
        //end
    args[arg_count - 1].next = -1;

    //switch
    int len = strlen(query);
    for (i = 0; i <= len; i++) { //i <= len: null character is also compared
        for (j = start; j != -1; j = args[j].next) {
            //remove from list 
            if (*(args[j].data + i) != *(query + i)) {
                //only one element in list
                if (args[j].prev == -1 && args[j].next == -1) {
                    start = -1;
                }
                //first element
                else if (args[j].prev == -1) {
                    start = args[j].next;
                    args[start].prev = -1;
                }
                //last element
                else if (args[j].next == -1) {
                    args[args[j].prev].next = -1;
                }
                //mid element
                else {
                    args[args[j].prev].next = args[j].next;
                    args[args[j].next].prev = args[j].prev;
                }
            }
        }
    }

    //return
    free((void*)args);
    return start;
}

node 结构如下所示:

struct node {
    int next;
    int prev;
    char *data;
};

小测试程序:

#include<stdio.h>
#include<stdlib.h>


int main(void){
    char query[10] = "Horse";
    switch(str_switch(query, 3, "Bird", "Dog", "Horse")) {
        case 0: // Bird
            printf("It\'s a bird\n");
            break;
        case 1: // Dog
            printf("It\'s a dog\n");
            break;
        case 3: // Horse
            printf("It\'s a horse\n");
            break;
        case -1: // Error
            printf("It\'s an error :(\n");
            break;
        default: // ?
            printf("It\'s nothing..?\n");
            break;
    }
    system("pause");
    return 0;
}

我的问题:这有效吗?我怎样才能使它更有效率?我想知道这一点,因为我可能会在未来的项目中使用此代码,并且我不想因为一些愚蠢的错误而失去性能:)

【问题讨论】:

  • case 3 --> case 2 ?
  • 当您需要调用calloc() 并使用自定义结构来查找三个字符串的匹配项时,您就偏离了轨道。分配调用可能比调用strcmp() 3 次更昂贵。无论如何,为什么在预分配时使用链表?
  • 将已经在栈上的数据重构为列表似乎效率低下。
  • 您可能想看看哈希表:它们几乎可以对字符串等复杂对象执行快速查找 (en.wikipedia.org/wiki/Hash_table)。
  • 这个问题对于Code Review 来说基本上是完美的,但是这里非常离题。只需确保包含与str_switch 相关的所有实际代码,而不是 MCVE。

标签: c string performance switch-statement


【解决方案1】:

您可能应该构建一个像sethashtable 甚至trie 这样的数据结构。或者至少qsort 列表并执行bsearch 以获取索引。当前代码中最大的问题是每次调用都需要做大量工作。

如果您的字符串列表在编译时已知,您甚至可以使用gperf 生成完美的哈希表。

另一种可能性是 GTK+ 具有 GQuark 数据类型,它为您提供字符串和唯一整数标识符之间的双向关联。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-12
    • 1970-01-01
    相关资源
    最近更新 更多