5

これが私がやろうとしていることです:

私は文字列ストリームを持っていると言います。その後私は<< "\"hello world\" today";

それから私がするとき

sstr >> myString1 >> myString2;

myString1 には「hello world」を、myString2 には「today」を付けたいと思います。

おそらくマニピュレータを使用して、これを達成する方法はありますか?

ありがとう

4

7 に答える 7

5

短い答え: いいえ

長い答え:
あなたのためにそれを行う操作はありません。

別の答え:

このタスクを実行するストリーム演算子と組み合わせて使用​​できる独自の型を作成できます。

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>


class QuotedWord
{
    public:
        operator std::string const& () const { return data;}

    private:
        std::string     data;
      friend std::ostream& operator<<(std::ostream& str, QuotedWord const& value);
      {
        return str << value.data;
      }
      friend std::istream& operator>>(std::istream& str, QuotedWord& value);
      {
        char x;
        str >> x;
        if ((str) && (x == '"'))
        {
            std::string extra;
            std::getline(str, extra, '"');
            value.data = std::string("\"").append(extra).append("\"");
        }
        else
        {
            str.putback(x);
            str >> value.data;
        }
        return str;
      }
};

その後、通常どおり使用できます。

int main()
{
    QuotedWord  word;

    std::cin >> word;
    std::cout << word << "\n";

    // Easily convertible to string
    std::string tmp = word;
    std::cout << tmp << "\n"

    // because it converts to a string easily it can be used where string is needed.
    std::vector<std::string>   data;

    std::copy(std::istream_iterator<QuotedWord>(std::cin),
              std::istream_iterator<QuotedWord>(),

              // Notice we are using a vector of string here.
              std::back_inserter(data)
             );
}

> ./a.out
"This is" a test    // Input
"This is"           // Output
"This is"
于 2011-01-15T19:27:28.690 に答える
4

いいえ。

ストリーム タイプ (したがって解析セマンティクス) を変更するか、独自の文字列型を使用する (したがって、オーバーロードされた op>> の解析セマンティクスを変更する) 必要があります。

代わりに、ストリームから引用符で囲まれている可能性のある「単語」を解析する、getline に似た関数を作成することを検討してください。

getqword(sstr, myString1);
getqword(sstr, myString2);
if (sstr) { /* both succeeded */ }

std::string への入力はすでに空白で終了しているため、クォートの先読みを処理してから、エッジ ケースを処理するだけで十分であることに注意してください。

  • エスケープ (引用符内の引用符)
    • 3 つの一般的なスタイルは、許可されていない、バックスラッシュ、および二重引用符です。それぞれに長所と短所があります
  • 複数行にまたがる (\n を含めることはできますか?)
    • これは多くの場合データ エラーであるため、状況によっては許可しないことが大きな助けになることがあります。
  • 引用された単語が別の単語の隣で終わるとどうなりますか?
    • "\"hello world\"today"
  • 先頭の空白をスキップしますか?
    • getline とは異なり、ストリームの skipws フラグを尊重することは理にかなっていますが、まれな状況でそれが逆になることがわかりました
    • istream セントリーがこれを処理します
  • ストリームの特性とロケールを使用するか、既にそれを行っているメソッドを使用することを忘れないでください!
    • またはあなたの仮定を文書化する
于 2011-01-15T19:14:59.240 に答える
2

直接ではなく、必要な場所で終了する「ラッパー」クラスが必要です。

struct QuotedStringReader
{
   std::string& str;
   QuotedStringReader( std::string& s ) : str( s ) {}
};

std::istream operator>>( std::istream&, const QuotedStringReader& qsr );

std::string s, s2;
stream >> QuotedStringReader( s ) << s2;

これは、const にストリーミングするまれなケースであることに注意してください。これは、const であっても内部 str に書き込むことができるため、一時的に渡すことができるためです。

実際には、何を読み取ろうとしているのかわからない可能性があるため、「トークン」として定義したものを読み取る「TokenReader」と呼ぶことができます。

于 2011-01-15T19:26:26.040 に答える
1

いいえ。その特定の方法ではありません。ただし、文字列の「強力な typedef」を作成し、そのように動作する新しい operator>> を設計できます。

于 2011-01-15T19:16:24.720 に答える
0

それは不可能です。operator>>これは、実行時にforbasic_istreamが実際に呼び出される実装を調べると、ループsstr >> myString1内に次のように表示されるためです。for

else if (_Ctype_fac.is(_Ctype::space,_Traits::to_char_type(_Meta)))
   break;// whitespace, quit

つまり、「スペース」を取得したら終了します。myString1そのため、スペースができたら、文字を追加し続けることはできません。

これは MSVC++ 実装であることに注意してください。ただし、すべての実装で同等のものを見つけることができると確信しています!

于 2011-01-15T19:26:16.057 に答える
0

入力ストリーム演算子をオーバーロードして、そこに解析セマンティクスを含めることができます。

std::istream& operator>>(std::istream& is, std::string& out)
{
    char c;
    is >> c;
    if (c == '\"')
    {
        std::getline(is, out, '\"');
        return is;
    }
    else
    {
        is.putback(c);
        return std::operator >>(is, out);
    }
}

int main()
{
    std::istringstream iss("\"hello world\" today");
    std::string test;
    while (iss >> test)
        std::cout << test << std::endl;
}
于 2011-01-15T19:28:11.920 に答える