2008-10-12 28 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是很多。我在任何情况下,空间的限制。)