If you want to make std::cin
read
2,147,483,646
as a long
you need to do a little bit extra, because without you std::cin
will only read the first 2
and ignore the rest.
Lets start simple....std::cin
has an overload of its operator>>
for long
but we want it to do something else. How do we make it pick a different overload? We pass a different type. However, as we dont actually want anything else than a long
we use a thin wrapper:
struct read_long_with_comma_simple_ref {
long& long;
read_long_with_comma_simple_ref(long& value) : value(value) {}
};
Once we supply our own operator>>
overload we will be able to write something like this:
long x;
std::cin >> read_long_with_comma_simple_ref(x);
So far so simple. How can we implement that operator>>
? The most simple I can think of is to simply ignore the commas:
std::istream& operator>>(std::istream& in,read_long_with_comma_simple_ref& ref) {
std::string temp;
// read till white space or new-line
in >> temp;
// remove all commas
temp.erase(std::remove(temp.begin(), temp.end(), ','), temp.end());
// use a stringstream to convert to number
std::stringstream ss(temp);
ss >> rwcs.value;
return in;
}
However, this will accept non-sense such as 12,,,34
as input and interpret it as 1234
. This we of course want to avoid and add a bit of error checking:
#include <iostream>
#include <limits>
#include <algorithm>
#include <sstream>
#include <ios>
// same as before, just different name for a different type
struct read_long_with_comma_ref {
long& long;
read_long_with_comma_ref(long& value) : value(value) {}
};
std::istream& operator>>(std::istream& in,read_long_with_comma_ref&& rwc){
std::string temp;
in >> temp;
std::reverse(temp.begin(),temp.end());
std::stringstream ss(temp);
rwc.value = 0;
long factor = 1;
for (int i=0;i<temp.size();++i){
char digit;
ss >> digit;
if (((i+1)%4)==0) {
if (digit != ',') {
in.setstate(std::ios::failbit);
rwc.value = 0;
return in;
}
} else {
int dig = digit - '0';
if (dig < 0 || dig > 9) {
in.setstate(std::ios::failbit);
rwc.value = 0;
return in;
}
rwc.value += factor* (digit-'0');
factor*=10;
}
}
return in;
}
And we can use it like this:
long x;
std::cin >> read_long_with_comma_ref(x);
if (std::cin.fail()) std::cout << "reading number failed \n";
std::cout << x;
TL;DR if you want to make std::cin
read the value 2147483646
then simply type 2147483646
and dont use the ,
as seperator, or read it as string and remove the commas before converting it to a number.