将 XML 流转换为十六进制

Converting an XML stream to hexadecimal

本文关键字:十六进制 转换 XML      更新时间:2023-10-16

所以我对C++相当陌生,希望得到一些建设性的建议。

我目前正在研究一个科学火箭的遥测系统,该系统从仪器中获取数据,从软件中存储来自管道的数据,然后将这些数据发送到可用的串行端口。问题是仪器以XML格式传输数据包,例如:

<Sample Value="-4.80521e-012" />
<Sample Value="4.90272e-012" />
<Sample Value="3.49013e-011" />
<Sample Value="2.13785e-010" />
<Sample Value="2.38185e-010" />
<Sample Value="1.70573e-010" />
<Sample Value="1.16129e-011" />

这些暂时存储在由CreateFile/WriteFile(从串行端口)创建的缓冲区中。探测器本身不能发送 XML 以外的其他格式,我需要将其隐式或显式转换为 4 字节十六进制(由于遥测要求),例如:

2c34b73f 2c1dfc77 2bbd69d2 a9220b89 a8a0cedf 290bc781...

那么我的问题是:谁能提出一个好方法?我应该尝试从流中删除子字符串集,还是在 XML 和十六进制之间进行转换的更简单的方法?我再次指出,这项工作将在C++进行。

此致敬意

塔吉伊

该问题包括 2 个步骤:解析 XML 并将浮点数转换为其在 IEEE 754 中的表示形式为十六进制值。

对于解析 XML,有几个库可以简单地重用。您只需考虑您的输入是始终是完整、有效的 XML,还是仅是无法独立存在的片段。我不确定你的问题是否是这种情况。

为了将浮点数转换为 IEEE 754 十六进制,大多数系统在内部表示 IEEE 754 中的浮点数。如果您的系统是这种情况,您只需找到表示

您可以使用它(来自此问题的输入):

std::string floatToIEEE754(float f) {
    if (!std::numeric_limits<float>::is_iec559) {
        std::cerr << "Not in IEEE 754 format!" << std::endl;
        return "";
    }
    std::stringstream ss;
    ss << std::hex << std::setw(2);
    ss << static_cast<int> (reinterpret_cast<unsigned char*>(&f)[0]);
    ss << static_cast<int> (reinterpret_cast<unsigned char*>(&f)[1]);
    ss << static_cast<int> (reinterpret_cast<unsigned char*>(&f)[2]);
    ss << static_cast<int> (reinterpret_cast<unsigned char*>(&f)[3]);
    // Or to get it as int:
    //int i;
    //ss >> i;
    //return i;
    return ss.str();
}

奇怪的演员阵容是必要的,以确保符合语言。严格来说,如果将一种指针类型转换为另一种指针类型(如 int i = *((int*)&f); 所示),则C++具有未定义的行为。只有投射到char*才能保证工作。

如果对系统没有严格的要求,可以按如下方式简化方法:

std::string floatToIEEE754(float f) {
    std::stringstream ss;
    // Treat bits of float as an int, and print them as hex
    ss << std::hex << *((int*) &f);
    return ss.str();
}

如果来自仪器的数据只是非常简单的XML,如您的示例所示,则可能不需要完整的xml解析器,但您可以"手动"解析每一行。

对于每一行,提取表示值的子字符串:

<Sample Value="-4.80521e-012" />

成为

-4.80521e-012

然后解析提取的子字符串"-4.80521e-012"例如使用 sscanfstrtof 以获得 32 位float,最后将该浮点数强制转换为unsigned long并对其进行sprintf("08x",..)