开发者

how to best achieve string to number mapping in a c program

开发者 https://www.devze.com 2023-03-19 14:16 出处:网络
I have a definite set of strings and its cor开发者_开发技巧responding numbers: kill -> 1 live -> 2

I have a definite set of strings and its cor开发者_开发技巧responding numbers:

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

List is of 30 such strings and their number mapping.

If user enters "kill", I need to return 1 and if he enters "dont_live" I need to return 4.

How should I achieve this in c program? I am looking for an efficient solution because this operation needs to be done 100s of times.

  • should I put them in #define in my .h file?

Thanks in advance.


Sort your table, and use the standard library function bsearch to perform a binary search.

#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;
}

Here's what you get when you run the program.

$ ./a.out kill
1
$ ./a.out half_kill
3
$ ./a.out foo
<no output>

PS: I reused portions of sidyll's program. My answer should now be CC BY-SA compliant :p


A possible solution:

#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;
}


Here's one approach:

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;
}

The . mess is to work around kill being a substring of half_kill. Without that issue you could simply search for the string directly.


If it is a very short list of strings then a simple block of ifs will be more than sufficient

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

If the number approach 10 I would begin to profile my application though and consider a map style structure.


if you have a fixed set of strimgs, you have two options: generate a perfect hashing function (check gperf or cmph) or create a trie so that you never have to check charcters more than once. Compilers usually use perfect hashes to recognize a language keyword, in your case I would probably go with the trie, it should be the fastest way (but nothing beats direct measurement!)


Is it really a bottleneck? You should worry about efficiency only if the simple solution proves to be too slow.

Having said that, possible speed improvements are checking the lengths first:

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"

or checking the first character in a switch statement:

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


Use hashmap/ hashtable i think this would be the best solution.


Can you use an Enumunerator?

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;
}


Create a list of const values:

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

etc

0

精彩评论

暂无评论...
验证码 换一张
取 消