【问题标题】:How to read an "uneven" matrix from a file, and store into a 2D array?如何从文件中读取“不均匀”矩阵并存储到二维数组中?
【发布时间】:2019-07-11 02:03:23
【问题描述】:

我正在进行一项需要我切换到 C++ 的实验,我仍在学习。我需要将文件中的数据读取到二维数组中,其中文件中的数据由浮点数组成,以矩阵格式排列。但是,数据文件中矩阵的每一行都有不同的列数,例如:

1.24 3.55 6.00 123.5
65.8 45.2 1.0
1.1 389.66 101.2 34.5 899.12 23.7 12.1

好消息是我知道文件可能具有的最大行数/列数,至少现在我并不特别担心内存优化。我想要的是有一个二维数组,其中相应的行/列与文件的行/列匹配,所有其他元素都是一些已知的“虚拟”值。

我的想法是遍历文件的每个元素(逐行),识别行尾,然后开始读取下一行。不幸的是,我无法执行此操作。例如:

#include <iostream>
#include <fstream>

int main() {

const int max_rows = 100;
const int max_cols = 12;
//initialize the 2D array with a known dummy
float data[max_rows][max_cols] = {{-361}};

//prepare the file for reading
ifstream my_input_file;
my_input_file.open("file_name.dat");

int k1 = 0, k2 = 0; //the counters
while (!in.eof()) { //keep looping through until we reach the end of the file
    float data_point = in.get(); //get the current element from the file
    //somehow, recognize that we haven't reached the end of the line...?
        data[k1][k2] = next;
    //recognize that we have reached the end of the line
        //in this case, reset the counters
        k1 = 0;
        k2=k2+1;
}
}

所以我无法弄清楚索引。部分问题是,虽然我知道字符“\n”标记了一行的结尾,但与文件中的浮点数相比,它的类型不同,所以我很茫然。我是不是想错了?

【问题讨论】:

  • 一定要用数组吗?
  • 用数组不可能完成吗?我对矢量没有任何经验...
  • 难道不能用数组来完成 -- 不是不可能,但不切实际。如果您查看您的代码,您会想出任意大小。以任何方式超过这些大小,都会导致未定义的行为。不使用所有空间,你有空的空间不做任何事情。除此之外,数组不可调整大小,因此您永远不能拥有“锯齿状”二维数组。如果有的话,你是在使用二维数组来伪造这个。除此之外,在使用传统数组时,您不知道每一行的“实际大小”。使用std::vector——它可以解决所有这些问题。
  • while (!in.eof()) -- 为此,please read this
  • @JohnAlperto 查看我的更新答案!!!!我尽力做到尽可能简单、高效和易于理解!!!!

标签: c++ arrays file multidimensional-array


【解决方案1】:

如果你坚持std::vector,你不需要提前知道限制。下面是一些将读取文件的示例代码(假设文件中没有非浮点数)。

using Row = std::vector<float>;
using Array2D = std::vector<Row>;

int main() {
    Array2D data;
    std::ifstream in("file_name.dat");
    std::string line;
    Row::size_type max_cols = 0U;
    while (std::getline(in, line)) { // will stop at EOF
        Row newRow;
        std::istringstream iss(line);
        Row::value_type nr;
        while (iss >> nr) // will stop at end-of-line
            newRow.push_back(nr);
        max_cols = std::max(max_cols, newRow.size());
        data.push_back(std::move(newRow)); // using move to avoid copy
    }
    // make all columns same length, shorter filled with dummy value -361.0f
    for(auto & row : data)
        row.resize(max_cols, -361.0f);
}

【讨论】:

  • 感谢您的帮助。你能解释一下你在用“Row::size_type max_cols = 0U;”做什么吗?线?另外,由于我不熟悉向量,push_back 和 resize 是它们独有的吗?
  • Row::size_type ... 只是为了获取相关容器使用的正确大小类型,在这种情况下,std::vector(它通常以std::size_t 结尾。所以我可以写过std::size_t max_cols = 0U;0U 只是我的说法,我想为无符号标量类型分配一个无符号零。push_backresize 不是vector 独有的。请参阅en.cppreference.com/w/cpp/container 方法通过容器共享。唯一可靠的方法是.empty()
【解决方案2】:

这是起点,我将编写您可以使用的代码。使用二维向量vector&lt;vector&lt;double&gt;&gt;,您可以使用getline() 将线作为string 获取,而不是使用string stream 从字符串中获取小数。

这是代码

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

int main (void) {
    std::vector<std::vector<double>> matrix;

    std::ifstream inputFile;
    inputFile.open("test.txt");
    char line[99];
    for (int i = 0; inputFile.getline(line, sizeof(line)); ++i) {    
        std::stringstream strStream (line);
        double val = 0.0;
        matrix.push_back(std::vector<double>());
        while (strStream >> val)
            matrix[i].push_back(val);
    }

    return 0;
}

【讨论】:

  • 您需要修复char line[99]; for (int i = 0; inputFile.getline(line, 200); ++i) 部分以匹配所提供缓冲区的大小。我可以建议inputFile.getline(line,sizeof(line))inputFile.getline(line, 99) 吗?
  • double vals[valCnt]; -- 这不是有效的 C++。你为什么要发布一个包含这个的答案,而到目前为止所有评论并给出答案的人都声明使用std::vector?也许您应该坚持只发布vector 示例?
  • @PaulMcKenzie 我理解你的担忧,这是C 样式数组,但相信我,我就是这样。如果你不介意,我稍后会修复这个烂摊子。 :( 刚从外面来,我的邻居有货。
  • @PaulMcKenzie 现在已经永久修复了!!!!有时,当有人在学习新事物时,它比其他任何东西都更加心理学。对我来说,更多的是帮助 OP 让程序以他舒适的方式工作,而不是继续尝试vectorsstd::array 等。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-23
  • 1970-01-01
  • 1970-01-01
  • 2013-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多