Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C lookup string by value

Tags:

c

I need to translate a value into a human readable string. Normally for things I define I would use values that start at zero and create a simple array of strings with the values as the index.

static const char *foo[] = { "foo", "bar", "etc" };
if (val < 3) printf("%s\n", foo[val]);

For this circumstance I have values that do not start at zero and there are some gaps between them. Is there a good way to do this without having to manually code in a bunch of empty strings for the indexes without a matching value/string pair?

static const char *foo[] = { "", "", "", "foo", "", "bar", "", "", "etc" };
like image 953
jmfox24 Avatar asked Dec 20 '22 03:12

jmfox24


2 Answers

As of C99, you can use designated initialisers:

static const char *foo[] = { 
   [3] = "foo", 
   [5] = "bar",
   [8] = "etc"
};

This is equivalent to the array definition you posted and will generate an array with 9 entries. There is a similar syntax for the initialisation of structs:

struct Person joe = {
    .name = "Joe", .age = 24, .favcolor = "mauve"
};

Note that this is a C feature only and will not work in C++.

like image 151
M Oehm Avatar answered Jan 05 '23 23:01

M Oehm


If there aren't too many gaps, you can encode each contiguous sequence as a separate array, and then do a little bounds-checking to find the appropriate one to use. Here's a quick-and-dirty example:

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

static const int array_first_indices[] = {3, 15, 28, 32};
static const char * array0[] = {"foo"};
static const char * array1[] = {"bar", "baz"};
static const char * array2[] = {"bloop", "blorp", "blat"};
static const char * array3[] = {"glop", "slop", "bop"};

#define check_array(whichArray, idx) { \
   unsigned int relIdx = idx - array_first_indices[whichArray]; \
   if (relIdx < (sizeof(array##whichArray)/sizeof(const char *))) \
      return array##whichArray[relIdx]; \
   }

const char * LookupWord(int idx)
{
   check_array(0, idx);
   check_array(1, idx);
   check_array(2, idx);
   check_array(3, idx);
   return NULL;
}

int main(int args, char ** argv)
{
   for (int i=0; i<50; i++) printf("   LookupWord(%i) = %s\n", i, LookupWord(i));
   return 0;
}

For a fully general lookup mechanism, you'd probably need to use a data structure like a hash table or a tree; C implementations of those data structures are available, although if you have the option of using C++ it would be easier to use those data structures in that language, as they are provided by the standard library.

like image 28
Jeremy Friesner Avatar answered Jan 06 '23 00:01

Jeremy Friesner