gpt4 book ai didi

c++ - 如何在对象中表示不规则但有序的数据?

转载 作者:太空宇宙 更新时间:2023-11-04 11:22:45 25 4
gpt4 key购买 nike

我有一组包含二进制数据的文件。每个文件都由 block 组成,每个 block 都有一个标题,然后是一组事件。每个事件都有一个标题,然后是一系列字段。我的问题是字段的顺序。

这些字段包含不同长度的有序/结构化数据,但这些字段没有任何特定的顺序。例如,在一个事件中,我可能在一个事件中有 3 个字段,如下所示:

Event Header (12 bytes, always, made of things like number of fields, size, etc)
Field Header (2 bytes, always, field type in the top 4 bits, size in the bottom 12)
Field Data (4299-4298(VDC) data, Signals from various wires in a vertical drift chamber)
Field Header ( '' )
Field Data (ADC-LAS data, Signals from various photo multiplier tubes)
Field Header ( '' )
Field Data (FERA data, Signals from a fast encoding readout adc system)

在另一个事件中,我可能有相同的字段加上更多,或者删除一个字段并添加另一个字段,等等。这完全取决于 DAQ 硬件的哪些部分在读出系统触发时有数据要记录。

我已经考虑了一些可能的解决方案,老实说,我似乎对它们都不满意。

方法一:
创建一个抽象基类 Field然后对于每个字段类型(只有 13 个)从中继承。
优点: 从文件中读取数据很容易,只需获取区域 ID、分配适当类型的字段、读取数据并存储一个 Field*。 .此外,这种方法符合我对万物归位和万物各就其位的感觉。
缺点: 当我处理事件中的字段以将数据转换为分析实际使用的信息时,我一直需要 dynamic_cast<>()派生类的一切。这有点乏味和丑陋,我记得在某个地方(不久前)读过,如果你不得不使用 dynamic_cast<>()那么你使用的多态性是“错误的”。这也使得为字段设置对象池变得棘手,因为我需要为 Field 的每个子类创建一个池。 .最后,如果后面增加了更多的字段类型,那么除了修改处理代码外,还需要创建额外的字段子类。

方法二:
只需要一个大字节数组来存储所有字段标题和数据。然后将其留给处理代码来提取结构并处理数据。
优点:这意味着如果将来数据格式发生变化,那么唯一需要更改的是事件处理代码。这是一个非常简单的解决方案。它更灵活。
缺点: 处理/读取代码中的作业划分较少。感觉不够优雅。

我认识到可能没有一种解决方案在各个方面都是“优雅”的,从 KISS 的角度来看,我倾向于方法 2。我应该选择方法 1、方法 2 还是有没有我没有想到的方法三?

最佳答案

您正在尝试在结构或元组或 MSRA 安全协议(protocol)处理程序之间进行选择

`//示例程序 #包括 #包括 #包括 #包括

// start ABI Protocole signature
const int EVENT_HEADER_SZ = 12;
const int FIELD_HEADER_SZ = 2;
const int FIELD_DATA_SIZE = 2^12;
// end ABI Protocole
#ifdef WINDOWS
#define __NOVT __declspec(novtable
#else
#define __NOVT
#endif

struct Protocole_Header __NOVT {
union {
char pbody[EVENT_HEADER_SZ+1];
unsigned ptype : 32;
unsigned psize : 32;
unsigned pmisc : 32;
};
};
struct Field_Header __NOVT {
union {
char fbody[FIELD_HEADER_SZ+1];
unsigned ftype : 4; // type of data 0...15
unsigned fsize : 12; // size of field data to follow up 0..4096 max size
};
};
struct Field_Data {
std::string _content;
};

typedef std::tuple<uint_fast32_t, int_fast32_t,uint_fast32_t> Protocole_Header2;
enum PHR{
TPL_TYPE,
TPL_SIZE,
TPL_ETC
};

std::istream& operator >>(std::istream &is, std::tuple<uint_fast32_t, int_fast32_t,uint_fast32_t>& tpl)
{
is >> std::get<TPL_TYPE>(tpl) >> std::get<TPL_SIZE>(tpl) >> std::get<TPL_ETC>(tpl);
return is;
}


union Field_Header2 {
char fbody[FIELD_HEADER_SZ];
unsigned ftype : 4; // type of data 0...15
unsigned fsize : 12; // size of field data to follow up 0..4096 max size
};


int main()
{
Protocole_Header ph;
Field_Header fh;
Field_Data fd;

long i;
char protocole_buffer[FIELD_DATA_SIZE+1];

std::cin.get(ph.pbody,EVENT_HEADER_SZ);
std::cin.get(fh.fbody,FIELD_HEADER_SZ);
for(i=0;i<ph.psize;++i)
{
std::cin.get(protocole_buffer,fh.fsize);
fd._content = protocole_buffer; // push somewhere else
std::cin.get(fh.fbody,FIELD_HEADER_SZ);
}
// ...


// ...
Protocole_Header2 ph2;
Field_Header2 fh2;
std::cin >> ph2;
std::cin.get(fh2.fbody,FIELD_HEADER_SZ);
for(i=0;i<std::get<TPL_SIZE>(ph2);++i)
{
std::cin.get(protocole_buffer,fh.fsize);
fd._content = protocole_buffer; // push somewhere else
std::cin.get(fh2.fbody,FIELD_HEADER_SZ);
}
}`

在这里,你有两个答案......

请注意,在结构上使用元结构与找回代码并在协议(protocol)破裂的情况下重新编译它一样是一种负担。通常你不会为协议(protocol)结构定义 ABI,这就是为什么要创建 C++ Spirit。

必须使用解析器来处理 protocole(总是,因为 protocole 本身就是一种语法,定义一个 EBNF 并且您的代码将运行数十年而无需人们重新编译它......)

唯一的异常(exception)是不使用解析器,当您需要通过 MSRA 或 Heatlh Care 或任何受监管部门时。其余时间,不要使用 C 或 C++ 将外部数据绑定(bind)到 ABI 结构,这是 100% 的错误原因。

关于c++ - 如何在对象中表示不规则但有序的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27723805/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com