【问题标题】:Read hex text format 0x from stream从流中读取十六进制文本格式 0x
【发布时间】:2011-10-18 11:36:23
【问题描述】:

我正在寻找一种使用流从文本文件中读取十六进制值的简单方法。我使用“C++ hex read stream 0x”搜索了 Stack Overflow,大多数回复都是关于将 hex 作为文本写入或读取没有“0x”前缀的 hex 值。这个问题是关于读取十六进制数字,在一次操作中使用“0x”前缀作为数字。

我的方法:

unsigned char byte;
std::istringstream sample("0xce");
sample >> std::hex >> byte;

byte 结尾,从第一个字符开始包含 '0' (0x30)。

'strtol' 函数处理转换,但需要读取数据,转换为 C 风格的字符串。

我在一个类中重载operator>> 以读取逗号分隔值 (CSV) 文本文件。以下是数据文件的示例:

1,-4.93994892,0xa5,8,115.313e+3,
2,-4.93986238,0xc0,8,114.711e+3,
3,-4.93977554,0xc2,8,114.677e+3,

我的提取方法:

class Csv_Entry
{
public:
    friend std::istream& operator >>(std::istream& inp, Csv_Entry& ce);
    unsigned int    m_index;
    double      m_time;
    unsigned char   m_byte;
    unsigned int    m_data_length;
    double      m_bit_rate;
};

std::istream&
operator >> (std::istream& inp, Csv_Entry& ce)
{
    char    separator;
    inp >> ce.m_index;
    inp >> separator;
    inp >> ce.m_time;
    inp >> separator;
    inp >> std::hex >> ce.m_byte;
    inp >> separator;
    inp >> ce.m_data_length;
    inp >> separator;
    inp >> ce.m_bit_rate;
    inp.ignore(10000, '\n');
    return inp;
}

我需要使用std::setw吗?

编辑 1:
我在 Windows 7 64 位平台上使用 Visual Studio 2010 Premium。

【问题讨论】:

  • 您可以省去自己解析 cvs 文件的麻烦,并使用足够灵活的现成解析器生成器来处理所有情况(包括 unicode):tinyurl.com/3zs2o6k
  • @Gene Bushuyev:感谢您的建议。我一直认为解析器对于简单的 CSV 文件来说太过分了。如果涉及语言或复杂协议,我会使用解析器。这个程序是一个小型分析器,我认为解析器会使程序过于复杂。

标签: c++ text stream hex


【解决方案1】:

一种解决方案是使用unsigned int 读取值,然后转换为unsigned char

unsigned int value;
inp >> hex >> value;
unsigned char byte;
byte = value & 0xFF;

我猜想unsigned char 类型是有问题的。

任何 C++ 语言的律师都可以引用描述这种行为的部分吗?

【讨论】:

  • 这是一个文本流,字符被读取为符号,而不是值;因此 '0' 被读取为值为 0x30 的字符。
  • 是的,是 int 数据类型而不是 char 在这里有所不同。根据规范,showbase 不会影响输入流。我不确定这适用于哪些编译器,请参阅此线程以获取一些示例:gamedev.net/topic/540229-simple-question-of-integer-input-c
  • @Gene Bushuyev:unsigned 字符是否仍被视为符号(字符)?我来自嵌入式系统领域,我们使用 unsigned char 作为数字类型,而不是字符。
  • @Thomas -- 流是文本,运算符>> 对于所有 char 类型(singed/unsigned,charT)都重载
  • C++03 §27.6.1.2.2 [lib.istream.formatted.arithmetic] 说对于算术类型,提取器使用语言环境的 num_get<> 对象来解析输入流。根据 §22.2.2.1/2 [lib.facet.num.get.virtuals],字符根据 scanf 使用适当的格式说明符(表 55-56)进行解释,即 %X 用于 unsigned int .但是,charunsigned char 不被视为算术类型; §27.6.1.2.3 描述了它们的行为。
【解决方案2】:

问题在于Csv_Entrym_byte 成员的数据类型。在对输入数据进行输入流提取时,它将0 解释为有效值,然后将x 解释为分隔符,因此丢弃流提取中的其余值。如果您将Csv_Entry::m_byte 成员更改为unsigned int,问题就会消失,它会使用std::hex 正确解释十六进制值。

顺便说一句,由于您的所有成员都是公开的,您不妨将Csv_Entry 设为一个结构,但这里有一些使用您的条目数据的示例工作代码:http://ideone.com/H7NG1

您会注意到在输出端,我只需要包含 std::hexstd::showbase 即可正确打印十六进制值。

【讨论】:

    【解决方案3】:

    Thomas Matthews 对。您必须从 unsigned int 转换为 unsigned char

    如果您方便使用 C 函数 scanf/printf,您会注意到它们的行为相似。但我认为它们对这种情况更具描述性。

    //%X specifies that we trying read integer in format 0x123FFF
    //%c specifies that we trying read character
    //0xABC is input string
    
    unsigned char hex;
    sscanf("0xABC", "%X", &hex); // error because not enough memory allocated
                                 // by address &hex to store integer
    
    unsigned char hex;
    sscanf("0xABC", "%c", &hex); // reads only one character '0'
    

    所以我的意思是,您可以读取十六进制整数或读取字符,但您尝试“读取字符中的十六进制整数”。所以针对 stdlib 开发人员的具体案例)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-04
      • 2014-02-25
      • 1970-01-01
      • 2015-05-01
      • 1970-01-01
      • 2012-02-07
      相关资源
      最近更新 更多