これが私がやろうとしていることです:
私は文字列ストリームを持っていると言います。その後私は<< "\"hello world\" today";
それから私がするとき
sstr >> myString1 >> myString2;
myString1 には「hello world」を、myString2 には「today」を付けたいと思います。
おそらくマニピュレータを使用して、これを達成する方法はありますか?
ありがとう
これが私がやろうとしていることです:
私は文字列ストリームを持っていると言います。その後私は<< "\"hello world\" today";
それから私がするとき
sstr >> myString1 >> myString2;
myString1 には「hello world」を、myString2 には「today」を付けたいと思います。
おそらくマニピュレータを使用して、これを達成する方法はありますか?
ありがとう
短い答え: いいえ
長い答え:
あなたのためにそれを行う操作はありません。
別の答え:
このタスクを実行するストリーム演算子と組み合わせて使用できる独自の型を作成できます。
#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"
いいえ。
ストリーム タイプ (したがって解析セマンティクス) を変更するか、独自の文字列型を使用する (したがって、オーバーロードされた op>> の解析セマンティクスを変更する) 必要があります。
代わりに、ストリームから引用符で囲まれている可能性のある「単語」を解析する、getline に似た関数を作成することを検討してください。
getqword(sstr, myString1);
getqword(sstr, myString2);
if (sstr) { /* both succeeded */ }
std::string への入力はすでに空白で終了しているため、クォートの先読みを処理してから、エッジ ケースを処理するだけで十分であることに注意してください。
"\"hello world\"today"
直接ではなく、必要な場所で終了する「ラッパー」クラスが必要です。
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」と呼ぶことができます。
いいえ。その特定の方法ではありません。ただし、文字列の「強力な typedef」を作成し、そのように動作する新しい operator>> を設計できます。
それは不可能です。operator>>
これは、実行時にforbasic_istream
が実際に呼び出される実装を調べると、ループsstr >> myString1
内に次のように表示されるためです。for
else if (_Ctype_fac.is(_Ctype::space,_Traits::to_char_type(_Meta)))
break;// whitespace, quit
つまり、「スペース」を取得したら終了します。myString1
そのため、スペースができたら、文字を追加し続けることはできません。
これは MSVC++ 実装であることに注意してください。ただし、すべての実装で同等のものを見つけることができると確信しています!
入力ストリーム演算子をオーバーロードして、そこに解析セマンティクスを含めることができます。
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;
}