c中的查找表

Posted

技术标签:

【中文标题】c中的查找表【英文标题】:lookup table in c 【发布时间】:2011-04-21 23:46:15 【问题描述】:

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

我收到以下错误:

错误:灵活初始化 嵌套上下文中的数组成员

错误:(接近初始化为 ‘tab[0].message’)

如何初始化第二个示例中的选项卡数组? 注意:我知道 tab 数组中的所有值。

更新:消息的大小可能不同,例如

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

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

非常感谢。

最好的问候, 维克多

【问题讨论】:

【参考方案1】:

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

【讨论】:

我只是打开我的旧 C 书来理解这个结构;)(Java 正在扼杀我的工程技能......)【参考方案2】:

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

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

【讨论】:

要么这样,要么吞下苦果并使用多行代码进行初始化;) 您好,谢谢,您的选择有效,但消息的大小也可能不同,我刚刚更新了我的问题以反映这一点。对不起。 顺便说一句,对消息使用 fix-max-size 也不太喜欢我。 @Victor:在这种情况下,您必须将message 的大小设置为可能的最大大小。或者只是使用指针手动管理内存,如另一个答案中所建议的那样。【参考方案3】:

您需要在结构定义中为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++;
  

【讨论】:

【参考方案4】:
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;

【讨论】:

您不能像评论建议的那样分配灵活数组成员结构的数组 - 编译器无法知道 tab[1] 应该从哪里开始。 在我的代码中它说所有数组元素都具有相同的大小,我编辑了注释以使其更加可见。感谢您指出这一点。

以上是关于c中的查找表的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery:查找 ID 类型为 RECORD 的数组并使用 SQL 连接辅助表中的数据

二分查找(折半查找)算法详解(C语言实现)

根据来自另一个表的匹配行查找表中的一组行

在一个表中的不同行和不同列中查找相同的值SQL

C语言中啥是索引??

C语言数据结构——静态查找顺序查找