0

Let's say I want the user to input an integer but he enters a double or a character value, how do I check that the the user has input the correct type.

string line;
getline(cin, line);
// create stringstream object called lineStream for parsing:
stringstream lineStream(line); 
string rname;
double res;
int node1,node2;
lineStream >> rname >> res >> node1 >> node2;

How do I check for valid input type?

2
  • You can enable exceptions and catch them Commented Sep 28, 2013 at 15:51
  • I don't remember how I did this, sorry Commented Sep 28, 2013 at 15:52

3 Answers 3

1

You check the stream is OK:

if (lineStream >> rname >> res >> node1 >> node2)
{
    // all reads worked.
}

You may want to check for garbage on the end.

if (lineStream >> rname >> res >> node1 >> node2)
{
    char x;
    if (lineStream >> x)
    {
         // If you can read one more character there is junk on the end.
         // This is probably an error. So in this situation you
         // need to do somethings to correct for this.
         exit(1);
    }

    // all reads worked.
    // AND there is no junk on the end of the line.
}

Comment expanded.

From the comments below:

if i input an integer for rname, it still works. for exmaple:

string line; getline(cin, line);
stringstream lineStream(line); // created stringstream object called lineStream for parsing
string rname; 
if (lineStream >> rname) { cout << "works"; }

Lets assume there is some properties about rname that allow us to distinguish it from a number. For example: it must be a name. i.e. it must only contain alpha characters.

struct Name
{
    std::string   value;
    friend std::istream& operator>>(std::istream& s, Name& data)
    {
        // Read a word
        s >> data.value;

        // Check to make sure that value is only alpha()
        if (find_if(data.value.begin(), data.value.end(), [](char c){return !isalpha(c);}) != str.end())
        {
            // failure is set in the stream.
            s.setstate(std::ios::failbit);
        }
        // return the stream
        return s;
    }
};

Now you can read a name.

Name rname; 
if (lineStream >> rname) { cout << "works"; }

This will fail if you enter an integer for rname.

Stretch Answer

If you have multiple lines of the same information you want to read. Then it is worth wrapping it in a class and defining a input stream operator.

strcut Node
{
    Name   rname;
    double res;
    int    node1;
    int    node2;

    friend std::istream& operator>>(std::istream& s, Node& data)
    {
        std::string line;
        std::getline(s, line);

        std::stringstream linestream(line);
        lineStream >> data.rname >> data.res >> data.node1 >> data.node2;

        if(!linestream)
        {
            // Read failed.
            s.setstate(std::ios::failbit);
        }
        return s;
    }
};

Now it becomes easy to read the lines in a loop:

Node n;
while(std::cin >> n)
{
    // We read another node successfully
}
Sign up to request clarification or add additional context in comments.

4 Comments

if i input an integer for rname, it still works. for exmaple: string line; getline(cin, line); stringstream lineStream(line); // created stringstream object called lineStream for parsing string rname; if (lineStream >> rname); { cout << "works"; }:
I don't know if you can read that but when i run the program and input lets say.. 5, it will still print "works"
@Andy: Yes because an integer is just a set of characters and thus is a valid string. If you want to define rname as its own type that has some special properties you can define the input operator that validates it. Is there some requirements about rname that make it look different from an integer?
@Andy this is because integer 123 is also considered as string, if you are checking for strings.
0

Since string 123 will also be considered as string, and not an integer, so the better way is to iterate the string to end, until we find any non-digit character. here's how you may do it:

bool is_number(const std::string& s)
{
    std::string::const_iterator it = s.begin();
    while (it != s.end() && std::isdigit(*it)) ++it;
    return !s.empty() && it == s.end();
}

Comments

0

Read node1 and node2 into strings first, then validate with a regular expression.

#include <regex>
...
string node1_s, node2_s;
linestream >> rname >> node1_s >> node2_s
if (regex_match(node1_s, regex("[+-]?[0-9]+") {
    /* convert node1_s to int */
} else {
    /* node1_s not integer */
}
/* Do same for node2_s */

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.