Les chaînes peuvent-elles être utilisées comme index de tableau?

Une chaîne peut-elle être utilisée comme index de tableau en C?

Ex: Chaîne Valeur correspondante “UN” 1 “DEUX” 2 “CINQ” “5” DIX “10

Lorsqu’une chaîne de la liste ci-dessus est transmise à la fonction, celle-ci doit renvoyer la valeur correspondante indiquée ci-dessus. Peut-on y parvenir en déclarant un tableau constant avec chaîne sous forme d’index

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

La logique ci-dessus ne fonctionne pas comme prévu; Existe-t-il une solution de contournement pour implémenter la logique ci-dessus afin d’avoir un tableau indexé par chaîne?

    Cela peut être compilé, mais ça ne marchera pas.

    Ce que vous essayez de réaliser n’est pas tout à fait clair. Je pense que vous voulez un tableau associatif , auquel cas vous devriez trouver une implémentation de bibliothèque.

    Si vous recherchez quelque chose de plus semblable à un type énuméré et que vous pouvez compter sur C89 , examinez quelque chose comme:

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

    Si vous ne pouvez pas compter sur C89, alors vous devriez essayer quelques astuces typedef .

    Il y a d’autres excellentes réponses à ce que vous devriez faire, alors j’ai pensé expliquer ce que vous faites et pourquoi il comstack et ne fonctionne pas.

    En C, la référence à un tableau se fait en ayant un tableau ou un pointeur et un entier quelconque. (dans x [1], x est le tableau et 1 est le nombre entier). Tant que vous utilisez un type intégral, cela fonctionnera comme prévu.

    Supposons que vous ayez quelque chose qui ne soit pas un entier. Dans ce cas, l’implémentation C verra si elle peut le convertir en un type approprié, de sorte que vous obtenez un tableau et un entier. Ce sont des cas comme celui-ci où vous rencontrez des problèmes (et des versions légèrement plus sophistiquées de C ++ ont confondu des personnes plus expérimentées que vous).

    En C, une chaîne littérale telle que “one” est de type const char *, ce qui signifie un pointeur sur des caractères que vous ne pouvez pas modifier. La valeur réelle est l’adresse de la mémoire où la chaîne réside réellement dans la mémoire. Normalement, vous ne faites pas attention à cette valeur de pointeur et regardez la valeur de chaîne, mais il y a un piège ici.

    En C, tout pointeur de données peut être converti en une sorte d’entier et le sera automatiquement. Par conséquent, vous avez une chaîne comme “un” et sa valeur est le nombre qui représente l’adresse de la mémoire. Utilisez-le là où C s’attend à une sorte de nombre entier et il sera converti en une valeur intégrale ou autre.

    C’est donc ce qui se passe avec x [“ONE”]. Le système C doit mettre la chaîne “ONE” quelque part en mémoire, peu importe où. Il est probable qu’il se trouve quelque part avec une adresse mémoire assez volumineuse, probablement des milliards. Lorsqu’il voit x [“ONE”], il tente de convertir cette valeur en entier et l’utilise comme indice. Par conséquent, vous essayez d’accéder au tableau x très loin, bien au-delà de ses limites, ce qui pose problème. Soit vous essayez d’utiliser une mémoire que vous n’êtes pas autorisé à utiliser et le système vous en empêche, soit vous vous retrouvez avec un bloc de mémoire que vous devriez laisser seul, et il est probable que cela échoue de manière mystérieuse plus tard.

    Vous devrez écrire une fonction qui mappera des chaînes sur des entiers ou utiliser des énumérations dans l’ensemble (et éventuellement une fonction mappant des valeurs énumérées à des chaînes).

    En général, il est préférable de procéder de la manière suivante: transmettre des entiers, de sorte que l’implémentation ne dépende pas des détails des chaînes pouvant être utilisées dans la représentation. Par exemple, réfléchissez à la façon dont vous géreriez la localisation (traduction) si vous devez rendre ces chaînes agréables à une personne parlant une autre langue.

    Vous pouvez facilement construire des tables de recherche avec la fonction bsearch() fournie par stdlib.h . Voici un exemple de travail:

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

    Ce que vous recherchez correspond probablement à un tableau associatif auquel on ne peut malheureusement pas fournir le même sucre syntaxique en C sans résultats stupides.

    Toutefois, vous pouvez fournir une table de hachage si vos données sont conformes aux paires clé -> valeur. Ce dont vous aurez besoin est une fonction de hachage appropriée.

    Il y a un exemple simple décent d’une table de hachage ici:

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

    Comme déjà indiqué, vous avez besoin d’un tableau associatif, d’une carte de hachage ou d’un équivalent. Une source possible pour ce code est ” Interfaces C et implémentations ” de Hanson (code sur Google Code – vérifiez les conditions de licence, etc. avant de l’utiliser.)

    Ceci est un vieux fil, mais je pensais que cela pourrait toujours être utile pour tous ceux qui recherchent une implémentation. Cela ne prend pas trop de code; J’ai fait le mien en ~ 100 lignes sans aucune bibliothèque supplémentaire comme suggéré par Hank Gay. Je l’ai appelé un dictionnaire car il est parallèle (en quelque sorte) au type de données Python. Voici le code:

     #include  #include  #include  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's 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))); } 

    Malheureusement, vous ne pouvez pas reproduire la syntaxe de liste [x], mais c’est la meilleure alternative que j’ai proposée.

    Dans “plain C”, vous pouvez utiliser une chaîne comme un index, mais pas QUITE comme vous semblez le vouloir. Cependant, cela est rarement utile et surtout un excellent moyen de rendre votre code illisible. Ce que vous semblez vouloir, c’est pouvoir utiliser les clés de chaîne dans un dictionnaire (ou “table de hachage”, si vous préférez) et il n’y a pas de structure de données intégrée pour celle en C. La conception exacte dépend de ce que vous voulez. vouloir (et, en effet, si cela fait partie des devoirs, vous n’aurez peut-être même pas besoin d’utiliser une implémentation à part entière de la table de hachage, mais vous pourriez probablement vous en tirer avec un codage statique moins performant).

    Exemple utilisant une chaîne (OK, un tableau de caractères) dans “position d’index” d’une construction a [b]:

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

    Autant que je sache, ce qui précède est un C légal, avec une sortie bien définie (la chaîne "Tss ssi"). Il repose sur le fait que a [b] est défini comme étant le même que * (a + b).