C++ 表示std::endl的istream_迭代器

C++ 表示std::endl的istream_迭代器,c++,stl,istream-iterator,C++,Stl,Istream Iterator,我想将以下容器存储在文件中: std::vector< std::vector< Point > > m_vPoints; 点元素用“,”分隔,点用“”分隔,例如: 我成功地制作了这样一个文件: std::ostream& operator<<(std::ostream &o, ...) { for(auto it=m_vPoints.begin(); it!=m_vPoints.end(); ++it) {

我想将以下容器存储在文件中:

std::vector< std::vector< Point > > m_vPoints;
点元素用“,”分隔,点用“”分隔,例如:

我成功地制作了这样一个文件:

std::ostream& operator<<(std::ostream &o, ...)
{
    for(auto it=m_vPoints.begin(); it!=m_vPoints.end(); ++it)
    {
        copy(it->begin(), it->end(), std::ostream_iterator<Point>(o," "));
        o << endl;
    }
    return o;
}
而且效果很好。然而,问题在于阅读。当我尝试以下方法时:

std::istream& operator>>(std::istream &is, ...)
{
    int numberOfRows; // assume it is known and valid
    m_vPoints.resize(numberOfRows);
    for(int i=0; i<numberOfRows; i++)
    {
        copy(std::istream_iterator<Point>(is), std::istream_iterator<Point>(), std::back_inserter(m_vPoints[i]));
    }
    return is;
}
所有线中的所有点都被读入m_p点[0]。看起来std::istream_迭代器忽略了std::endl。使用is>>noskipws将不起作用,因为我仍然希望跳过分隔各个点的空格。所以基本上,问题是从istream复制,但不是直到流的末尾,而是直到行的末尾。我在网络中看到的使用cin的示例以某种方式解析了一行,忽略了空格字符,但正确地以std::endl或'\n'结尾

我还希望避免使用getline,因为这样我必须将每一行复制到一个字符串中,然后解析该字符串。相反,我希望将行I直接复制到容器mvpoints[I]

逐行读取:

std::istream& operator>>(std::istream &is,
                         std::vector<std::vector<Point>>& points)
{
    using namespace std;
    using point_itr = istream_iterator<Point>;
    string line;
    while( getline(is, line) ) // read line by line
    {
        // iterate points from istringstream into new line vector
        istringstream line_in{ line };
        points.emplace_back(
            make_move_iterator(point_itr{ line_in }),
            make_move_iterator(point_itr{}) );
    }
    return is;
}
编辑:

这是标准解

我还希望避免使用getline,因为这样我必须将每一行复制到一个字符串中,然后解析该字符串。相反,我希望将行I直接复制到容器mvpoints[I]

您想避免使用std::getline有什么原因吗

阅读每一点后,您可以在代码中使用ifis.peek=='\n'。这将使您的代码更加复杂,因为您将不再能够直接从迭代器复制,而实际执行此操作的代码将更加复杂,您还必须手动处理输入流错误状态。

逐行阅读:

std::istream& operator>>(std::istream &is,
                         std::vector<std::vector<Point>>& points)
{
    using namespace std;
    using point_itr = istream_iterator<Point>;
    string line;
    while( getline(is, line) ) // read line by line
    {
        // iterate points from istringstream into new line vector
        istringstream line_in{ line };
        points.emplace_back(
            make_move_iterator(point_itr{ line_in }),
            make_move_iterator(point_itr{}) );
    }
    return is;
}
编辑:

这是标准解

我还希望避免使用getline,因为这样我必须将每一行复制到一个字符串中,然后解析该字符串。相反,我希望将行I直接复制到容器mvpoints[I]

您想避免使用std::getline有什么原因吗


阅读每一点后,您可以在代码中使用ifis.peek=='\n'。这将使您的代码更加复杂,因为您将不再能够直接从迭代器复制,而执行此操作的实际代码将更加复杂,您还必须手动处理输入流错误状态。

我希望避免使用getline以避免从字符串复制到点,但您的解决方案似乎可以解决此问题。一件事是我无法编译您提出的解决方案,因为:无法在std::make_move_iteratorpoint_itrline_中从'const DisparityPixel'转换为'DisparityPixel&',另外,我替换了{}对于as VS2012,我似乎不喜欢它。为了解决编译问题,我假设这些点是可移动的定义DisparityPixel::DisparityPixel DisparityPixel&&constructor。如果不能这样做,只需删除make_move_迭代器调用。我在VStudio 2013初始值设定项列表支持方面也遇到了同样的问题。我创建了移动构造函数,但它没有帮助-我想它与常量限定符有关。错误的另一部分是:在编译类模板成员函数“DisparityPixel&&std::move\u iterator::operator*void const”时。不知道为什么,因为我没有在DisparityPixel的定义中使用const。当然,类DisparityPixel对应于前面介绍的点。您是否也添加了移动赋值?我应该提到它,但没有提到,因为通常在定义移动构造函数时,也会定义移动赋值运算符。事实证明,不能直接从istream_迭代器生成移动迭代器,请参见:。无论如何,感谢您的帮助。我想避免使用getline,以避免从字符串复制到点,但您的解决方案似乎解决了这个问题。一件事是我无法编译您提出的解决方案,因为:无法在std::make_move_iteratorpoint_itrline_中从'const DisparityPixel'转换为'DisparityPixel&',另外,我替换了{}对于as VS2012,我似乎不喜欢它。为了解决编译问题,我假设这些点是可移动的定义DisparityPixel::DisparityPixel DisparityPixel&&constructor。如果不能这样做,只需删除make_move_迭代器调用。我在VStudio 2013初始值设定项列表支持方面也遇到了同样的问题。我创建了移动构造函数,但它没有帮助-我想它与常量限定符有关。错误的另一部分是:在编译类模板成员函数“DisparityPixel&&std::move\u iterator::operator*void const”时。不知道为什么,因为我没有在DisparityPixel的定义中使用const。当然,类DisparityPixel对应于前面介绍的点。您是否也添加了移动赋值?我应该提到它,但没有提到,因为通常在定义移动构造函数时,也会定义移动赋值运算符。事实证明,不能直接从istream_迭代器生成移动迭代器,请参见:。不管怎样,谢谢你的帮助。
std::istream& operator>>(std::istream &is,
                         std::vector<std::vector<Point>>& points)
{
    using namespace std;
    using point_itr = istream_iterator<Point>;
    string line;
    while( getline(is, line) ) // read line by line
    {
        // iterate points from istringstream into new line vector
        istringstream line_in{ line };
        points.emplace_back(
            make_move_iterator(point_itr{ line_in }),
            make_move_iterator(point_itr{}) );
    }
    return is;
}