整数を受け取るプログラムがあるとします。ユーザーが範囲外の数字や文字などを入力した場合にプログラムが崩壊するのを防ぐにはどうすればよいですか?
5 に答える
のcin
基本クラスはstd::basic_istream
です。入力ストリームは、要求されたデータをストリームから抽出できない場合に回復可能なエラーを示します。そのエラー ビットをチェックするには、std::basic_istream::fail()
メソッドを使用する必要があります。エラーが発生true
した場合、またはfalse
すべてが正常である場合に返されます。エラーが発生した場合、データはストリームに残り、もちろんエラー ビットも を使用してクリアする必要があることを覚えておくことが重要ですstd::basic_istream::clear()
。また、プログラマーは間違ったデータを無視する必要があります。そのためには、std::basic_istream::ignore()
メソッドを使用できます。有効な値の範囲については、手動で確認する必要があります。さて、理論は十分です。簡単な例を次に示します。
#include <limits>
#include <iostream>
int main()
{
int n = 0;
for (;;) {
std::cout << "Please enter a number from 1 to 10: " << std::flush;
std::cin >> n;
if (std::cin.fail()) {
std::cerr << "Sorry, I cannot read that. Please try again." << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
if (n < 1 || n > 10) {
std::cerr << "Sorry, the number is out of range." << std::endl;
continue;
}
std::cout << "You have entered " << n << ". Thank you!" << std::endl;
break;
}
}
それが役に立てば幸い。幸運を!
入力を文字列として読み取り、次のようにサニタイズすることを好みますboost::lexical_cast<>
。
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
int main () {
std::string s;
while( std::cin >> s) {
try {
int i = boost::lexical_cast<int>(s);
std::cout << "You entered: " << i << "\n";
} catch(const std::bad_cast&) {
std::cout << "Ignoring non-number: " << s << "\n";
}
}
}
追記: Boost にアレルギーがある場合は、この lexical_cast の実装を使用できます。
template <class T, class U>
T lexical_cast(const U& u) {
T t;
std::stringstream s;
s << u;
s >> t;
if( !s )
throw std::bad_cast();
if( s.get() != std::stringstream::traits_type::eof() )
throw std::bad_cast();
return t;
}
私が正しいことを覚えているかどうかを確認した後、バッファをクリアする必要があります
if (cin.fail())
{
cout<<"need to put a number"<<endl;
cin.clear();
cin.ignore();
}
次のコードを使用して、 int の有効な入力を最も簡単かつ迅速にチェックできます。
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int intb;
while( !( cin>>intb ) ){
cin.clear ();
cin.ignore (1000, '\n');
cout<<"Invalid input enter again: "<<endl;
}
cout<<"The value of integer entered is "<<b<<endl;
return 0;
}
while ループは、正しい入力が得られるまで反復を続けます。cin.clear() はエラー制御状態を変更します。cin.ignore() は、入力ストリームのクリアを削除して、新しい入力を再び取得できるようにします。これを行わないと、while ループは無限状態になります。
コードにライブラリを追加したくない場合は、do..while() ステートメントを使用することもできます。do while でユーザー入力を要求し、それを変数に受け取ります。while 部分で、データを要求し続けない場合に、これが期待するデータであることを確認できます。
ちょうど別のオプション....すでに述べた答えは十分に機能するはずですが