istringstream decimal integer input to 8-bit type

隐身守侯 提交于 2019-12-20 01:10:30

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!