从 .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::vector
s 范围构造函数。在这里您可以指定一个开始迭代器和一个结束迭代器和构造函数,连同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 文件中读取未知大小的整数二维数组的最有效方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章