таблица поиска в с - PullRequest
       8

таблица поиска в с

6 голосов
/ 06 октября 2010

Я создаю таблицу поиска в C Когда я определяю это:

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

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

компилируется без ошибок, но когда я делаю что-то вроде этого:

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

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

Я получаю следующую ошибку:

ошибка: инициализация гибкой член массива во вложенном контексте

ошибка: (рядом с инициализацией для «Вкладка [0] .message»)

Как я могу инициализировать массив вкладок во втором примере? Примечание: я знаю все значения в массиве вкладок.

ОБНОВЛЕНИЕ: сообщение может иметь другой размер, например,

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

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

Большое спасибо.

С уважением, Victor

Ответы [ 4 ]

12 голосов
/ 06 октября 2010

Нельзя использовать структуры, содержащие гибкий элемент массива в массиве (структуры).См. Стандарт C99 §6.7.2.1 / 2:

Структура или объединение не должны содержать члена с неполным или функциональным типом (следовательно, структура не должна содержать своего экземпляра, но может содержатьуказатель на сам экземпляр), за исключением того, что последний член структуры с более чем одним именованным членом может иметь неполный тип массива;такая структура (и любое объединение, содержащее, возможно, рекурсивно член, который является такой структурой) не должно быть членом структуры или элементом массива.

Итак, используйте char ** вместо этого (и беспокоиться о том, как вы знаете, сколько записей):

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" } }
};

При этом используется конструкция C99 (§6.5.2.5 Составные литералы) - будьте осторожны, если вы не используете компилятор C99.

2 голосов
/ 06 октября 2010

Я думаю, вы должны указать размер массива, чтобы использовать структуру в другом массиве:

typedef struct {
 char* action;
 char* message[2];
} lookuptab;
0 голосов
/ 06 октября 2010

Необходимо указать размер для элемента массива message в определении структуры:

#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"}},
  ...
};

В этом случае N должно быть не менее 2.

Если вы хотите, чтобы каждый экземпляр структуры lookuptab имел разное количество элементов в массиве message, вам придется выделять каждый массив message по отдельности, то есть вы не сможете использовать статический инициализатор:

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);
  ...
}

Вместо явного указания количества сообщений вы можете использовать страж:

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

но вам придется либо дважды просмотреть все аргументы (сначала получить число для выделения массива messages, затем скопировать каждое сообщение), либо вам придется realloc() ваш массив для каждого сообщения , например:

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++;
  }
}
0 голосов
/ 06 октября 2010
typedef struct {
 char* action;
 char* message[];
} lookuptab;

lookuptab является неполным типом.Вы не можете создавать объекты этого типа.Либо укажите определенный размер для массива сообщений

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

, либо используйте указатели повсюду и управляйте памятью «вручную»

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

, вы можете использовать элемент гибкого массива (все элементыимеют одинаковый размер), но это много работы: -)

#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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...