如何在c程序中最好地实现字符串到数字的映射

时间:2011-07-12 19:22:04

标签: c performance

我有一组明确的字符串及其相应的数字:

kill -> 1
live -> 2
half_kill -> 3
dont_live -> 4

列表是30个这样的字符串及其数字映射。

如果用户输入“kill”,我需要返回1,如果他输入“dont_live”,我需要返回4。

我应该如何在c程序中实现这一目标?我正在寻找一种有效的解决方案,因为这项操作需要完成100次。

  • 我应该把它们放在我的.h文件中的#define吗?

提前致谢。

9 个答案:

答案 0 :(得分:8)

对表格进行排序,并使用标准库函数bsearch执行二进制搜索。

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

struct entry {
    char *str;
    int n;
};

/* sorted according to str */
struct entry dict[] = {
    "dont_live", 4,
    "half_kill", 3,
    "kill", 1,
    "live", 2,
};

int compare(const void *s1, const void *s2)
{
     const struct entry *e1 = s1;
     const struct entry *e2 = s2;

     return strcmp(e1->str, e2->str);
}

int
main (int argc, char *argv[])
{
    struct entry *result, key = {argv[1]};

    result = bsearch(&key, dict, sizeof(dict)/sizeof(dict[0]),
                     sizeof dict[0], compare);
    if (result)
        printf("%d\n", result->n);

    return 0;
}

这是运行程序时的结果。

$ ./a.out kill
1
$ ./a.out half_kill
3
$ ./a.out foo
<no output>
PS:我重复使用了sidyll程序的部分内容。我的答案现在应符合CC BY-SA标准:p

答案 1 :(得分:5)

可能的解决方案:

#include <stdio.h>
#include <string.h>

struct entry {
    char *str;
    int n;
};

struct entry dict[] = {
    "kill", 1,
    "live", 2,
    "half_kill", 3,
    "dont_live", 4,
    0,0
};

int
number_for_key(char *key)
{
    int i = 0;
    char *name = dict[i].str;
    while (name) {
        if (strcmp(name, key) == 0)
            return dict[i].n;
        name = dict[++i].str;
    }
    return 0;
}

int
main (int argc, char *argv[])
{
    printf("enter your keyword: ");
    char s[100]; scanf("%s", s);
    printf("the number is: %d\n", number_for_key(s));
    return 0;
}

答案 2 :(得分:3)

这是一种方法:

int get_index(char *s)
{
    static const char mapping[] = "\1.kill\2.live\3.half_kill\4.dont_live";
    char buf[sizeof mapping];
    const char *p;
    snprintf(buf, sizeof buf, ".%s", s);
    p = strstr(mapping, buf);
    return p ? p[-1] : 0;
}

.混乱是kill作为half_kill的子字符串。没有这个问题,你可以直接搜索字符串。

答案 3 :(得分:2)

如果它是一个非常短的字符串列表,那么if的简单块就足够了

if (0 == strcmp(value, "kill")) {
  return 1;
}
if (0 == strcmp(value, "live")) {
  return 2;
}
...

如果数字接近10,我会开始描述我的应用程序,并考虑一个地图样式结构。

答案 4 :(得分:1)

如果你有一组固定的strimgs,你有两个选择:生成 完美散列 功能(检查gperf或cmph)或创建 trie ,这样您就不必多次检查字符。 编译器通常使用完美的哈希来识别语言关键字,在你的情况下我可能会使用trie,它应该是最快的方式(但没有什么比直接测量更好!)

答案 5 :(得分:0)

真的是瓶颈吗?只有当简单的解决方案证明太慢时,你才应该担心效率。

话虽如此,可能的速度提升首先要检查长度:

If it's 4 characters then it could be "kill" or "live"
If it's 9 characters then it could be "half_kill" or "dont_live"

或检查switch语句中的第一个字符:

switch (string[0]) {
case 'k':
    if (strcmp(string, "kill") == 0)
        return 1;
    return 0;
case 'l':
    ...
default:
    return 0;
}

答案 6 :(得分:0)

使用hashmap / hashtable我认为这将是最好的解决方案。

答案 7 :(得分:0)

可以使用枚举器吗?

int main(void) {

  enum outcome { kill=1, live, half_kill, dont_live };

  printf("%i\n", kill);       //1
  printf("%i\n", dont_live);  //4
  printf("%i\n", half_kill);  //3
  printf("%i\n", live);       //2

  return 0;
}

答案 8 :(得分:-3)

创建一个const值列表:

const int kill = 1; const int live = 2; const int half_kill = 3;