开发者

C++ cin.fail() question

When running the following code and enter a number, it works fine. But when entering a letter, the program enters an infinite loop, displayi开发者_Go百科ng "Enter a number (0 to exit): cin failed."

My intent was to handle the cin fail case and prompt the user again.

int number;
do{
    cout << "Enter a number (0 to exit): ";
    cin >> number;
    if(cin.fail()){
        cout << "cin failed." << endl;
        cin.clear();
    }else{
        cout << "cin succeeded, " << number << " entered." << endl;
    }
}while(number != 0);


You need to clear the line from cin, using cin.ignore, in addition to clearing the stream state (which is what cin.clear does).

I have several utility functions to make this easier (you'll be interested in clearline in particular, which clears the stream state and the current line) and almost an exact example of what you want.

Your code, more or less, using my clearline:

#include "clinput.hpp" // move my file to a location it can be used from

int main() {
  using namespace std;
  while (true) {
    cout << "Enter a number (0 to exit): ";
    int number;
    if (cin >> number) {
      cout << "Read " << number << '\n';
      if (number == 0) {
        break;
      }
    }
    else {
      if (cin.eof()) { // tested only *after* failed state
        cerr << "Input failed due to EOF, exiting.\n";
        return 1;
      }
      cerr << "Input failed, try again.\n";
      clearline(cin); // "cin >> clearline" is identical
    }
  }
  return 0;
}

There is still a potential issue here (fixed in my clinput_loop.cpp with blankline), with leaving input in the buffer that will screw up later IO (see "42 abc" in the sample session). Extracting the above code into a separate and self-contained function is left as an exercise for the reader, but here's a skeleton:

template<class Type, class Ch, class ChTr>
Type read(std::basic_istream<Ch,ChTr>& stream, Ch const* prompt) {
  Type value;
  // *try input here*
  if (could_not_get_input or more_of_line_left) {
    throw std::runtime_error("...");
  }
  return value;
}
template<class Type, class Ch, class ChTr>
void read_into(
  Type& value,
  std::basic_istream<Ch,ChTr>& stream,
  Ch const* prompt
) {
  value = read<Type>(stream, prompt);
}

Example use:

int n;
try {
  read_into(n, std::cin, "Enter a number: ");
}
catch (std::runtime_error& e) {
  //...
  raise;
}
cout << "Read " << n << '\n';

clearline function extracted for posterity, in case above links ever break (and slightly changed to make self-contained):

#include <istream>
#include <limits>

template<class C, class T>
std::basic_istream<C,T>& clearline(std::basic_istream<C,T>& s) {
  s.clear();
  s.ignore(std::numeric_limits<std::streamsize>::max(), s.widen('\n'))
  return s;
}

The template stuff is a bit confusing if you're not used to it, but it's not hard:

  • std::istream is a typedef of std::basic_istream<char, std::char_traits<char> >
  • std::wistream is a typedef of std::basic_istream<wchar_t, std::char_traits<wchar_t> >
  • widen allows '\n' to become L'\n' as appropriate
  • this code works for both of the common char and wchar_t cases, but also any compatible instantiation of basic_istream
  • it's written to be called as clearline(stream) or stream >> clearline, compare to other manipulators like std::endl, std::ws, or std::boolalpha


This is probably what you intended to do:

#include <iostream>
using namespace std;

int main ()
{
  int i;
  do {
    if (cin.fail())
    {
      cin.ignore(255);
      cin.clear();
    }          
    cout << "Please enter an integer value: ";
    cin >> i;
  } while ( cin.fail() );
  cout << "The value you entered is " << i;
  return 0;
}


This is simple example of cin.fail() It will process input until a valid integer value is provided

#include <iostream>
using namespace std;

int main()
{
int j;
int i;

i = 0;
while (1) {
    i++;
    cin >> j;
    if (cin.fail()) return 0;
    cout << "Integer " << i << ": " << j << endl;
}
}

Input:

42 51 85 hello 85

Output:

Integer 1: 42

Integer 2: 51

Integer 3: 85

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜