【问题标题】:How to read hex values into integer with fstream (C++)如何使用 fstream (C++) 将十六进制值读入整数
【发布时间】:2018-11-19 09:16:26
【问题描述】:

我正在尝试从二进制文件中读取一个 little-endian 十六进制字符串,并将该值放入一个整数中以使用它。当我尝试阅读时,我得到的是 ascii 符号,而不是数字。我试过演员和atoi,似乎没有任何效果。使用 fstream 将十六进制字符串从文件读入整数的最佳方法是什么?

这基本上是我的程序:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main(int argc, char* argv[]) {
    fstream input;
    fstream output;
    char cbuffer[4];
    char revbuffer[8];

    input.open(argv[1], fstream::binary | fstream::in);
    output.open("output.txt", ios::out | ios::app);
    input.seekg(16, input.beg);
    input.read(cbuffer, 4);

    cout << sizeof(revbuffer) << endl;
    cout << cbuffer[0] << cbuffer[1] << cbuffer[2] << cbuffer[3] << endl;
}

【问题讨论】:

  • 该值是否真的以十六进制字符串形式存储在文件中?您提到了字节顺序,并且从文件中读取了 4 个字符,因此十六进制字符串似乎不太可能。
  • 也许不是,我真的不知道怎么称呼它。我对编程相当陌生。该值位于偏移量 0x10 处,类似于 [in hex] 00 92 f8 03。该数字应为 0x03f89200。

标签: c++ input hex fstream atoi


【解决方案1】:

如果它是以二进制格式存储的整数值,我猜它要么是int32_t,要么是uint32_t。既然您提到该值是以小端字节顺序存储的,我想您想确保运行您的程序的主机将其转换(如果需要)。 C++20 有std::endian。如果这对您不可用,通常可以使用宏来在编译时检测字节顺序,而不是我使用的 std::endian 测试。我假设该值是下面的uint32_t

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <type_traits> // std::endian

// little endian unsigned 32 bit integer to host byte order
inline uint32_t Le32toh(uint32_t le) {
    #if __cplusplus <= 201703L
    // run-time check
    static constexpr uint16_t endian = 1;
    if(*reinterpret_cast<const uint8_t*>(&endian)==1) return le;
    #else
    // compile-time check
    static_assert(std::endian::native == std::endian::little || std::endian::native == std::endian::big);
    if constexpr (std::endian::native == std::endian::little) return le;
    #endif

    const uint8_t* c=reinterpret_cast<const uint8_t*>(&le);
    return // little-to-big endian conversion
        (static_cast<uint32_t>(c[0])<<24) |
        (static_cast<uint32_t>(c[1])<<16) |
        (static_cast<uint32_t>(c[2])<<8) |
        (static_cast<uint32_t>(c[3]));

    return le;
}


int main(int argc, char* argv[]) {
    std::vector<std::string> args(argv+1, argv+argc);

    std::fstream output("output.txt", std::ios::out | std::ios::app);

    uint32_t cbuffer;

    for(const auto& file : args) {
        std::fstream input(file, std::fstream::binary | std::fstream::in);
        input.seekg(16, input.beg);
        // read directly into the varibles memory
        input.read(reinterpret_cast<char*>(&cbuffer), 4);
        // output the value unconverted
        std::cout << std::hex << cbuffer << "\n";
        // convert if needed
        cbuffer = Le32toh(cbuffer);
        // output the value converted
        std::cout << std::hex << cbuffer << "\n";
    }
}

【讨论】:

  • 感谢您的回复。我收到一个错误:'std::endian' 尚未声明。但是仅使用 main 我现在可以将值读取为 int。非常感谢!
  • 太棒了!是的,std::endian 是 C++20 的一项功能,因此为了能够在 C++17 和更早的编译期间执行类似的操作,您必须求助于一些非标准的字节序宏 - 或进行运行时检查。我也会补充的。
猜你喜欢
  • 2011-07-30
  • 2010-12-07
  • 1970-01-01
  • 1970-01-01
  • 2018-04-26
  • 2010-11-26
  • 2021-09-29
  • 2015-09-10
  • 1970-01-01
相关资源
最近更新 更多