代码之家  ›  专栏  ›  技术社区  ›  jmanning2k

stringstream operator>>作为函数失败,但作为实例工作?

  •  3
  • jmanning2k  · 技术社区  · 15 年前

    我正在编写一个简单的代码,它将从一个文件中提取一组name,int对。我正在修改只使用以下代码的现有代码:

    string chrom;
    unsigned int size;
    while ( cin >> chrom >> size ) {
        //  save values
    }
    

    但我想使用另一个(类似的)输入文件,该文件的前两列相同,但后面跟着其他数据(将被忽略)。 所以我写道:

    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...]
    

    正确的。行不是std::string,而是std::basic_string等的一些变体。 但是,显式实例化Stringstream是有效的。

    string chrom;
    unsigned int size;
    string line;
    while ( getline(genome, line) ) {
        stringstream ss(line);
        if ( ss >> chrom >> size ) {
           // save values
        }
        // Discard remainder of line
    }
    

    为什么?第一个病例怎么了?这个 example basic_io 在总是有用的cplusplus.com上,为什么我的代码不能工作?

    更新: 另一个参考点:当提取的第一个值是int而不是字符串时,临时字符串流工作:

    unsigned int chrom;  // works as int...
    unsigned int size;
    string line;
    while ( getline(cin, line) ) {
        if( stringstream(line) >> chrom >> size ) {
            // save values
        }
    }
    
    4 回复  |  直到 12 年前
        1
  •  2
  •   Shasha.Zhu    12 年前

    三组成员函数和一组全局函数将重载此“提取运算符”(>>),请参见 http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/ .

    • stringstream(line);--创建了一个临时对象
    • stringstream ss(line);--普通对象。

    当“chrom”为int时,运算符>>作为成员函数的算术提取器重载。正常对象和临时对象都可以正常工作。

    当“chrom”是字符串时,运算符>>应重载为 istream& operator>> (istream& is, char* str) ,这是一个全局函数,应将对象引用作为参数。但是,给定临时对象,我们不允许在标准C++中通过非const引用传递临时对象。除非将重载函数定义为 istream& operator>> (const istream& is, char* str) . 不幸的是,事实并非如此。在临时对象情况下,不能重载函数,因此会发出如下错误: error: no match for function...

        2
  •  2
  •   Anton    15 年前

    为了进一步阐述约翰·韦尔登的答案,业余经营者“>>”做了两件事:

    1. 提取下一个值并将其放入运算符右侧的变量中。
    2. 增加流在左侧的当前位置。

    因此,它同时修改其左操作数和右操作数。在您的例子中,左侧操作数是一个临时值,编译器不愿意修改它。

        3
  •  2
  •   Thomas    15 年前

    C和C++中的一些运算符要求操作符左边的值是一个左值,也就是说它们可以被修改。

    Here 是一个更完整的解释。

        4
  •  1
  •   jmanning2k    15 年前

    因为从stringstream提取的第一个值是std::string。如果它是一个int,那么stringstream(line)版本就可以工作。

    Std::String的Stringstream中没有成员函数运算符>。因此,临时流不能用作左值。

    不是说我完全理解上面的内容…但也许这是一个更好的答案的起点。