This:
#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;
}
Produces:
1
2
3
4
2
But I want:
123
42
Casting iss >> (int)x
(I initially tried this with a char
) gives me "error: invalid operands to binary expression ('istringstream' (aka 'basic_istringstream') and 'int')" (clang) or "error: ambiguous overload for ‘operator>>’" (g++).
Is there a way to read the value as a number directly into an 8-bit type, or do I have to use an intermediary store?
You have to use an intermediate type or do the parsing yourself. All char-types (char, signed char and unsigned char) are treated as text elements, not integers. int8_t is probably just a typedef for one of them, which is why your code fails.
Note:
- The output will suffer from the same issues.
- Don't use C-style casts, they almost only cause errors.
- Checking for EOF before an input operation is useless, you need to check for failure afterwards instead.
There is no built-in 8-bit type; you're using an alias for signed char
and IOStreams will always extract a single ASCII letter when you do formatted input into any kind of char
.
So, yes, use an intermediary store, or wrap int8_t
in a new class that provides its own overloads for formatted I/O (which I'd consider overkill unless you have strict memory and/or performance requirements).
(Your attempt of iss >> (int)x
is very confused; conversions are used on expressions you're about to take the value of, not for lvalues naming objects that you want to set the value of.)
The fundamental problem is that int8_t
is normally (apparently including your case) something like: typedef char int8_t;
. For better or worse, iostreams provide overloads for char
that assume the content is a character instead of a number.
It's possible to avoid this, such as by defining your own class such as:
class my_int8_t {
// ...
};
In this case, you can provide your own overloads of operator>>
and operator<<
for that type (that treat the content as a number instead of a character).
Once you have that, copying the data from input to output (one number per line) is probably better done something like:
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"));
Among things, this avoids a problem in your current code with detecting the end of file correctly.
#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;
}
来源:https://stackoverflow.com/questions/25230473/istringstream-decimal-integer-input-to-8-bit-type