这个。
#include <iostream>
#include <sstream>
#include <inttypes.h>
using namespace std;
int main (void) {
istringstream iss("123 42");
int8_t x;
while (iss >> x) {
cout << x << endl;
}
return 0;
}
生产。
1
2
3
4
2
但我想:
123
42
Casting iss >> (int)x
(我最初尝试用 char
)给我"错误: 二进制表达式('istringstream'(又名'basic_istringstream')和'int')的操作数无效" (clang)或"错误: 'operator>>'的重载有歧义" (g++).
有没有办法将数值作为一个数字直接读入一个 8位 类型,还是必须使用中间存储?
你必须使用一个中间类型或者自己做解析。所有的char类型(char、signed char和unsigned char)都被视为文本元素,而不是整数。int8_t可能只是其中之一的类型定义,这就是为什么你的代码失败了。
请注意。
没有内置的8位类型;你使用了一个别名的 signed char
和IOStreams将 始终 当你在任何一种格式化的输入中提取一个ASCII字母的时候,你就会发现,你的输入是一个很好的例子。char
.
所以,是的,使用一个中间存储,或者包裹一个中间存储。int8_t
在一个新的类中,它为格式化的IO提供了自己的重载(我认为这是矫枉过正的,除非你有严格的内存或性能要求)。
(你的尝试 iss >> (int)x
是非常混乱的;转换是用在你要取值的表达式上,而不是用在命名你要设置值的对象的lvalues上)。)
基本的问题是 int8_t
通常(显然包括你的情况)是这样的。typedef char int8_t;
. 无论好坏,iostreams都会提供过载,用于 char
假设内容是一个字符而不是一个数字。
可以避免这种情况,比如定义你自己的类,比如。
class my_int8_t {
// ...
};
在这种情况下,你可以提供你自己的重载的 operator>>
和 operator<<
(把内容当作一个数字而不是一个字符)。
一旦你有了这些,将数据从输入复制到输出(每行一个数字)可能会更好地做一些类似的事情。
std::copy(std::istream_iterator<my_int8_t>(std::cin),
std::istream_iterator<my_int8_t>(),
std::ostream_iterator<my_int8_t>(std::cout, "\n"));
其中,这就避免了你当前代码中的一个问题,即正确检测文件的结束。
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
typedef unsigned char uint8_t;
class exstringstream : public stringstream
{
public:
exstringstream(const string& s)
:stringstream(s)
{
}
friend exstringstream& operator >> (exstringstream&, uint8_t& t);
};
exstringstream& operator >> (exstringstream& ss, uint8_t& t)
{
unsigned int val;
stringstream& s = ss;
s >> val;
t = static_cast<uint8_t>(val);
return ss;
}
int main()
{
string str("123 45");
exstringstream ss(str);
uint8_t a, b;
ss >> a >> b;
cout << a << " " << b << endl;
return 0;
}
运算符无法区分字符类型和8位signedunsigned整数类型的区别,因为它们和从语言中看到的是一样的(如其他答案中提到的),这意味着你也无法实现一个同时支持这两种类型的类运算符。
如果你需要这两种类型,你就不得不使用 scanf/printf
格式为 "hhu"
或 PRIu8
从 <cinttypes>
: