954,480 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

std:: cin question

How Would i be able to check for valid input on cin or getline

heres what i have

#include <iostream>
#include <string.h>

using namespace std;

int main()
{
string word;

getline(cin, word);

cout << word;


system("PAUSE");
return EXIT_SUCCESS;
}


what i mean by valid input is either if the user enters an integer when i wanted a string or if the user enters nothing and causes weird results

RyanMcMillan
Newbie Poster
11 posts since Mar 2011
Reputation Points: 10
Solved Threads: 0
 

what constitutes as valid input?

firstPerson
Senior Poster
3,923 posts since Dec 2008
Reputation Points: 841
Solved Threads: 608
 

That depends on your definition of "valid input". As this code is written, almost any input would be "valid".

Fbody
Posting Maven
2,930 posts since Oct 2009
Reputation Points: 833
Solved Threads: 393
 

what i mean by valid input is either if the user enters an integer when i wanted a string or if the user enters nothing and causes weird results

RyanMcMillan
Newbie Poster
11 posts since Mar 2011
Reputation Points: 10
Solved Threads: 0
 

Wanting a string is easy, even if there are digits in it :)
A user entering nothing is even easier as your program will not get any input.
To verify a particular input you can set exceptions to be thrown when things go awry or take everything as a string and verify what you get by hand.

It depends highly on what you expect to read from the user.

L7Sqr
Practically a Master Poster
656 posts since Feb 2011
Reputation Points: 201
Solved Threads: 123
 

Wanting a string is easy, even if there are digits in it :) A user entering nothing is even easier as your program will not get any input. To verify a particular input you can set exceptions to be thrown when things go awry or take everything as a string and verify what you get by hand.

It depends highly on what you expect to read from the user.

no but sometimes , for example when the cin statement is in a while loop with conditional statement involved with the input and the user enters nothing, it causes the program to cause extremly abnormal results

RyanMcMillan
Newbie Poster
11 posts since Mar 2011
Reputation Points: 10
Solved Threads: 0
 

you mean for example:

int x;
cin >> x;

when someone input a string? You can try for example something like this:

int x;
        for (;;)
        {
                cin >> x;

                if (cin.fail())
                {
                        cin.clear();
                        cin.ignore(1000, '\n');
                }
                else
                {
                        break;
                }
        }

        cout << x << endl;

if you get "fail" it can mean that someone does not enter valid input. But remember that if he enter something like "111randomtext" stream will be ok and your x will become "111".. so it is not a perfect way to validate input :)
Anyway you can simply read line to string and write your own validating function.

ic3k
Newbie Poster
1 post since Mar 2011
Reputation Points: 10
Solved Threads: 0
 
no but sometimes , for example when the cin statement is in a while loop with conditional statement involved with the input and the user enters nothing, it causes the program to cause extremly abnormal results


Yes. I understand that user input is a potential for disaster. Consider the following:

#include <iostream>

int main()
{
    std::cin.exceptions( std::istream::failbit );
    try {
        int i;
        std::cin >> i;
        std::cout << "I got an integer: " << i << std::endl;
    } catch (std::istream::failure & e) {
        std::cout << "Exception: " << e.what() << std::endl;
    }

    return 0;
}


So you can use exceptions to guarantee atype of input is received (this handles the empty input case). However, if you use readline or similar approach where all you get back is a string (or character buffer) you need to roll your own parser and do your own verification.

For instance, if you only want a string and someone provides a number how is the stream to know that is an error? Digits are valid string characters - except maybe in your particular case.

L7Sqr
Practically a Master Poster
656 posts since Feb 2011
Reputation Points: 201
Solved Threads: 123
 

Yes. I understand that user input is a potential for disaster. Consider the following:

#include <iostream>

int main()
{
    std::cin.exceptions( std::istream::failbit );
    try {
        int i;
        std::cin >> i;
        std::cout << "I got an integer: " << i << std::endl;
    } catch (std::istream::failure & e) {
        std::cout << "Exception: " << e.what() << std::endl;
    }

    return 0;
}

So you can use exceptions to guarantee atype of input is received (this handles the empty input case). However, if you use readline or similar approach where all you get back is a string (or character buffer) you need to roll your own parser and do your own verification.

For instance, if you only want a string and someone provides a number how is the stream to know that is an error? Digits are valid string characters - except maybe in your particular case.

Thats interesting. I never used cin.exception mechanism. I usually just use cin as a boolean arguments.
Just a question, why would one choose that over say this :

int x = 0;
while( !(cin >> x) ){ 
 /* handle error */
}
firstPerson
Senior Poster
3,923 posts since Dec 2008
Reputation Points: 841
Solved Threads: 608
 

I'm happy that L7Sqr pointed out that IO streams have exceptions as an alternative to those ugly while-loops and successive if-statements. It's certainly the preferred way to go in many cases, and many people, even experienced programmers, forget about this or never knew at all.

You can also use exceptions as a validation mechanism that integrates very nicely with stream exceptions. Here is an example where you would like to force the user to write their names (which, I assume, would not contain numbers or punctuations):

#include <exception>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

struct invalid_name : public exception {
  const char* what() const throw() { return "The name entered is invalid!"; };
};

struct full_name {
  string first_name;
  string last_name;
  full_name(const string& aFirstName = "John", const string& aLastName = "Doe") : first_name(aFirstName), last_name(aLastName) { };
};

istream& operator >>(istream& in, full_name& fn) {
  in >> fn.first_name >> fn.last_name;
  if((count_if(fn.first_name.begin(),fn.first_name.end(),::isalpha) != fn.first_name.length()) || 
     (count_if(fn.last_name.begin(), fn.last_name.end(), ::isalpha) != fn.last_name.length()))
    throw invalid_name();
};

int main() {
  int the_age = 0;
  full_name the_name;

  cin.exceptions( std::istream::failbit );
  while(true) {
    try {
      cout << "How old are you?" << endl;
      cin >> the_age; 
      cin.ignore();
      cout << "What is you full name?" << endl;
      cin >> the_name; 
      cin.ignore();
      break; //if it got to this point, it means all was valid.
    } catch (istream::failure & e) {
      cout << "Exception: " << e.what() << endl;
      cin.clear(); cin.ignore();
    } catch (invalid_name& e) {
      cout << e.what() << " Please re-enter the information..." << endl;
    };
  };

  return 0;
};


@firstPerson, One would choose to use exceptions instead of error-codes mostly for the reasons expressed here and here (which is what I agree with the most) .

mike_2000_17
Posting Virtuoso
Moderator
2,134 posts since Jul 2010
Reputation Points: 1,634
Solved Threads: 457
 

In addition to what mike_2000_17 points out, the exception route also gives you finer control over what triggers the exit condition. Any of the iostate flags can be used to control exceptions which enables you to only throw on failbit , for instance, instead of also on eofbit .

L7Sqr
Practically a Master Poster
656 posts since Feb 2011
Reputation Points: 201
Solved Threads: 123
 
In addition to what mike_2000_17 points out, the exception route also gives you finer control over what triggers the exit condition. Any of the iostate flags can be used to control exceptions which enables you to only throw on failbit , for instance, instead of also on eofbit .

But the thing is would you be limited to exactly those bits? So no custom failure would work.

firstPerson
Senior Poster
3,923 posts since Dec 2008
Reputation Points: 841
Solved Threads: 608
 

>>But the thing is would you be limited to exactly those bits? So no custom failure would work.

What custom failure?

There are three failure cases for the istream:
- eofbit: when the stream reaches end-of-file (I guess cin will never throw that one)
- failbit: basically a failure to perform the reading operation.
- badbit: some other problem (e.g. the source of the stream is in a bad state).

There are no "custom" failures, these are just the failures that the standard has decided on for the implementation of istream. The "exception()" function simply tells the istream which error cases should throw an exception and which should not (and thus, will be signaled by the internal state flag instead, i.e. an error-code mechanism).

Custom failures could mean two things: either you are implementing your own kind of istream and have other failures to report, or you have some special items that can be read off any istream which have failures of their own to report. In the former case, since you are implementing your own istream class (or derived class), you are free to throw any exception you like. In the latter case, you would just throw your custom exception in the read operator >>, see my last post.

mike_2000_17
Posting Virtuoso
Moderator
2,134 posts since Jul 2010
Reputation Points: 1,634
Solved Threads: 457
 

I like the look of this exceptions function, I did not know about it. I'll have to play with it more. Thanks for pointing it out.
There are three failure cases for the istream:
- eofbit: when the stream reaches end-of-file (I guess cin will never throw that one)
- failbit: basically a failure to perform the reading operation.
- badbit: some other problem (e.g. the source of the stream is in a bad state).
Actually, you can get eofbit from cin. I'm not sure if it's universal or not, but on Windows if you enter the key combination CTRL-Z at the prompt it will set it. Run this:

#include <iostream>
#include <exception>

int main() {
  int input = 0;
  std::cin.exceptions(std::istream::eofbit);
  try {
    std::cout << "Please enter CTRL-Z: ";
    std::cin >> input;
  } catch (std::istream::failure &e) {
    std::cout << "Exception: " << e.what() << std::endl;
    std::cin.clear();
    std::cin.ignore();
  }
  return 0;
}

When you enter the CTRL-Z combination, it will probably show up as "^Z". Then, when you press ENTER you'll get an exception saying "Exception: ios_base::eofbit set"

Fbody
Posting Maven
2,930 posts since Oct 2009
Reputation Points: 833
Solved Threads: 393
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: