【问题标题】:C++ read numbers from file and store in vectorsC++ 从文件中读取数字并存储在向量中
【发布时间】:2010-09-15 23:47:54
【问题描述】:

我在“撤消”此方法时遇到了麻烦,该方法本质上是将可变大小的数字矩阵转储到文本文件中:

void vectorToFile(char *name, vector<vector<double>>* a){
    FILE* fp = fopen(name, "w");
    for(int i=0;i<a->size();i++){
        for(int j=0;j<a->at(i).size();j++){
            fprintf(fp, "%f ", a->at(i).at(j));
        }
        fprintf(fp, "\n");
    }
    fclose(fp);
}

我在执行反向操作时遇到问题:

vector<vector<double>> fileToVector(char *name){ ??? }

我保证文件中的数字形成一个“矩形”,即内部向量的大小都相等,但我不知道如何计算每行的条目数和列数.

谁能指出我正确的方向?到目前为止,我发现的每个示例都实现了一些更容易的东西,具有硬编码的大小,或者第一行给出的大小(不幸的是,我负担不起)

【问题讨论】:

  • 您希望文件中的数据如何组织?你能给我们举个例子吗?同时,这里有一个示例可能会有所帮助:stackoverflow.com/questions/2677029/…
  • 我认为方法说明了。基本上作为一个数字矩阵:m 个数字,以 n 行中的空格分隔

标签: c++ file input


【解决方案1】:

我是 C++ 新手,所以我不确定这是否是一个好方法,但我会打开文件,逐行读取输入,在阅读时解析每一行。这是一些示例代码(未经测试,未编译):

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

std::vector<std::vector<double> > fileToVector(const char *name)
{
    std::vector<std::vector<double> > result;
    std::ifstream input (name);
    std::string lineData;

    while(getline(input, lineData))
    {
        double d;
        std::vector<double> row;
        std::stringstream lineStream(lineData);

        while (lineStream >> d)
            row.push_back(d);

        result.push_back(row);
    }

    return result;
}

【讨论】:

  • 对新手来说很好的答案,+1 来自我。我唯一要补充的是,在关闭流之前检查流是否实际到达 EOF:if( !lineStream.eof() ) throw inputError("Dammit!"); 或更好,以免被尾随空格 if( !(lineStream &gt;&gt; std::ws).eof() ) throw inputError("Dammit!"); 抛弃。
【解决方案2】:

您可以尝试更多 C++ish 方法:

void vectorToFile(std::vector<double> const& vec, std::string const& filename) {
    std::ofstream file(filename);
    if(file.good()) {
        file.flags(std::ios::fixed);
        std::copy(vec.begin(), vec.end(), std::ostream_iterator<double>(file));
    } else {
        // throw error or sth
    }
    file.close();
}

如果你想保存为二进制文件,你可以像这样使用 ostream_binary_iterator - http://bit.ly/9JAxdp:

void vectorToFile(std::vector<double> const& vec, std::string const& filename) {
    std::ofstream file(filename, std::ios::binary);
    if(file.good()) {
        file.flags(std::ios::fixed);
        std::copy(vec.begin(), vec.end(), ostream_binary_iterator<double>(file));
    } else {
        // throw error or sth
    }
    file.close();
}

【讨论】:

    【解决方案3】:

    如果您使用 C++ I/O 而不是 C I/O 会更容易。我建议使用ifstream 读取文件并使用getline() 读取每一行。然后每一行是应该进入vector 的数字。解析string 的最简单方法可能是使用stringstream。然后,您可以将每个double 和push_back() 解析到vector,因此您不必关心vectors 的大小。我还建议尽可能使用std::string 而不是char*(尽管对于文件名,您通常最终不得不在它们上使用c_str(),因为文件I/O 的东西似乎总是占用@987654333 @ 而不是 std::string)。

    【讨论】:

      【解决方案4】:

      您可以读取行,使用您拥有的分隔符拆分,然后解析为数字。 您可以使用getline 将行读取为字符串,您不需要知道确切的数字。

      【讨论】:

        【解决方案5】:

        使用向量 > 而不是只使用 double** 和使用 new double[] 来分配数组和每个子元素有什么特别的原因吗?我的猜测是数组可以在运行时动态调整大小,但是如果数组只分配一次,使用 double** 肯定比遍历向量更有效。

        无论如何,解决您的问题的方法是在文件中预先转储数组的边界并将其读回...

        【讨论】:

        • 这不是很好的建议。向量提供了许多额外的好处(负责内存管理,提供与&lt;algorithm&gt; 中的许多算法一起使用的迭代器,如果您使用at(),则提供边界检查等)。在这一点上,性能不应该是真正的考虑因素。
        • 只是为了回答您所说的问题,即是否有任何特殊原因使用向量而不是 c 样式数组 - 主要原因是 OP 在 C++ 上下文中询问,而不是 C。
        • 对vector 进行迭代的效率可能与迭代overy 动态数组的效率不完全一样。奇怪的是 vector 的迭代器无论如何都是指针(至少在发布模式下),尽管这取决于实现。此外,使用push_back() 将比您在向其添加更多元素时不断调整数组大小更有效。无论如何,文件 I/O 成本会掩盖迭代动态数组和 vector 之间的任何性能差异。此外,与使用数组相比,使用向量将产生更易于维护的代码。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-25
        • 1970-01-01
        • 1970-01-01
        • 2021-12-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多