stringstream operator>>関数として失敗しますが、インスタンスとして動作しますか?
-
10-07-2019 - |
質問
ファイルから名前と整数のペアを抽出する簡単なコードを書いています。使用する既存のコードを変更しています:
string chrom;
unsigned int size;
while ( cin >> chrom >> size ) {
// save values
}
しかし、最初の2列が同じで、その後に他のデータが続く(無視される)別の(類似の)入力ファイルを使用します。 だから私は書く:
string chrom;
unsigned int size;
string line;
while ( getline(cin, line) ) {
if( stringstream(line) >> chrom >> size ) {
// save values
}
}
しかし、これはコンパイルに失敗し、典型的なわいせつなstd libテンプレートspewを与えます:
error: no match for "operator>>" in "std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >(((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >*)(& line))), std::operator|(_S_out, _S_in)) >> chrom"
istream:131: note: candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>& (*)(std::basic_istream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
[...another dozen lines...]
そうです。 lineはstd :: stringではありませんが、std :: basic_stringなどのバリエーションです。 ただし、文字列ストリームを明示的にインスタンス化することはできます。
string chrom;
unsigned int size;
string line;
while ( getline(genome, line) ) {
stringstream ss(line);
if ( ss >> chrom >> size ) {
// save values
}
// Discard remainder of line
}
なぜですか?最初のケースの何が問題になっていますか?常に役立つcplusplus.comの basic_ioの例が機能するのはなぜですか。コード?
更新: 別の参照ポイント:一時的な文字列ストリームは、抽出された最初の値が文字列ではなくintである場合に機能します:
unsigned int chrom; // works as int...
unsigned int size;
string line;
while ( getline(cin, line) ) {
if( stringstream(line) >> chrom >> size ) {
// save values
}
}
解決
メンバー関数の3つのグループとグローバル関数の1つのグループは、この「抽出演算子」をオーバーロードします。 (&gt;&gt;)、 http://www.cplusplusを参照してください。 com / reference / istream / istream / operator%3E%3E / 。
- stringstream(line); -一時オブジェクトを作成しました
- stringstream ss(line);-通常のオブジェクト。
&quot; chrom&quot;の場合は整数、演算子&gt;&gt;メンバー関数である算術抽出としてオーバーロードされます。通常のオブジェクトまたは一時オブジェクトの両方が正常に機能します。
&quot; chrom&quot;の場合文字列、演算子&gt;&gt; istream&amp;としてオーバーロードする必要があります演算子&gt;&gt; (istream&amp; is、char * str)
、これはパラメーターとしてオブジェクト参照を取る必要があるグローバル関数です。ただし、一時オブジェクトを指定すると、標準C ++の非const参照によって一時オブジェクトを渡すことはできません。オーバーロード関数は、 istream&amp;として定義されていない限り、一時オブジェクトの参照を取得できません。演算子&gt;&gt; (const istream&amp; is、char * str)
。残念ながら、それは事実ではありません。一時オブジェクトの場合、関数はオーバーロードできないため、 error:no match for function ...
他のヒント
John Weldonの答えを拡張するために、エクストラ演算子&quot;&gt;&gt;&quot; 2つのことを行います:
- 次の値を抽出して、演算子の右側の変数に配置します。
- ストリームの左側の現在位置をインクリメントします。
したがって、左と右の両方のオペランドを変更します。あなたの場合、左側のオペランドは一時的な値であり、コンパイラーはそれを変更することに眉をひそめます。
CおよびC ++の一部の演算子では、演算子の左側の値が左辺値である必要があります。つまり、変更可能です。
こちらはより完全な説明です。
stringstreamから抽出される最初の値はstd :: stringであるため。たとえば、intの場合、stringstream(line)バージョンは機能します。
メンバー関数演算子はありません&gt;&gt; std :: stringのstringstream。したがって、一時ストリームは左辺値として機能できません。
上記を完全に理解しているわけではありません...しかし、おそらくより良い答えの出発点です。