我的理解是,从uint8_t
读取stringstream
是一个问题,因为stringstream
会将uint8_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;
}
打印出52
。我希望它打印出46
。
编辑:一种替代方法是只从string
中读取stringstream
,然后将解决方案转换为uint8_t
,但这会破坏良好的链接属性。例如,在我必须编写的实际代码中,我经常需要这样的东西:
void foobar(std::istream & istream){
uint8_t a,b,c;
istream >> a >> b >> c;
// TODO...
}
答案 0 :(得分:6)
您可以为operator>>
重载输入uint8_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;
}
实时演示:https://wandbox.org/permlink/cVjLXJk11Gigf5QE
说实话,我不确定这样的解决方案是否没有问题。更有经验的人可能会澄清。
更新
请注意,此解决方案通常不适用于std::basic_istream
(及其实例std::istream
),因为operator>>
的{{1}}过载:{{3 }}。然后,行为将取决于如何实现unsigned char
。
答案 1 :(得分:1)
经过反复的反复,答案似乎是没有标准的方法可以做到这一点。选项是将uint8_t
读为uint16_t
或std::string
,然后将这些值转换为uint8_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;
}
但是,这种解决方案忽略了范围检查。因此,如果需要,您将需要自己实现。
答案 2 :(得分:0)
如果要以格式化的方式阅读,请不要使用char
或unsigned char
(uint8_t)。您的示例代码及其结果是预期的行为。
我们从https://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt2看到
template< class Traits >
basic_istream<char,Traits>& operator>>( basic_istream<char,Traits>& st, unsigned char& ch );
这是“执行字符输入操作”。
52
是'4'的ASCII码。这意味着stringstream
仅读取了一个字节,并且仍准备读取“ 6”。
因此,如果您希望以期望的方式工作,则应为sstream::operator>>
使用2字节或更大的整数类型,然后将其强制转换为uint8_t
-您可以自行回答。
这里是这些重载的参考。 https://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt