tags:

views:

136

answers:

3

Hi

I would like to make the user input a center number of character, e.g. 10, however, the user might input more than 10.

for(int i = 0 ; i< 10 ; i++)
cin>>x;

The extra character could make my code crash since I will ask for input later.

How can I clear the input at this moment when the user input more than 10?

Thanks so much!

+4  A: 
  std::cin.clear();
  std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');

This should reset the failbit and ignore the bad input.

Xorlev
streamsize is the input? How about the size is dynamic depending on other variables?
skydoor
`streamsize` is a type. `cin.ignore()` takes two arguments: the maximum number of characters to ignore (type is `streamsize`), and the delimiter after which to stop ignoring (type is `char`). `std::numeric_limits<streamsize>::max()` means "the largest number that can fit into a variable of type `streamsize`. So the whole line means "ignore as many characters as necessary until you ignore a newline, then stop.
Tyler McHenry
… assuming bad input is the culprit…
Potatoswatter
A: 

cin goes into an error mode and stops doing anything if the user gives invalid input. You need to add a check for invalid input and a loop to retry.

for(int i = 0 ; i< 10 ; i++)
    while ( ( cin >> x ).rdstate() == ios::failbit ) {
        cin.clear();
        cin.ignore( numeric_traits<streamsize>::max(), '\n' );
    }

It's a lot of work, but you need to define some kind of policy for ignoring invalid input. There are other choices; this just ignores the remainder of the line.

Potatoswatter
+1  A: 

By the way, to avoid duplicating all that code every time, I once wrote a little template function to do that work:

template<typename InType> void AcquireInput(std::ostream & Os, std::istream & Is, const std::string & Prompt, const std::string & FailString, InType & Result)
{
    do
    {
        Os<<Prompt.c_str();
        if(Is.fail())
        {
            Is.clear();
            Is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        }
        Is>>Result;
        if(Is.fail())
            Os<<FailString.c_str();
    } while(Is.fail());
}

template<typename InType> InType AcquireInput(std::ostream & Os, std::istream & Is, const std::string & Prompt, const std::string & FailString)
{
    InType temp;
    AcquireInput(Os,Is,Prompt,FailString,temp);
    return temp;
}

The first overload may be preferred if you want to avoid copying, the second may be more convenient for builtin types. Usage examples:

//1st overload
int AnInteger;
AcquireInput(cout,cin,"Please insert an integer: ","Invalid value.\n",AnInteger);

//2nd overload (more convenient, in this case)
int AnInteger=AcquireInput(cout,cin, "Please insert an integer: ","Invalid value.\n");
Matteo Italia