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

Recommended Answers

All 13 Replies

what constitutes as valid input?

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

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

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.

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

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.

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 a type 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.

commented: Exceptions rule!! +2

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 a type 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 */
}

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).

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 .

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.

>>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.

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"

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.