C++ 从std::stringstream中读取uint8_t作为数字类型

C++ 从std::stringstream中读取uint8_t作为数字类型,c++,C++,我的理解是,从stringstream读取uint8\u t是一个问题,因为stringstream将uint8\u t解释为char。我想知道如何将uint8\t作为数字类型从stringstream中读取。例如,以下代码: #include <iostream> #include <sstream> using namespace std; int main() { uint8_t ui; std::stringstream ss("46");

我的理解是,从
stringstream
读取
uint8\u t
是一个问题,因为
stringstream
uint8\u t
解释为
char
。我想知道如何将
uint8\t
作为数字类型从
stringstream
中读取。例如,以下代码:

#include <iostream>
#include <sstream>

using namespace std;

int main()
{
    uint8_t ui;
    std::stringstream ss("46");
    ss >> ui;
    cout << unsigned(ui);
    return 0;
}

经过多次反复,答案似乎是没有标准的方法来做这件事。选项是将
uint8\u t
读取为
uint16\u t
std::string
,然后将这些值转换为
uint8\u t

#include <iostream>
#include <sstream>

using namespace std;

int main()
{
    uint8_t ui;
    uint16_t tmp;
    std::stringstream ss("46");
    ss >> tmp;
    ui = static_cast<uint8_t>(tmp);
    cout << unsigned(ui);
    return 0;
}
#包括
#包括
使用名称空间std;
int main()
{
uint8_t ui;
uint16_t tmp;
标准:stringstream ss(“46”);
ss>>tmp;
ui=静态(tmp);

cout如果您想以格式化的方式阅读,请不要使用
char
无符号char
(uint8\t)。您的示例代码及其结果是预期的行为

我们可以从中看到

template
基本流和运算符>>(基本流和st、无符号字符和ch);
这会“执行字符输入操作”

52
是“4”的ascii码。这意味着
stringstream
只读取了一个字节,仍然可以读取“6”

因此,如果您希望以所需的方式工作,您应该
sstream::operator>
使用2字节或更大的整数类型,然后将其转换为
uint8\t
——这正是您自我回答的方式

下面是这些重载的参考。

您可以为
uint8\u t
重载输入
运算符>
,例如:

std::stringstream& operator>>(std::stringstream& str, uint8_t& num) {
   uint16_t temp;
   str >> temp;
   /* constexpr */ auto max = std::numeric_limits<uint8_t>::max();
   num = std::min(temp, (uint16_t)max);
   if (temp > max) str.setstate(std::ios::failbit);
   return str;
}
std::stringstream和操作符>>(std::stringstream和str,uint8\u t&num){
uint16温度;
str>>温度;
/*constexpr*/auto max=std::numeric_limits::max();
num=标准::最小值(温度,(uint16_t)最大值);
if(temp>max)str.setstate(std::ios::failbit);
返回str;
}
现场演示:

说实话,我不确定这样的解决方案是否没有问题。有经验的人可能会澄清


更新


请注意,此解决方案通常不适用于
std::basic_istream
(以及它的实例
std::istream
),因为有一个重载的
操作符>
用于
无符号字符
:。行为将取决于
uint8\u t
的实现方式。

读取两个字节并通过
std::stoi
解析它们?这是一个丑陋的解决方案。我知道它。@freakish-不是OP,而是自己创建一个字符串并解析它,而不是溪流(它的工作对象)似乎不对劲。你的笔记对我来说没有意义-你可以阅读
uint16\u t
,从中转换,再也不用它了…当然,也有一些范围检查和流状态无效。@bruno-但是由于
std::uint8\u t
是作为数字类型而不是字符发布的,这是一个问题。我不会真的把这称为“答案”,但这是非常有用的信息。这看起来很好。如果你把它放在一个匿名名称空间中,那么我想任何损害都是有限的。尽管我刚才问了stringstreams,我想你可以很容易地将它更改为
istream
,然后覆盖所有输入流。@bremen_matt它没有看起来很简单。看这里:。编译器显然优先于
ui
char
的简单隐式转换,然后通过从派生到基的转换将
str
ss
配对。不确定如何解决此问题。@DanielLangr“编译器显然优先于
ui
到char的简单隐式转换。"–这种隐式转换不适用于引用。但是,流的
std::operator>
有一个
无符号字符&
重载。我不确定是什么原因导致明显的歧义得到了有利于
std
版本的解决,但高度怀疑libstdc++中的以下专门化:
extern模板istream&operator>>(istream&,unsigned char&)
–我想这表明对标准函数进行模糊重载是一个非常糟糕的主意。@ArneVogel哦,现在明白你的意思了。我之前没有提到()。此解决方案可能非常脆弱。我会在答案中添加一个注释。
std::stringstream& operator>>(std::stringstream& str, uint8_t& num) {
   uint16_t temp;
   str >> temp;
   /* constexpr */ auto max = std::numeric_limits<uint8_t>::max();
   num = std::min(temp, (uint16_t)max);
   if (temp > max) str.setstate(std::ios::failbit);
   return str;
}