2

C++ プログラムで、演算子 (+ - / *) が散在する整数オペランドで構成されるユーザー入力を処理しようとしています。各演算子の前後に空白を入れることをユーザーに要求する余裕があります。私のアプローチは、int でないものはすべて演算子であると想定することです。したがって、ストリームで eof 以外のエラーが発生するとすぐに、cin.clear() を呼び出して、次の値を文字列に読み込みます。

#include <iostream>
#include <string>

//in some other .cpp i have these functions defined
void process_operand(int);
void process_operator(string);

using namespace std;

int main()
{
    int oprnd;
    string oprtr;
    for (;; )
    {
        while ( cin >> oprnd)
            process_operand(oprnd);
        if (cin.eof())
            break; 
        cin.clear();
        cin >> oprtr;
        process_operator(oprtr);
    }
}

これは / および * 演算子では問題なく機能しますが、+ - 演算子では機能しません。その理由は operator>>、エラーを報告する前に + または - を食い尽くし、それをストリームに戻さないためです。そのため、無効なトークンが oprtr に読み込まれます。

Ex: 5 1 * 2 4 6 * /   works fine
    5 1 + 2 
          ^ ---> 2 becomes the oprnd here.

この問題に対処する C++ の良い方法は何でしょうか?

4

2 に答える 2

5

s を読み込み、または同等std::stringのものを使用して変換します。boost::lexical_cast<>

int main()
{
    string token;
    while ( cin >> token) {
        try {
            process_operand(boost::lexical_cast<int>(token));
        } catch (std::bad_cast& e) {
            process_operator(token);
        }
    }
}

追記: 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;
}
于 2012-05-14T15:52:37.270 に答える
3

>> は、+/- で別の整数を開始していると思います。数字を追わないと怒る。

@Robᵩが言ったように、文字列を読んでキャストします。標準ライブラリからの別の選択肢のみを提供します。

int stoi(const string& str, size_t *idx = 0, int base = 10);

invalid_argumentこれは、変換を実行できなかっout_of_rangeた場合、または変換された値が戻り値の型で表現可能な値の範囲外である場合にスローされます。

これはスタンダードからです。

于 2012-05-14T16:48:16.500 に答える