1

私はクラス テンプレートを持っています。これは、特に istream をオーバーロードすることになっているため、ユーザーの入力を受け入れ、それを T 型の要素を保持するベクトルに追加 (プッシュ) します。

    friend istream &operator>> (istream &in, Set<T> &s)
    {
        int ctr = 0;
        string tmp;
        T val;
        while (true) {
            cout << "\tElement #" << ctr + 1 << ": ";
            getline (in, tmp);
            if (tmp == "\0") break;
            // MISSING CODE HERE: "Convert" tmp into val
            s.add(val);
            ctr = s.size();
        }
        return in;
    }

これは で問題なく動作Set<string>しますが、任意のプリミティブ データ型でも機能させる方法を見つける必要がありますSet<integer>

やってみた

stringstream(tmp) >> val

しかし、それでは機能しませんSet<string>

入力は文字列として読み込む必要があると思います。では、入力文字列を T 型にキャストして .add() 関数に渡すにはどうすればよいでしょうか?

4

3 に答える 3

1

stringstreamオブジェクト (から作成) を使用しtmpて、文字列でない場合は正しい値を抽出できます。組み込み型以外のものが必要な場合はoperator>>、 forを上書きする必要があることに注意してください (例: )ostreamint

または、文字列から必要な型への適切な変換を提供するために、遭遇するconvert()たびに関数のオーバーロードを定義できます。テンプレート パラメータに基づいて、適切なオーバーロード (存在する場合) が選択されます。Ttmp

于 2012-05-17T17:31:06.503 に答える
1

boost::lexical_cast文字列を辞書式に他の型に変換するために使用できます。

template<class T>
friend istream &operator>> (istream &in, Set<T> &s) {
    int ctr = 0;
    string tmp;
    T val;
    while (true) {
        cout << "\tElement #" << ctr + 1 << ": ";
        getline (in, tmp);
        if (tmp == "\0") break;
        val = boost::lexical_cast<T>(tmp);
        s.add(val);
        ctr = s.size();
    }
    return in;
}

または、 を使用することもできますstd::istringstream

std::istringstream sstream(tmp);
sstream >> val;

boost::lexical_castキャストが成功しなかった場合は例外をスローし、失敗した場合は例外をスローするstd::istringstream ことに注意してください (手動で確認する必要があります)。

于 2012-05-17T17:34:05.377 に答える
0

コードには、対処したい問題がいくつかあります。

getline (in, tmp);

戻り値を確認する必要があります。

if(!getline (in, tmp))
    // handle end-of-file or read failure
// read okay, tmp contains the read line

次:

if (tmp == "\0") break;

テキスト ファイルにゼロが埋め込まれていることはあまり一般的ではありません。この部分は、getlineまたはif(in)ステートメントの戻り値をチェックして処理する必要があるファイルの終わりの状態を検出しようとしている可能性があります。

stringstream(tmp) >> val;

これは、一時的な文字列ストリームを作成し、それを呼び出そうとしoperator>>ます。operator>>forには次の 2 種類がありますstd::istream

  • std::istreamstd::istream一時 (右辺値) オブジェクトと左辺値オブジェクトを受け入れるメンバー関数
  • std::istream右辺値を受け入れない非 const を参照する独立したもの。(C++11 ではstd::istream&&、r 値を許可するものとしても受け入れることができます)。

operator>>したがって、上記のステートメントは、 にメンバーがある組み込み型にのみストリーミングできますstd::istream

したがって、そのステートメントは次のように置き換えることができます。

std::istringstream ss(tmp);
ss >> val;

全体strが に解析されたかどうかを確認するために、エラー処理を再度行う必要がvalあるため、他の人がここで言っているように、エラーチェックを行う方が使いやすいboost::lexical_cast<>です:

val = boost::lexical_cast<T>(tmp);

空白で区切られたトークンを読むのではなく、行全体を読むことを主張しない場合、ループは次のようになります。

template<class T>
friend std::istream &operator>>(std::istream &in, Set<T> &s) {
    int ctr;
    T val;
    while(in >> val) {
        ctr = s.size();
        std::cout << "\tElement #" << ctr + 1 << ": ";
        s.add(val);
    }
    // end-of-file or parsing failure
    if(!in.eof()) {
        // handle failuer to parse or read error
    }
}
于 2012-05-17T17:41:52.610 に答える