2008-10-12 36 views
0

假設的Visual C/C++ 6,我有22399元,看起來像這樣的複雜的數據結構:如何在C中初始化一個相當複雜的char數組?

{ 
{ "(SAME", "AS", "U+4E18)", "HILLOCK", "OR", "MOUND"}, 
{ "TO", "LICK;", {1, 1, 0}, "TASTE,", "A", "MAT,", "BAMBOO", "BARK"}, 
{ "(J)", "NON-STANDARD", "FORM", "OF", "U+559C", ",", {1, 1, 0}, "LIKE,", "LOVE,", "ENJOY;", {1, 1, 4}, "JOYFUL", "THING"}, 
{ "(AN", "ANCIENT", {1, 2, 2}, {1, 2, 3}, "U+4E94)", "FIVE"}, 
... 
} 

什麼是申報的最佳方式?我試過的東西

char * abbrevs3[22399][] = { ... }; 

char * abbrevs3[22399][][] = { ... }; 

但編譯whinges一些慢性。

編輯:數據是某些Unihan字符描述的數據庫。我一直在探索壓縮數據的各種方法。就目前而言,您有22399個條目,其中每個條目可能包含不同數量的字符串,或者{縮寫標記,最後一次出現的行,最後一次出現的行的元素}的三元組。

順便說一句格雷格的說話,我可能需要讓每行包含相同數量的元素,即使它們中的一些是空字符串。是這樣嗎?

編輯#2:它發生在我身上,三胞胎的一些數值超出了字符的限制。

+0

你如何索引到數組中?它看起來有點像在第二行中的{1,1,0}三元組可能指的是前一個條目(否則,它是自引用的),所以即使數組工作得最多自然從零開始。 – 2008-10-12 21:48:42

+0

你是對的。是的,1是用於生成陣列的VBScript中的一個artefact。一旦我找出如何真正讓吸盤工作,它會在某個時候進行調查。 – bugmagnet 2008-10-13 15:55:33

回答

2

我剛剛閱讀你的新帖,重新閱讀原文,我想我完全理解了這裏的目標。對不起,花了這麼長時間,我有點慢。

套用的問題,在原來的例子的第4行:

{ "(AN", "ANCIENT", {1, 2, 2}, {1, 2, 3}, "U+4E94)", "FIVE"}, 

你會希望三元轉化爲早期使用的字符串的引用,在試圖壓縮數據。這條線變成:

{ "(AN", "ANCIENT", "FORM", "OF", "U+4E94)", "FIVE"}, 

如果目標是壓縮,我認爲你不會在這裏看到很多收益。自引用三元組每3個字節,但被替換的字符串總共只有8個字節,計數爲空終止符,並且您只能在該行保存2個字節。這是使用字符。由於你的結構非常龐大,你將需要使用整數引用,所以你的三元組實際上是12個字節,這更糟糕。在這種情況下,您只能通過替換12個ASCII字符或更多的單詞節省空間。

如果我完全離開這裏,然後隨意忽略我,但我認爲在空格上標記化並刪除重複單詞的方法只是一種窮人的方式Huffman compression。霍夫曼,其中字母表是longest common substrings,或其他標準文本壓縮方法的列表可能適用於此問題。

如果由於某種原因,這不是一個選項,但我想我會得到您的數據中的所有唯一字的列表,並將其用作查找表。然後將所有字符串作爲索引列表存儲到該表中。你必須使用兩個表格,但最後它可能會更簡單,並且可以節省您現在用作「縮略標記」的前導1的空間。基本上,您的縮寫標記將成爲單個索引而不是三元組。

所以,

const char * words[] = { 
    "hello", "world", "goodbye", "cruel" 
    }; 

const int strings[] = { 
    { 0, 1 }, 
    { 2, 3, 1 } 
    }; 

你還是會失去很多的空間,如果你的字符串不是的大致均勻長度雖然。

3

在C語言中,你只能聲明數組時離開了第一尺寸:

char * abbrevs3[][22399] = { ... }; 

這是因爲編譯器要知道每個「行」有多大,以便它可以奠定正確地列出「列」。我將這些尺寸放在引號中,因爲您可以隨意以任何方式解釋尺寸,但這是二維數組的慣例。

這就是說,目前還不清楚你的數據結構究竟是什麼或者你想要初始化它到底是什麼。您的示例數據似乎沒有任何形式。

4

我會考慮以XML或其他結構化形式存儲數據,然後讀取並解析它,而不是在代碼中進行初始化。您在初始化過程中付出的代價將超過理解和提高代碼可維護性的程度。我也會考慮設計一個特定的數據結構來保存每個條目。

[編輯]下面嘗試複製您的後續描述的例子:

enum EntryType { string = 0, triple = 1 }; 

typedef struct { 
    enum EntryType entry_type; 
    union { 
     char** string; 
     int[3] *triple; 
    } 
} Entry; 

typedef struct { 
    Entry *entries; 
} Abbreviation; 

Abbreviation *abbrevs3; 

abbrevs3 = parseAbbreviationData("path-to-abbreviations/abbrevs.xml"); 
+0

我同意 - 顯式的結構定義加上文件初始化是要走的路。我同意在他們的評論中迄今爲止都回答說我們不能說出你的實際數據結構應該是什麼,所以很難給出更具體的答案。 – 2008-10-12 18:37:05

1

我覺得這裏的問題是你是否可以靜態聲明空調風格字符串的多維數組,其中有不同數量每行上的字符串。所以,像這樣:

const char * arr[][3] = 
    { 
    {"bla", "bla", "bla"}, 
    {"bla", "bla" } 
    }; 

在某些語言中,這被稱爲「鋸齒狀陣列」。在C和C++中,你可以這樣做,儘管編譯器會分配空間來存儲所有行,就好像它們的長度一樣,所以你最終不會初始化第二個數組的第三項。當我在gcc上測試這個時,該數組中的第三項被設置爲NULL,但我不知道你是否可以指望這一點。

我不認爲你能夠讓編譯器接受像{1,2,3}這樣聲明的數組作爲C風格的字符串。即使它做到了,並且你將它們當作字符串處理,你也會遇到問題,因爲它們不是空的。

我同意其他海報,更好的方法可能是將這些數據存儲在XML,yaml中,或可能存儲在數據庫中,然後在那裏訪問它們。如果您確實需要在源文件中靜態創建這些文件,您最好先聲明一個對您的數據有意義的結構並初始化這些結構的數組。例如:

typedef struct 
{ 
    const char * somestring; 
    const char * someotherstring; 
    const unsigned int triple[3]; 
} Abbreviation; 

const Abbreviation abb[] = 
    { 
    {"First Thing", "Second String", {1,2,3} }, 
    {"Other Thing", "Some String", {4,5,6} } 
    }; 
0

傳奇還沒有結束它似乎。我最終最終把所有東西都變成了一組int。但是由於這一點,失去了三聯體背後的自我指涉機制所依賴的項目的想法。

我現在正在考慮使用Euphoria而不是C,因爲它支持不規則陣列。一個人可以建立標準的DLL與幸福感,一旦我找出如何交回一個變種陣列的BSTR,並寫一個Typelib ...

請注意,我想我可以堅持C和三胞胎存儲只有三個整數在一行中,並將字符串存儲爲以整數形式投射的指針。這將爲我節省一大筆重建VBScript的工作,它首先構建了自我參照字典。

1

原始數據大約是1.7MB,它來自其他兩個文件,一個來自我的僱主,另一個來自Unicode聯合會(Unihan.txt,大約30MB)。使用字典查找技術,使用頂部128個最長和最常出現的單詞的字典,只能將數據大小降至1.5MB。我可以通過使用我的單詞檢測更加智能來改善這一點,目前它只是一個VBScript Split()。

對於準霍夫曼方法我有多小,我沒有任何數字,但我的猜測是它略低於1MB。我想把所有這些都放在二進制文件中,而不是作爲一個單獨的文件(儘管其他人可能會說壞的練習等等)。然而,就目前而言,這一切都變得有些困難,至少在C中。如果我可以找出如何創造幸福感的BSTR變種陣列...

編輯:我已經使用了字典查找相對於標準UCNs和行之有效由於字形描述的重複性。 Unihan的問題在於你最終描述了字形意味着;有"VULGAR FRACTION ONE QUARTER""A KIND OF PUNISHMENT IN HAN DYNASTY, NAME OF CHESSMEN IN CHINESE CHESS GAME(SIMPLIFIED FORM, A VARIANT U+7F75) TO CURSE; TO REVILE; TO ABUSE, TO SCOLD"

之間的定性(定量!)差異因此遠離字典查詢,以及向一些更強大的「壓縮」技術的舉動。

(和任何人說,之前,「有啥大不了的1.7MB?」,我來自一個時代,16K RAM是很多。我在任何情況下,空間的限制。)