简体   繁体   中英

Is an initialised 2d array fine for mapping consecutive integers to strings in C?

I have to map consecutive integer codes from 1 to 100 to strings in C. Normally, for a mapping of number to string, I would have something like this:

#define code1   1
#define code2   2
.
.
#define code100 100

struct map 
   {
     int code;
     char *msg;
   }objs[100];

I would then loop over the objs and if the number matches, I would use the corresponding string of the obj array. Since I know that the numbers to be mapped are consecutive, I can just do this:

const char *arr[100] = { "abc", "def", ....... "100th msg"};

I can then forget the looping and just print arr[code]. Is this a bad approach? The only disadvantage I see is that when somebody else adds a code in the middle, they have to be careful about it. The advantage is obviously that I don't need to loop over the struct array.

Using a direct indexed array is a commonly used approach that works fine if the data never (rarely) changes, and there are not too many gaps, because you spend a record for every gap. At some point the management or the storage cost of the gaps may become an issue.

If you need to cope with more dynamic compile-time updates to the data then the next best thing is a sorted array. If you can guarantee that your entries are always in order but perhaps there are gaps, or new entries added to the end, then you can binary chop your ordered array to quickly find the entry you want. You may want to do a start-up pass that checks the array is correctly ordered, but you only have to do that once.

If you need to worry about runtime updates, then you seriously need to consider higher-level container abstractions such as mapping trees or hashmaps.

Suppose the array has error messages. Then a common approach is to define constants fo each error and print the message associated with it, for example:

#define ERR_NONE 0
#define ERR_NOMEM 1
#define ERR_BADNUM 2
// etc

and define the array as:

const char *msgs[] = {
    "No error",
    "Out of memory",
    "Bad number",
    // etc
};

and have a function to print the message, for example:

void printmsg(int code)
{
    printf("%s\n",msgs[code]);
}

which can be called as

    printmsg(ERR_NOMEM);

For modularity, the #define s can be in eg errors.h , together with the prototype of printmsg , and the array can be in errors.c .

The only problem with your approach is that the codes can never change. You can't add intermediate codes without changing the entire code. But it should work. Also the first code should be zero or you'll have to either pad the array or shift the codes when accessing.

Essentially what you have is an immutable hash table.

#define BASE_CODE 5
#define CODE_BLUE 5
#define CODE_GREEN 6

const char *responses[] = {'blue', 'green'};
printf("%s\n", responses[code - BASE_CODE]);

If you want to be able to change the codes (add, remove, insert codes in the middle of the sequence, verify if a code was properly referenced), then you should stick with the first approach, but add a hash function so you don't need to loop sequentially over the array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM