2010-10-06 6 views
6

Je crée une table de recherche dans C Quand je décris cette:table de recherche dans c

typedef struct { 
char* action; 
char* message; 
} lookuptab; 

lookuptab tab[] = { 
    {"aa","bb"}, 
    {"cc","dd"} 
}; 

compile sans erreur, mais quand je fais quelque chose comme ceci:

typedef struct { 
char* action; 
char* message[]; 
} lookuptab; 

lookuptab tab[] = { 
    {"aaa", {"bbbb", "ccc"}}, 
    {"cc", {"dd", "eeeee"}} 
}; 

Je reçois l'erreur suivante:

error: initialization of flexible array member in a nested context

error: (near initialization for ‘tab[0].message’)

Comment puis-je initialiser le tableau d'onglets dans le deuxième exemple? Note: Je connais toutes les valeurs dans le tableau d'onglets.

MISE À JOUR: message pourrait être de taille différente, par exemple

typedef struct { 
char* action; 
char* message[]; 
} lookuptab; 

lookuptab tab[] = { 
    {"aaa", {"bbbb", "ccc", "dd"}}, 
    {"cc", {"dd", "eeeee"}} 
}; 

Merci beaucoup.

Cordialement, Victor

Répondre

12

Vous ne pouvez pas utiliser des structures contenant un tableau flexible dans un tableau (de la structure). Voir C99 norme §6.7.2.1/2:

A structure or union shall not contain a member with incomplete or function type (hence, a structure shall not contain an instance of itself, but may contain a pointer to an instance of itself), except that the last member of a structure with more than one named member may have incomplete array type; such a structure (and any union containing, possibly recursively, a member that is such a structure) shall not be a member of a structure or an element of an array.

, utilisez un char ** à la place (et l'inquiétude sur la façon dont vous savez combien d'entrées il y a):

typedef struct 
{ 
    const char   *action; 
    const char * const *message; 
} lookuptab; 

static const lookuptab tab[] = 
{ 
    { "aaa", (const char * const []){ "bbbb", "ccc" } }, 
    { "cc", (const char * const []){ "dd", "eeeee" } } 
}; 

Il utilise une construction de C99 (§6.5.2.5 Littéraux composés) - méfiez-vous si vous n'utilisez pas un compilateur C99.

+0

Salut Jonathan! ce code a bien fonctionné! (et sans avertissements!) –

+4

Je vais juste déballer mon ancien livre C pour comprendre cette construction;) (Java est en train de tuer mes compétences en ingénierie ...) –

2

Je pense que vous devez spécifier la taille du tableau à utiliser la struct dans un autre tableau: membre

typedef struct { 
char* action; 
char* message[2]; 
} lookuptab; 
+1

Soit ça, ou tout simplement avaler la pilule amère et faire l'initialisation en utilisant plus d'une ligne de code;) – riwalk

+0

Salut BDE, merci, votre option fonctionne, mais le message pourrait également être de taille différente, je viens de mettre à jour ma question pour refléter cela. Pardon. –

+0

BTW, en utilisant fix-max-size pour le message ne m'aime pas beaucoup, ni l'un ni l'autre. –

0
typedef struct { 
char* action; 
char* message[]; 
} lookuptab; 

lookuptab est un type incomplet. Vous ne pouvez pas créer d'objets de ce type. Soit fournir une taille définie pour le tableau de messages

typedef struct { 
char* action; 
char* message[42]; 
} lookuptab_definite_size; 

ou utiliser des pointeurs tout autour et gérer la mémoire « à la main »

typedef struct { 
char* action; 
char** message; 
} lookuptab_pointers_all_around; 

vous pouvez utiliser le membre flexible (tous les éléments aurez la même taille), mais il est beaucoup de travail :-)

#include <stdlib.h> 
typedef struct { 
    char* action; 
    char* message[]; 
} lookuptab; 

int main(void) { 
    lookuptab *tab; 

    tab = malloc(sizeof *tab + 42 * sizeof *tab->message); 
    /* tab = malloc(elems * (sizeof *tab + 42 * sizeof *tab->message)); */ 
    /* tab[0] ... tab[elems-1] all have the same size */ 
    if (tab) { 
    tab->action = NULL; 
    tab->message[0] = NULL; 
    tab->message[1] = NULL; 
    /* ... */ 
    tab->message[41] = NULL; 
    free(tab); 
    } 
    return 0; 
} 
+0

Vous ne pouvez pas allouer un tableau de structures flexible-array-member comme votre comment suggère - le compilateur n'a aucun moyen de savoir où 'tab [1]' devrait commencer. – caf

+0

Dans mon code il est dit que tous les éléments du tableau ont la même taille, je modifie le commentaire pour le rendre plus visible. Je vous remercie de le faire remarquer. – pmg

0

Vous devez spécifier une taille pour le membre du groupe message dans la définition de struct:

#define N ... // maximum number of elements in message array 

typedef struct 
{ 
    char *action; 
    char *message[N]; 
} lookuptab; 

lookuptab tab[] = { 
    {"aa", {"bb", "cc"}}, 
    {"dd", {"ee", "ff"}}, 
    ... 
}; 

Dans ce cas, N doit être d'au moins 2.

Si vous voulez que chaque instance de la struct lookuptab d'avoir un nombre différent d'éléments du tableau message, alors vous devrez allouer chaque tableau message séparément, ce qui signifie que vous ne serez pas en mesure d'utiliser un initialiseur statique:

typedef struct 
{ 
    char *action; 
    char **messages; 
} lookuptab; 

lookuptab *newEntry(const char *action, size_t numMessages, ...) 
{ 
    lookuptab *entry = malloc(sizeof *entry); 
    if (entry) 
    { 
    entry->action = malloc(strlen(action) + 1); 
    if (entry->action) 
     strcpy(entry->action, action); 
    if (numMessages > 0) 
    { 
     entry->messages = malloc(sizeof *entry->messages * numMessages); 
     if (entry->messages) 
     { 
     size_t i; 
     va_list ap; 

     va_start(ap, numMessages); 

     for (i = 0; i < numMessages; i++) 
     { 
      char *nextMessage = va_arg(ap, char *); 
      entry->messages[i] = malloc(strlen(nextMessage) + 1); 
      if (entry->messages[i]) 
      strcpy(entry->messages[i], nextMessage); 
     } 
     } 
    } 
    } 
    return entry; 
} 

int main(void) 
{ 
    lookuptab *tab[ENTRIES]; // for some number of ENTRIES 
    tab[0] = newEntry("AA", 2, "BB", "CC"); 
    tab[1] = newEntry("DD", 3, "EE", "FF", "GG"); 
    tab[2] = newEntry("HH", 0); 
    ... 
} 

au lieu de passer le nombre de messages explicitement, vous pouvez utiliser une sentinelle:

tab[0] = newEntry("AA", "BB", "CC", NULL); 

mais vous devez soit faire défiler tous les arguments deux fois (premier à ge t le nombre d'allouer le tableau messages, puis copier chaque message) ou vous devrez realloc() votre tableau pour chaque message, tel que:

size_t numMessages = 0; 
... 
char *nextMessage 
while ((nextMessage = va_arg(ap, char *)) != NULL) 
{ 
    char **tmp = realloc(entry->messages, sizeof *entry->messages, numMessages+1); 
    if (tmp) 
    { 
    entry->messages = tmp; 
    entry->messages[numMessages] = malloc(strlen(nextMessage) + 1); 
    strcpy(entry->messages[numMessages], nextMessage); 
    numMessages++; 
    } 
} 
Questions connexes