C ++ cin.fail()问题 [英] C++ cin.fail() question

查看:174
本文介绍了C ++ cin.fail()问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

运行以下代码并输入数字时,它可以正常工作。
但是当输入一个字母时,程序进入一个无限循环,显示输入一个数字(0退出):cin失败。



以处理cin失败的情况并再次提示用户。

  int number; 
do {
cout<< 输入一个数字(0退出):;
cin>>数;
if(cin.fail()){
cout<< cin失败了。 << endl;
cin.clear();
} else {
cout<< cin succeeded,<数字<< 输入。 << endl;
}
} while(number!= 0);


解决方案

您需要清除 cin ,除了清除流状态(这是 cin.clear 的作用)之外,还使用 b $ b

我有几个实用程序功能这更容易(您将特别感兴趣 clearline ,清除流状态和当前行),并且几乎是您想要的内容



您的代码,或多或少,使用我的 clearline

  #includeclinput.hpp//将我的文件移动到位置它可以使用

int main(){
using namespace std;
while(true){
cout<< 输入一个数字(0退出):;
int number;
if(cin>> number){
cout<< 读取<<数字<< '\\\
';
if(number == 0){
break;
}
}
else {
if(cin.eof()){//仅在*失败状态后测试
cerr< 输入失败,由于EOF,退出。\\\
;
return 1;
}
cerr<< 输入失败,请重试。
clearline(cin); //cin>> clearline是相同的
}
}
return 0;
}

这里还有一个潜在的问题(修正在我的 clinput_loop.cpp blankline ),并离开在缓冲区中输入将拧紧以后的IO(参见示例会话中的42 abc)。将上面的代码提取到一个单独的自包含的函数中作为一个练习留给读者,但这里有一个骨架:

  template< class Type,class Ch,class ChTr> 
类型读(std :: basic_istream< Ch,ChTr>& stream,Ch const *提示符){
类型值;
// * try input here *
if(could_not_get_input或more_of_line_left){
throw std :: runtime_error(...);
}
返回值;
}
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);
}

使用示例:

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






对于后代,如果上述链接已经中断(并且稍微改变为自包含):

  #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('\\\
'))
return s;
}

模板东西有点混乱,如果你不习惯它,但不难:

$ d
$ b

  • std :: istream std的typedef: :basic_istream< char,std :: char_traits< char> >

  • std :: wistream std :: basic_istream< wchar_t,std: :char_traits< wchar_t> > 允许'\\\
    '
    成为
    L'\\\
    '
    (如适用)

  • 此代码适用于常见的 char > wchar_t 案例,还包括任何兼容的实例化 basic_istream

  • 它被写为 clearline / code> stream>>与 std :: endl std :: ws std :: boolalpha 等其他操纵器进行比较时,clearline


When running the following code and enter a number, it works fine. But when entering a letter, the program enters an infinite loop, displaying "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

这篇关于C ++ cin.fail()问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆