c中的查找表

时间:2010-10-06 18:02:27

标签: c arrays struct char

我正在用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"}}
};

非常感谢。

祝你好运, 维克多

4 个答案:

答案 0 :(得分:12)

您不能在数组(结构)中使用包含灵活数组成员的结构。见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编译器,请注意。

答案 1 :(得分:2)

我认为您必须指定数组大小才能在另一个数组中使用该结构:

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

您需要在结构定义中指定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);
  ...
}

您可以使用sentinel:

,而不是明确传递消息数
  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++;
  }
}