相关:flexible array member in a nested struct
我正在尝试将一些数据解析为结构。数据包含如下组织的信息:
struct unit {
struct unit_A {
// 28 bytes each
// dependency r6scA 1
char dr6scA1_tagclass[4];
uint32_t dr6scA1_tagnamepointer;
uint32_t dr6scA1_tagnamestringlength;
uint32_t dr6scA1_tagid;
// 12 bytes of 0x00
}A;
// A strings
struct unit_B {
// 48 bytes each
// dependency r6scB 1
char dr6scB1_tagclass[4];
uint32_t dr6scB1_tagnamepointer;
uint32_t dr6scB1_tagnamestringlength;
uint32_t dr6scB1_tagid;
// 32 bytes of 0x00
}B;
// B strings
// unit strings
}unit_container;
你可以忽略这种奇怪的命名法。
我的评论// A strings
,// B strings
和// unit strings
每个都包含以空字符结尾的C字符串,其数量与许多unit_A
,unit_B
重合,以及数据中的unit
结构条目。因此,如果A
中有unit_container
的5个条目,那么在// A strings
所在的位置会有5个C字符串。
由于我不能在这些位置使用灵活的数组成员,我应该如何解释数据中这些位置基本上未知数量的可变长度C字符串?
例如,这些位置的数据可能是:
"第一个条目在这里。\ 0第二个条目\ 0另一个!\ 0第四个。\ 0这第五个条目是最合适的条目evah以任何合理的标准。\ 0"
...我希望我应该解释为:
char unit_A_strings[]
......但这是不可能的。我有什么选择?
感谢您的考虑。
编辑:
我认为到目前为止最吸引人的选择是:
char** unit_A_strings;
指向一个char字符串数组。
如果我这样做:
char unit_A_strings[1];
定义一个固定大小为1 char的char数组,然后我必须放弃sizeof(unit)等,或者对内存分配大小很麻烦,即使它对于存在的数据类型最准确。如果我char * unit_A_strings[1];
,则会出现同样的情况。
另一个问题:使用char *unit_A_strings;
和char** unit_A_strings;
之间有什么区别?
结论:
主要问题是结构用于固定大小的信息,我需要的是可变大小的信息存储区域。因此,我无法合法地将数据存储到结构中 - 至少不是作为结构。这意味着任何其他解释都没有问题,在我看来char**
是这种结构情况的最佳选择。
答案 0 :(得分:0)
我认为它可以使用char **(或者你可以编写一些结构来包装它)。 例如,您可以编写帮助函数来解码流。
char** decodeMyStream(uint_8* stream, unsigned int* numberOfCString)
{
*numberOfCString = decodeNumberOfCString(stream);
char** cstrings = malloc((*numberOfCString) * sizeof(char*));
unsigned int start = 0;
for (unsigned int i = 0; i < *numberOfCString; ++i)
{
usigned int len = calculateIthStringLength(stream, start)
cstrings[i] = malloc((len) * sizeof(char));
memcpy(cstrings[i], stream + start, len);
start += len
}
return cstrings;
}
它只是没有思考示例代码,你可以想出更好的算法。
答案 1 :(得分:0)
我认为你最接近的是提供一系列字符串:
import java.applet.*;
import java.awt.*;
public class Breakout extends Applet implements Runnable{
Thread thread = new Thread(this);
boolean running = true;
//Brick b;
Brick2 b2;
Paddle p;
Ball ba;
Image dbImage;
Graphics dbg;
public void init(){
setSize(800,600);
//b = new Brick(this);
b2 = new Brick2(0,0);
p = new Paddle(this);
ba = new Ball(this);
}
public void start(){
thread.start();
}
public void destroy(){
running = false;
}
public void stop(){
running = false;
}
public void run(){
while(running){
//b.update(this,ba);
b2.update(ba);
p.update(this);
ba.update(this,p);
repaint();
try{
thread.sleep(20);
}
catch (InterruptedException e){
System.out.println("AN ERROR HAS OCCURED");
}
}
}
public void update(Graphics g, Brick2 b){
dbImage = createImage(getWidth(),getHeight());
dbg = dbImage.getGraphics();
paint(dbg);
g.drawImage(dbImage,0,0,this);
}
public void paint(Graphics g){
g.fillRect(0,0,800,600);
//b.paint(g,this);
b2.paint(g);
p.paint(g,this);
ba.paint(g,this);
}
}
注意两件事:
char *AStrings[] = { "The first entry is here.",
"Second entry",
"Another!",
"Fourth.",
"This 5th entry is the bestest entry evah by any reasonable standards.",
NULL
};
是一个指向字符串的指针数组 - 它将是6个(见下面的2.)指向实际字符串的连续指针,而不是&#39;复合&#39;您在示例中使用的字符串。AStrings
指针结束AStrings
,以解决&#34;我何时完成?&#34;问题。所以你可以&#34;掉线&#34; NULL
并开始将位置视为指针 - 但要小心!编译器可以在一个变量和下一个变量之间放入各种填充,弄清楚它们在内存中相对于彼此的位置 - 包括重新排序它们!
修改强> 哦!我只是想了一下。另一个可能有用的数据表示基本上就是你所做的。我已经'漂亮了'&#39;它有点:
A
char AString[] = "The first entry is here.\0"
"Second entry\0"
"Another!\0"
"Fourth.\0"
"This 5th entry is the bestest entry evah by any reasonable standards.\0";
字符。我把它们专门放在上面。NUL
放在任何字符串的末尾 - 在上例中的分号('\0'
)处。这意味着字符串实际上以两个NUL字符结尾,而不是一个。您可以使用该事实来跟踪解析字符串&#39;数组的位置。 - 假设每个所需的值都有一个超过零长度的(子)字符串!一旦遇到零长度(子)字符串,您就知道您已经到达字符串&#39;数组的末尾。
我将这些字符串称为ASCIIZZ字符串(ASCIIZ字符串,并在所有字符串的末尾添加第二个NUL)。