从 .txt 文件中读取未知大小的整数二维数组的最有效方法是啥?

Posted

技术标签:

【中文标题】从 .txt 文件中读取未知大小的整数二维数组的最有效方法是啥?【英文标题】:What is the most efficient way to read integer 2D array with unknown size from .txt file?从 .txt 文件中读取未知大小的整数二维数组的最有效方法是什么? 【发布时间】:2021-10-04 04:58:22 【问题描述】:

read.txt 文件中我有:

//read.txt的开始

第一个矩阵是: 1、2、3、4; 5、6、7、8; 9、8、1、2;\

//read.txt 结束 注意空格、逗号和分号矩阵可以不同!(这就是为什么我写了未知大小的矩阵)

我非常非常低效的方法: 使用getline(File, string)while(getline(File,str)) 循环,我将在第一次 时间内通过循环来查找行和列。然后我将使用行和列来创建int arr[row][col],并通过second循环和同一个文件将每个整数分配给arr[row][col]。 我也在考虑malloc(),但是,每次我分配新内存时它都会删除数组内容(例如为了创建更多行)。

我上面的方法非常缓慢和混乱。所以我正在寻找如何提高效率的建议!

【问题讨论】:

你标记了 C++,所以忘了malloc()。如果列数固定,则使用std::array,否则使用std::vector 如果使用realloc而不是malloc,就可以解决之前填充的数组内容丢失的问题。但是,正如其他人已经指出的那样,在 C++ 中,您可以简单地使用std::vector,并且会自动为您处理底层内存缓冲区的大小调整。 描述的写法表明The first matrix is: 是文件的一部分。使用代码标签标记文件范围,所以毫无疑问。 【参考方案1】:

您需要选择正确的方法来解决该问题。

如果您想存储未知数量的列,则可以使用std::vector。它会随您的喜好动态增长。

如果你想存储未知数量的行和列,那么你将再次使用std::vector。但是此时一个vector的vector,So,一个二维的vector:std::vector<std::vector<std::string>>

这将存储任意数量的行和任意数量的不同列。

接下来。要从一行中提取数据,或者更好地说,就是拆分行。

为此有一个特殊的专用迭代器。 std::sregex_token_iterator。你可以定义你正在寻找的模式。或者,您可以定义一个模式,即您不想要的分隔符。

而且由于正则表达式用途广泛,您可以构建满足您需求的复杂模式。

对于正 sarach 数字,您可以使用 R"(\d+)",对于负搜索分隔符,您可以使用 R"([\.;\\])"。

如果要搜索分隔符,可以在构造函数的最后一个参数中添加 -1。

为了得到分割线的结果,我们将使用std::vectors 范围构造函数。在这里您可以指定一个开始迭代器和一个结束迭代器和构造函数,连同std::sregex_token_iterator 将为您完成所有工作。

看下面的简单例子:

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

using Columns = std::vector<std::string>;
using Rows = std::vector<Columns>;

const std::string fileName "data.txt" ;
const std::regex re R"(\d+)" ;

int main() 

    // Open file and check, if it could be opened
    if (std::ifstream inputFileStream fileName ; inputFileStream) 

        // Here we will store the result
        Rows rows;

        // Read all complete text lines from text file
        for (std::string line; std::getline(inputFileStream, line);) 

            // Get the columns
            Columns columns(std::sregex_token_iterator(line.begin(), line.end(), re), );

            // Add the columns to rows
            rows.push_back(columns);
        
        // Debug Ouput
        for (const auto& row : rows) 
            for (const auto& column : row) std::cout << column << ' ';
            std::cout << '\n';
        

       
     // Error message, if file could not be opened
    else std::cerr << "\nError:Could not open file '" << fileName << "'\n\n";
    return 0;

使用 C++17 编译

【讨论】:

【参考方案2】:

在 Linux 操作系统上,您可以使用 mmap(2) 在地址空间中查看文本文件,然后使用标准解析技术,可能是 ANTLR 或 GNU bison。

我相信性能不会有太大变化:大部分时间将花在执行 IO 上(例如,等待旋转磁盘,如果有的话)。除非您必须解析一个巨大的矩阵(例如数百万个整数),否则我相信您的方法在 2021 年的实践中已经足够好了。

我建议在做出任何重新设计决策之前使用分析器(例如GNU gprof)。 CPU 时间很可能会花在程序的其他地方。

您可能想通过一些解析来研究现有开源程序的源代码以获取灵感,例如GCC, ninja, RefPerSys, fish.

当然,阅读好的C++ programming book 并使用C++ containers。

您可以使用部分评估技术并在运行时生成机器代码,其中asmjit 或libgccjit 适合您的矩阵的特定大小。我认为这不值得。

我建议先写一个完全正确的程序,调试它,然后再优化它。

考虑使用静态分析器,例如 Frama-C。

【讨论】:

您的任何答案或 cmets 是否都没有指向 refpersys 的链接? 我链接到其他打开的我们正在解析的程序。 是的,我确实提到了我合作过的程序:m!编译或贡献过。

以上是关于从 .txt 文件中读取未知大小的整数二维数组的最有效方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

从文件中读取未知长度的 int 数组

从txt文件中读取数据放在二维数组中

读取包含二维矩阵的 .txt 文件,fscanf 仅从 .txt 文件中获取第一个数据元素

在 C/C++ 中将矩阵读取到二维数组

从 Fortran 中的 HDF 文件中读取长度未知的数组

从 C 中的文件输入创建二维数组