Can strings be used as an array index?

Can a string be used as an array index in C?

Example: String The corresponding value is "ONE" 1 "TWO" 2 "FIVE" 5 "TEN" 10

When a string in the above list is passed to the function, the function should return the corresponding value indicated above. Is it possible to do this by declaring a constant array with a string as an index

int *x; x["ONE"] = 1; x["TWO"] = 2; x["FIVE"] = 5; x["TEN"] = 5; return x["string received by the function"]; 

The above logic is not working properly; is there a workaround for implementing the above logic to have a string index array?

+4
source share
8 answers

It may compile, but it will not work.

It is not clear what you are trying to achieve. I think you need an associative array and in this case you should find a library implementation from one.

If you are looking for something like an enumerated type , and you can rely on C89 , look at something like:

 enum cardsuit { CLUBS, DIAMONDS, HEARTS, SPADES }; 

If you can't rely on C89, you should try some typedef tricks.

+17
source

There are other great answers to what you should do, so I thought I would explain what you are doing and why it compiles and doesn't work.

In C, an array reference is made using an array or pointer and an integer. (in x [1], x is an array, and 1 is an integer). As long as you use some kind of holistic type, it will work as you expect.

Suppose you have something that is not whole. In this case, the C implementation will see if it can convert it to the appropriate type, so you end up with an array and an integer. This happens when you get into trouble (and somewhat more complex versions of this in C ++ confuse more experienced people than you).

In C, a literal string of type "one" is of type const char *, that is, a pointer to characters that you cannot change. The actual value is the memory address in which the string is actually in memory. Usually you do not pay attention to this pointer value and look at the string value, but there is one.

In C, any data pointer can be converted to some integer and will be automatically. Therefore, you have a string of type β€œone,” and its value is the number that represents the memory address. Use it where C expects some kind of integer, and it converts to some integer value or another.

Therefore, this is what happens with x ["ONE"]. System C should put the string "ONE" somewhere in memory, and it doesn't matter where. This is probably somewhere with a rather large memory address, quite possibly in billions. When he sees x ["ONE"], he tries to convert this value to an integer and uses it as an index. So you are trying to access the array x far, far beyond its borders, and this causes a problem. Either you try to use memory that you are not allowed to, and the system just stops you, or you twitch with a piece of memory, you must leave alone, and this may end in some mysterious way later.

+9
source

You will need to write a function that maps strings to integers, or, alternatively, use enumerations throughout (and then possibly a function that maps listed values ​​to strings).

In general, it’s better to do the latter: pass integers so that the implementation does not depend on the details of the lines that could be used in the view. For example, think about how you could manage localization (translation) if you ever need to make these lines acceptable to someone who speaks a different language.

+3
source

You can easily create lookup tables using the bsearch() function provided by stdlib.h . Working example:

 #include <string.h> #include <stdlib.h> #include <stdio.h> #define count(ARRAY) (sizeof(ARRAY)/sizeof(*ARRAY)) struct item { const char * name; int value; }; static _Bool sorted; static struct item items[] = { { "one", 1 }, { "two", 2 }, { "three", 3 }, { "ten", 10 } }; static int compare(const void * p1, const void * p2) { return strcmp(*((const char **)p1), *((const char **)p2)); } int get(const char * name) { if(!sorted) { qsort(items, count(items), sizeof(*items), compare); sorted = 1; } struct item * item = bsearch(&name, items, count(items), sizeof(*items), compare); return item ? item->value : 0; } int main(int argc, char ** argv) { int i; for(i = 1; i < argc; ++i) printf("%i\n", get(argv[i])); return 0; } 
+3
source

What you are looking for is probably equivalent to an associative array that cannot be supplied with the same syntactic sugar in C, unfortunately without any silly results.

However, you can provide a hash map if your data matches key β†’ value pairs. You will need a suitable hash function.

There is a decent simple hash table example here:

http://www.cl.cam.ac.uk/~cwc22/hashtable/

+1
source

As already stated, you need an associative array or hash map or equivalent. One possible source of such code is Hanson's β€œ C Interfaces and Implementations ” ( Google Code Code - Double-check the licensing terms, etc. before using it.)

0
source

This is an old thread, but I thought it might be useful for those looking for an implementation. This does not take up too much code; I made mine in ~ 100 lines without any additional library such as Hank Gay. I called it a dictionary, as it parallelizes (sort of) the python data type. Here is the code:

 #include <stdlib.h> #include <stdio.h> #include <stdbool.h> typedef struct hollow_list hollow_list; struct hollow_list{ unsigned int size; void *value; bool *written; hollow_list *children; }; //Creates a hollow list and allocates all of the needed memory hollow_list hollow_list_create(unsigned int size){ hollow_list output; output = (hollow_list) {.size = size, .value = (void *) 0, .written = calloc(size, sizeof(bool)), .children = calloc(size, sizeof(hollow_list))}; return output; } //Frees all memory of associated with a hollow list and its children void hollow_list_free(hollow_list *l, bool free_values){ int i; for(i = 0; i < l->size; i++){ hollow_list_free(l->children + i, free_values); } if(free_values){ free(l->value); } free(l); } //Reads from the hollow list and returns a pointer to the item data void *hollow_list_read(hollow_list *l, unsigned int index){ if(index == 0){ return l->value; } unsigned int bit_checker; bit_checker = 1<<(l->size - 1); int i; for(i = 0; i < l->size; i++){ if(bit_checker & index){ if(l->written[i] == true){ return hollow_list_read(l->children + i, bit_checker ^ index); } else { return (void *) 0; } } bit_checker >>= 1; } } //Writes to the hollow list, allocating memory only as it needs void hollow_list_write(hollow_list *l, unsigned int index, void *value){ if(index == 0){ l->value = value; } else { unsigned int bit_checker; bit_checker = 1<<(l->size - 1); int i; for(i = 0; i < l->size; i++){ if(bit_checker & index){ if(!l->written[i]){ l->children[i] = hollow_list_create(l->size - i - 1); l->written[i] = true; } hollow_list_write(l->children + i, bit_checker ^ index, value); break; } bit_checker >>= 1; } } } typedef struct dictionary dictionary; struct dictionary{ void *value; hollow_list *child; }; dictionary dictionary_create(){ dictionary output; output.child = malloc(sizeof(hollow_list)); *output.child = hollow_list_create(8); output.value = (void *) 0; return output; } void dictionary_write(dictionary *dict, char *index, unsigned int strlen, void *value){ void *hollow_list_value; dictionary *new_dict; int i; for(i = 0; i < strlen; i++){ hollow_list_value = hollow_list_read(dict->child, (int) index[i]); if(hollow_list_value == (void *) 0){ new_dict = malloc(sizeof(dictionary)); *new_dict = dictionary_create(); hollow_list_write(dict->child, (int) index[i], new_dict); dict = new_dict; } else { dict = (dictionary *) hollow_list_value; } } dict->value = value; } void *dictionary_read(dictionary *dict, char *index, unsigned int strlen){ void *hollow_list_value; dictionary *new_dict; int i; for(i = 0; i < strlen; i++){ hollow_list_value = hollow_list_read(dict->child, (int) index[i]); if(hollow_list_value == (void *) 0){ return hollow_list_value; } else { dict = (dictionary *) hollow_list_value; } } return dict->value; } int main(){ char index0[] = "hello, this is a test"; char index1[] = "hello, this is also a test"; char index2[] = "hello world"; char index3[] = "hi there!"; char index4[] = "this is something"; char index5[] = "hi there"; int item0 = 0; int item1 = 1; int item2 = 2; int item3 = 3; int item4 = 4; dictionary d; d = dictionary_create(); dictionary_write(&d, index0, 21, &item0); dictionary_write(&d, index1, 26, &item1); dictionary_write(&d, index2, 11, &item2); dictionary_write(&d, index3, 13, &item3); dictionary_write(&d, index4, 17, &item4); printf("%d\n", *((int *) dictionary_read(&d, index0, 21))); printf("%d\n", *((int *) dictionary_read(&d, index1, 26))); printf("%d\n", *((int *) dictionary_read(&d, index2, 11))); printf("%d\n", *((int *) dictionary_read(&d, index3, 13))); printf("%d\n", *((int *) dictionary_read(&d, index4, 17))); printf("%d\n", ((int) dictionary_read(&d, index5, 8))); } 

Unfortunately, you cannot replicate the syntax of the list [x], but this is the best alternative that I came across.

0
source

In "plain C" you can simulate using a string as an index, but not QUITE as you think. However, doing this is rarely useful and basically a great way to make your code unreadable. What you seem to want is the ability to use string keys in a dictionary (or a "hash table" if you prefer), and there is no built-in data structure for this in C. The exact design will depend on what you ( and, indeed, if this is part of the homework, you may not even need to use a full implementation of the hash table, but perhaps it can go away with less efficient static encoding).

An example of using a string (OK, a char) in the "index position" of a [b] construct:

 int main (void) { char *str = "This is a test string"; int x; for (x=0; x < 12; x += 3) putchar(x[str]); printf("\n"); return 0; } 

The above, as far as I can tell, has legal C, with a well-defined output (line "Tss ssi"). He relies on the fact that a [b] is defined as * (a + b).

-2
source

All Articles