Reputation: 17
so i've seen many people ask this and not many solid answers floating around the web. most just check that an integer was placed in place of a string but if a floating point number was entered then it truncates the bottom half or if integers and characters are intered it truncates the characters. i need help writing a piece of code that checks for user input and asks the user to retry if his input is not valid or a combination of valid/invalid. i think the basic idea was to make a string so it accepts anything then use sstream to manipulate and then back to int if the input was legit but i cant really manage to check the other parts. if anyones run accross this or can help me out please link me to it. i'll post my code when i get a good sense of what to do.
Upvotes: 0
Views: 510
Reputation: 38912
You can use C++11 string conversion functions like stol
try
{
std::string value = ...;
long number = std::stol(value);
}
catch (std::invalid_argument const& e)
{
// no conversion could be performed
}
Post-comments update: Visual C++ 11 shipped with Visual Studio 2012 implements std::stol
as a convenient wrapper around strtol
declared in <cstdlib>
. I think it's safe to assume most C++11 implementations define it in most optimal way possible, not reaching for std::stringstream
machinery.
Upvotes: 2
Reputation: 17595
I don't know if there are any classes in standard c++ lib that encapsule primitive types like in java but here how a simple and very basic implementation would look like
class Integer {
private:
int value;
void parse(string);
public:
Integer(string);
int intValue();
};
Integer::Integer(string sint) { parse(sint); }
int Integer::intValue() { return value; }
void Integer::parse(string sint) {
string::iterator its = sint.begin();
while(its != sint.end() && (! (*its < '0' || *its > '9'))) {
its++;
}
if(its != sint.end()) {
throw sint + ": Input is not a valid integer.";
}
value = atoi(sint.c_str());
}
Upvotes: 0
Reputation: 168626
Assuming that you can't use boost::lexical_cast
, you can write your own version:
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <cstdlib>
template <class T1, class T2>
T1 lexical_cast(const T2& t2)
{
std::stringstream s;
s << t2;
T1 t1;
if(s >> std::noskipws >> t1 && s.eof()) {
// it worked, return result
return t1;
} else {
// It failed, do something else:
// maybe throw an exception:
throw std::runtime_error("bad conversion");
// maybe return zero:
return T1();
// maybe do something drastic:
exit(1);
}
}
int main() {
std::string smin, smax;
int imin, imax;
while(std::cout << "Enter min and max: " && std::cin >> smin >> smax) {
try {
imin = lexical_cast<int>(smin);
imax = lexical_cast<int>(smax);
break;
} catch(std::runtime_error&) {
std::cout << "Try again: ";
continue;
}
}
if(std::cin) {
std::cout << "Thanks!\n";
} else {
std::cout << "Sorry. Goodbye\n";
exit(1);
}
}
Upvotes: 2
Reputation: 129374
The C function strtol
(and it's siblings) will be able to tell you if the string fed to it is completely consumed.
std::string str;
char *endptr;
std::cin >> str;
long x = std::strtol(str.c_str(), &endptr, 0);
if (*endptr != 0)
cout << "That's not a valid number...";
Upvotes: 1