3

次のコードを実行して数値を入力すると、正常に動作します。しかし、文字を入力すると、プログラムは無限ループに入り、「数字を入力してください (終了するには 0): cin に失敗しました」と表示されます。

私の意図は、cin fail ケースを処理し、ユーザーに再度プロンプトを表示することでした。

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);
4

3 に答える 3

5

ストリーム状態をクリアすることに加えて、cin.ignoreを使用してcinから行をクリアする必要があります (これはcin.clearが行うことです)。

これを簡単にするためのユーティリティ関数がいくつかあります (特に、ストリームの状態と現在の行をクリアするclearlineに興味があるでしょう) と、必要なもののほぼ正確な例があります

あなたのコードは、多かれ少なかれ、私の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;
}

ここにはまだ潜在的な問題があり (私のclinput_loop.cppblanklineで修正されています)、後で IO を台無しにするバッファーに入力を残すという問題があります (サンプル セッションの「42 abc」を参照)。上記のコードを独立した自己完結型の関数に抽出することは、読者の課題として残されていますが、ここにスケルトンがあります。

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);
}

使用例:

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

上記のリンクが壊れた場合に備えて、後世のために抽出されたclearline関数 (自己完結型にするためにわずかに変更されています):

#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;
}

テンプレートに慣れていないと少し混乱しますが、難しいことではありません。

  • std::istreamは typedef ですstd::basic_istream<char, std::char_traits<char> >
  • std::wistreamは typedef ですstd::basic_istream<wchar_t, std::char_traits<wchar_t> >
  • widenは適切'\n'になることを可能にしますL'\n'
  • このコードは、一般的なcharwchar_tの両方のケースで機能しますが、 basic_istreamの互換性のあるインスタンス化でも機能します
  • std::endlstd::ws、またはstd::boolalphaなどの他のマニピュレーターと比較して、 clearline(stream) or として呼び出されるように記述されています。stream >> clearline
于 2010-01-09T07:42:09.023 に答える
1

これはおそらくあなたが意図したことです:

#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;
}
于 2010-01-09T07:44:05.977 に答える
0

これは cin.fail() の簡単な例です 有効な整数値が提供されるまで入力を処理します

#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;
}
}

入力:

42 51 85 こんにちは 85

出力:

整数 1: 42

整数 2: 51

整数 3: 85

于 2015-10-07T16:03:23.263 に答える