繁体   English   中英

在循环中重用 std::stringstream 和 std::istream_iterator

[英]Reuse std::stringstream and std::istream_iterator in loop

我有以下文本文件:

0 0 0 0 0 1 0 0 2 3 4 2 1 2 1
0 0 0 0 2 7 5 4 5 7 5 4 3
3 2 4 6 2 7 2 7 5 4 5 7 5 4 3
3 2 4 6 2 7 2 7 5 4  5 4 3
0 0 0 0 0 1 0 2 3 4 2 1 2 1
0 0 0 0 0 1 0 0 2 3 4 2 1 2 1
0 0 0 0 2 1 2 1
3 2 4 6 2 7 2 7 5 4 5 7 5 4 3
3 2 4 6 2 0 2 3 4 2 1 2 1
0 0 0 0 0 1 0 0 2 3 4 2 1 2 1
3 2 4 6 2 7 2 7 5 4 5 7 5 4 3

我可以使用以下程序阅读它:

#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>

int main()
{
    std::ifstream is("numbers.txt");
    std::string line;
    std::vector<std::vector<int>> numbers{};
    while (std::getline(is,line)) {
        std::stringstream ss{line};
        std::istream_iterator<int> start{ss},end;
        numbers.emplace_back(start,end);
        std::cout << "Read " << numbers.back().size() << " numbers in row\n";
    }
    std::cout << "Read " << numbers.size() << " rows\n";

    std::cout << "numbers read in:\n";
    for (auto row : numbers) {
        for (auto number : row) {
            std::cout << number << " ";
        }
        std::cout << "\n";
    }
    std::cout << std::endl;
}

我想在循环外只创建一次std::stringstreamstd::istream_iterator 每次在以下程序中执行循环时,如何将迭代器调整到正确的位置?

#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>

int main()
{
    std::ifstream is("numbers.txt");
    std::string line;
    std::vector<std::vector<int>> numbers{};
    std::stringstream ss{line};
    std::istream_iterator<int> start{ss},end;
    while (std::getline(is,line)) {
        ss << line;
        //start = ss.beg;
        numbers.emplace_back(start,end);
        std::cout << "Read " << numbers.back().size() << " numbers in row\n";
    }
    std::cout << "Read " << numbers.size() << " rows\n";

    std::cout << "numbers read in:\n";
    for (auto row : numbers) {
        for (auto number : row) {
            std::cout << number << " ";
        }
        std::cout << "\n";
    }
    std::cout << std::endl;
}

为了使第二种方法起作用,必须解决两个问题:

  1. std::stringstream ss必须清除eof标志,以便可以再次使用。 为此,我们可以使用ss.clear()
  2. 然后,一旦将新数据添加到ss ,必须重置std::istream_iterator以便它可以看到来自std::stringstream的新输入。 这里的关键是要意识到,一旦它被构造,迭代器就会读取它将提供的第一个值。

那么程序就变成了:

#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>

int main()
{
    std::ifstream is("numbers.txt");
    std::string line;
    std::vector<std::vector<int>> numbers{};
    std::stringstream ss{line};
    std::istream_iterator<int> start{ss},end;
    while (std::getline(is,line)) {
        ss.clear(); // clear eof flag
        ss << line; // ok to add data 
        start = ss; // reset the iterator so that it will see the new data
        numbers.emplace_back(start,end);
        std::cout << "Read " << numbers.back().size() << " numbers in row\n";
    }
    std::cout << "Read " << numbers.size() << " rows\n";

    std::cout << "numbers read in:\n";
    for (auto row : numbers) {
        for (auto number : row) {
            std::cout << number << " ";
        }
        std::cout << "\n";
    }
    std::cout << std::endl;
}

在 Visual Studio 2015 中,我执行了以下操作:

  • 我用很多条目运行了两个版本的程序,没有明显的区别。

  • 在这两种情况下,大部分时间都花在构造迭代器上,因为语句start = ss; 似乎在任何情况下都在调用构造函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM