2010-10-01 31 views
2

內容提要:如何定義一個任意大小的2D數組,然後在編譯時確定其尺寸?

  1. 如何可以定義C中的任意大小的2D陣列?
  2. 如何在編譯時確定該數組的維數?

披露:

我的嵌入式控制器編寫代碼。我的應用程序需要幾個不同大小的查找表,這些查找表將全部由一個查找功能(二進制搜索)使用。這是我到目前爲止:

typedef struct 
{ 
    unsigned char count;  // number of rows in the table 
    unsigned char width;  // number of bytes in each row 
    const unsigned char * data; // pointer to table data[count][width] 
} 
LookupTable; 

// returns the index of a value from within a table 
unsigned char Lookup(unsigned long value, const LookupTable * table); 

這部分工作。我現在想要做的是在源代碼中定義這些表格,而無需手動輸入常量countwidth。以下是我現在做:

#define T1_count 100 
#define T1_width 3 
const unsigned char table1_data[T1_count][T1_width] = 
{ 
    { 0x12, 0x34, 0x56 }, 
    { 0x12, 0x38, 0x12 }, 
    ... 
}; 

const LookupTable table1 = { T1_count, T1_width, table1_data }; 

這裏是什麼,我會喜歡要能夠做到(僞代碼,因爲這個數組定義實際上不會編譯):

const unsigned char table1_data[] = 
{ 
    { 0x12, 0x34, 0x56 }, 
    { 0x12, 0x38, 0x12 }, 
    ... 
}; 

const LookupTable table1 = 
{ 
    get_count_expr(table1_data), 
    get_width_expr(table1_data), 
    table1_data 
}; 

顯然,get_count_exprget_width_expr必須是基於表大小的某種常量表達式,而不是實際的函數調用。

要清楚的是,這個設計的任何部分都沒有石頭。我只是發佈我迄今爲止的內容,希望我的意圖很明確。任何改進的想法將不勝感激。

「爲什麼」:

這些表會經常改變,它將使維護更加容易,如果可以添加和刪除條目,或表格的寬度,而無需手動調整常數改變每一次。必須手動記錄尺寸可能容易出錯,並且違反了DRY。我正在尋找更好的方法。

回答

3

嗯......你可以離開最左邊的大小,編譯器:

#define T1_WIDTH 3 
const unsigned char table1_data[][T1_WIDTH] = 
{ 
    { 0x12, 0x34, 0x56 }, 
    { 0x12, 0x38, 0x12 }, 
    /* ... */ 
}; 
T1_count = sizeof table1_data/sizeof *table1_data; 
T1_width = sizeof *table1_data; 
+0

+1這已經是一個很大的改進。使用相同的邏輯,我也可以設置'T1_width = sizeof * table1_data;',這幾乎是完美的。手動輸入的唯一東西是數組定義中的寬度,這不是世界的盡頭。 – 2010-10-01 22:03:08

+0

'T1_width'以前被定義爲預處理器宏。我已經更改了代碼(但現在您的宏和變量都具有相同的值)。 – pmg 2010-10-02 10:05:07

1

好,但誰填補這些表的數據?我認爲生成的來源是更好的解決方案。

+0

+1偉大的建議,我同意。不幸的是,我們現在沒有這樣設置。我正在對遺留系統進行這些更改,因此我不完全自由地改變事情的構建方式。 – 2010-10-01 22:07:31

+0

@詹姆斯如果模式很簡單,也許你可以使用像這樣的遞歸宏? http://graphics.stanford.edu/~seander/bithacks.html#ParityLookupTable – ruslik 2010-10-01 22:16:57

0

在標題內定義table1_data。您可以使用腳本自動生成該頭文件。我爲我的一些項目做了類似的事情。我有一個帶有數據的CSV文件和一個Ruby或Python腳本,可以從中生成一個標題。

2

嗯,這真是醜陋,但我認爲在列出的約束條件下做到這一點的唯一方法是將數據包含在字符串中,而不是讓初始化代碼解析字符串並生成表格。理想情況下,你可以在腳本中做到這一點,而不是使用C來做,但如果它必須在C中,則必須使用C語言。

請注意,我絕不會聲稱以下內容生產代碼,但它只是一個概念證明......

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define datatable "\ 
    { 0x12, 0x34, 0x56 },\ 
    { 0x14, 0x36, 0x10 },\ 
    { 0x13, 0x37, 0x11 },\ 
    { 0x12, 0x38, 0x12 }" 

typedef struct 
{ 
    unsigned char count;  // number of rows in the table 
    unsigned char width;  // number of bytes in each row 
    unsigned char **data; // pointer to table data[count][width] 
} 
LookupTable; 

int parsedatatable(char *data, LookupTable **table) { 
    char *p, *sp, save; 
    unsigned char *tabledata; 
    int count = 0, width = 0; 
    unsigned int tmp; 
    int i,j; 

    /* find count */ 
    p = strstr(data,"{"); 
    while (p) { 
     p++; 
     p = strstr(p, "{"); 
     count++; 
    } 
    /* find width */ 
    p = strstr(data, "{"); 
    p++; 
    sp = strstr(p, "}"); 
    if (sp != NULL) { 
     save = *sp; 
     *sp = '\0'; 
    } 
    while (p) { 
     p = strstr(p, ","); 
     width++; 
     if (p != NULL) p++; 
    } 
    if (sp != NULL) { 
     *sp = save; 
    } 

    printf("Count = %d, width = %d\n",count, width); 
    tabledata = (unsigned char *)malloc(width*count*sizeof(unsigned char)); 
    *table = (LookupTable *)malloc(sizeof(LookupTable)); 
    (*table)->data = (unsigned char **)malloc(count*sizeof(unsigned char*)); 
    for (i=0; i<count; i++) { 
     (*table)->data[i] = &(tabledata[i*width]); 
    } 
    (*table)->count = count; 
    (*table)->width = width; 

    p = data; 
    for (i=0; i<count; i++) { 
     p = strstr(p,"{"); 
     if (!p) { 
      fprintf(stderr,"Fail (a) reading in data!: %s\n",data); 
      free((*table)->data); 
      free(tabledata); 
      free(*table); 
      return -1; 
     } 
     p++; 
     for (j=0; j<width; j++) { 
      printf("Scanning <%s>, ",p); 
      sscanf(p,"%x",&tmp); 
      printf("got %d\n",tmp); 
      (*table)->data[i][j] = tmp; 
      p = strstr(p,","); 
      if (!p && j<width-1) { 
       fprintf(stderr,"Fail (b) reading in data!: %d, %d, %s\n",i,j,data); 
       free((*table)->data); 
       free(tabledata); 
       free(*table); 
       return -1; 
      } 
      p++; 
     } 
    } 
    return 0; 
} 

void printtable(LookupTable *table) { 
    unsigned char i,j; 
    for (i=0; i<table->count; i++) { 
     printf("{"); 
     for (j=0; j<table->width; j++) { 
      printf("%x ",table->data[i][j]); 
     } 
     printf("}\n"); 
    } 
    return; 
} 

int main(int argc, char **argv) { 
    char *data; 
    LookupTable *table; 

    data = (char *)malloc(strlen(datatable)+1); 
    strcpy(data,datatable); 

    parsedatatable(data,&table); 
    printtable(table); 

    return 0; 
} 
+1

+1只是爲了您付出的努力。哇。 – 2010-10-01 23:35:42

相關問題