2017-11-07 6 views
-1

私は、エラーチェック機能を含む整数と潜在的に倍数の代わりにcinを置き換えることができる関数を書いています。 cin.fail()を使用するほとんどのケースを確認することができましたが、入力にスペースがない文字列が続く場合は対象となりませんでした。たとえば、「23tewnty-three」と入力します。次のコードでこれに対応しています。空のsstreamを確認してください

int getUserInt(string prompt = "Enter an integer: ", string errorMessage "Error: Invalid Input") { 
    const int IGNORE_MAX = 100; 
    int userInt = 0; 

    bool isContinue = true; 
    do { 
     // initialize and reset variables 
     string inputStr; 
     istringstream inputCheck; 
     userInt = 0; 

     // get input 
     cout << prompt; 
     cin >> inputStr; 
     inputCheck.str(inputStr); 

     // check for valid input 
     inputCheck >> userInt; 
     if (!inputCheck.fail()) { 
      // check for remaining characters 
      if (inputCheck.eof()) { // Edit: This is the section that I tried replacing with different code (made code compilable in response to comment) 
       isContinue = false; 
      } 
      else { 
       cout << errorMessage << endl; 
      } 
     } 
     else { 
      // reset cin and print error message 
      cin.ignore(IGNORE_MAX, '\n'); 
      cin.clear(); 
      cout << errorMessage << endl; 
     } 
    } while (isContinue); 

    return userInt; 
} 

このコードは動作しますが、私の主な質問は、私が期待通りのコードの一部が機能しなかった理由についてですので、私は代わりにコードレビューのオーバーフローをスタックにこれを掲示していた理由があります。以下は、前のコードでinputCheck.eof()の代わりに試したものです。私の質問は、次のコードの違いは何ですか?なぜ方法2)と3)は機能しませんでしたか?どの方法が好ましいか?

  1. inputCheck.eof()
  2. inputCheck.peek() == EOF
  3. inputCheck.str().empty()
  4. inputCheck.rdbuf()->in_avail() == 0

1)及び4)予想されるように働いたが、2)及び3)しませんでした。

編集: 私は予想通りinputCheck.str()inputCheck.str(inputStr)が呼び出されたときinputStrに含まれていたものを返すため、3)動作しませんでしたと信じています。しかし、なぜinputCheck.peek() == EOFがうまくいかなかったのか分かりません。

これは関連情報であれば、私はコンパイルしてbash g ++でウィンドウズ上で実行しています。

+0

[iostateフラグ](http://en.cppreference.com/w/cpp/io/ios_base/iostate)とその意味について少しお読みください。 –

+1

コンパイル可能なサンプルコードを置いて、不要なノイズをすべて除去すると、それはより良い方法です。例えば。 'inputCheck.str()'の内容をチェックすると、3.がうまくいかない理由を確認するのが簡単です。私は 'EOF'とは思っていません。 – luk32

+0

@ luk32私は編集を終えるまでこのコメントを見ませんでした。 –

答えて

0

プロンプトが表示されるたびに、ユーザーはEnterキーを押します。入力を文字列として取得し、変換を試みます。 (cinから変換しようとしないでください)

ボーナス:ここでは変換を実行する機能があります。

template <typename T> 
std::optional <T> string_to(const std::string& s) 
{ 
    std::istringstream ss(s); 
    T result; 
    ss >> result >> std::ws; 
    if (ss.eof()) return result; 
    return {}; 
} 

代わりにC++ 20、または代わりに#include <boost/optional.hpp>が必要です。今

std::cout << "Enter an integer! "; 
std::string s; 
getline(std::cin, s); 
auto x = string_to <int> (s); 
if (!x) 
{ 
    std::cout << "That was _not_ an integer.\n"; 
} 
else 
{ 
    std::cout << "Good job. You entered the integer " << *x << ".\n"; 
} 

はこれ以上心配クリアしたりcinのリセットについて。手軽にいくつかのループを実行します(終了する前にユーザーに3回の試行を許可するなど)。その他。

関連する問題