问题
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?
回答1:
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.
回答2:
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.)
回答3:
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.
回答4:
#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