【问题标题】:read integers from a file into a vector in C++将文件中的整数读入 C++ 中的向量
【发布时间】:2013-11-05 07:31:24
【问题描述】:

我正在尝试将存储在不同行中的未知数量的双精度值从一个文本文件读取到一个名为rainfall 的向量中。我的代码无法编译;对于 while 循环行,我收到错误 no match for 'operator>>' in 'inputFile >> rainfall'。我了解如何从文件读入数组,但我们需要为这个项目使用向量,但我不明白。我很感激你能给我下面的部分代码的任何提示。

vector<double> rainfall;    // a vector to hold rainfall data

// open file    
ifstream inputFile("/home/shared/data4.txt");

// test file open   
if (inputFile) {
    int count = 0;      // count number of items in the file

    // read the elements in the file into a vector  
    while ( inputFile >> rainfall ) {
        rainfall.push_back(count);
        ++count;
    }

    // close the file

【问题讨论】:

  • 我建议使用迭代器对构造函数。网上有很多例子。

标签: c++ vector


【解决方案1】:

我认为您应该将其存储在double 类型的变量中。似乎您正在对一个向量执行&gt;&gt;,这是无效的。考虑以下代码:

// open file    
ifstream inputFile("/home/shared/data4.txt");

// test file open   
if (inputFile) {        
    double value;

    // read the elements in the file into a vector  
    while ( inputFile >> value ) {
        rainfall.push_back(value);
    }

// close the file

正如@legends2k 指出的那样,您不需要使用变量count。使用rainfall.size() 检索向量中的项目数。

【讨论】:

  • 变量count 也是多余的,因为rainfall.size() 会为您提供该信息。
  • 更新了答案。谢谢:)
【解决方案2】:

您不能使用&gt;&gt; 运算符来读取整个向量。您需要一次读取一项,并将其推入向量中:

double v;
while (inputFile >> v) {
    rainfall.push_back(v);
}

您不需要对条目进行计数,因为rainfall.size() 会为您提供准确的计数。

最后,最接近 C++ 的读取向量的方法是使用 istream 迭代器:

// Prepare a pair of iterators to read the data from cin
std::istream_iterator<double> eos;
std::istream_iterator<double> iit(inputFile);
// No loop is necessary, because you can use copy()
std::copy(iit, eos, std::back_inserter(rainfall));

【讨论】:

  • 我正在根据上面海报的建议研究迭代器概念。在这一点上对我来说有点复杂,但我决心理解这些东西!再次感谢大家的帮助。
【解决方案3】:

你也可以这样做:

#include <algorithm>
#include <iterator>

...
std::istream_iterator<double> input(inputFile);
std::copy(input, std::istream_iterator<double>(),    
          std::back_inserter(rainfall));
...

假设你喜欢 STL。

【讨论】:

    【解决方案4】:

    输入运算符&gt;&gt; 未定义用于将doubles 输入到std::vector

    改为使用两个用于输入文件的标记化输入迭代器构造 std::vector

    这是一个示例,说明如何使用仅 2 行代码来做到这一点:

    std::ifstream inputFile{"/home/shared/data4.txt"};
    std::vector<double> rainfall{std::istream_iterator<double>{inputFile}, {}};
    

    另一种解决方案是将输入运算符函数定义为:

    std::istream& operator>> (std::istream& in, std::vector<double>& v) {
        double d;
        while (in >> d) {
            v.push_back(d);
        }
        return in;
    }
    

    然后您可以像在示例中一样使用它:

    std::vector<double> rainfall;
    inputFile >> rainfall;
    

    【讨论】:

    • 感谢您展示第一种方法。它只有 2 个 locs 是的,但我认为它不是更具可读性。发生了什么并不是很明显。第二个参数是什么?它使用两个输入迭代器和一个可选的分配器调用向量的构造函数。第二个输入迭代器似乎是默认构造的并且指向空(NULL)。该行为标准是否在某处确认/定义?如何回答这些问题?
    • @SebastianWilke 在这方面使用{} 时没有类型,它被视为从预期参数类型推导出的类型的值或直接初始化(取决于是否提供参数)。所以在这种情况下,它等同于std::istream_iterator&lt;double&gt;{}。初始化 std::istream_iterator 的值会生成流结束迭代器 (see here)。
    • @SebastianWilke 我找不到合适的规范参考来说明没有类型的{} 如何工作,但它通常被称为“统一初始化”。对流尾迭代器使用值初始化(空括号)是标准用法(例如,参见example)。例如:for_each(std::istream_iterator&lt;double&gt;(my_istream), std::istream_iterator&lt;double&gt;()) 将迭代 my_istream 直到到达流结束。
    【解决方案5】:

    考虑使用这个输入阅读器:

    #include <iterator>
    #include <algorithm>
    #include <vector>
    #include <iostream>
    #include <fstream>
    
    template<typename T>
    std::vector<T> parse_stream(std::istream &stream) {
        std::vector<T> v;
        std::istream_iterator<T> input(stream);
        std::copy(input, std::istream_iterator<T>(), std::back_inserter(v));
        return v;
    }
    
    int main(int argc, char* argv[])
    {
        std::ifstream input("/home/shared/data4.txt");
        std::vector<int> v = parse_stream<int>(input);
        for(auto &item: v) {
            std::cout << item << std::endl;
        }
        return 0;
    }
    

    它也允许您使用其他流类型,并且是通用的类型读取。

    【讨论】:

      猜你喜欢
      • 2015-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多