如何从 .t​​xt 中提取文本并将其存储到动态二维数组中?

Posted

技术标签:

【中文标题】如何从 .t​​xt 中提取文本并将其存储到动态二维数组中?【英文标题】:How to pull text out of a .txt and store it into a dynamic 2d array? 【发布时间】:2021-12-09 11:07:50 【问题描述】:

我需要从我的 .txt 文件中逐行提取文本并将其存储到一个动态数组中,每次我从 .txt 文件中提取新行时都会分配新空间。我的代码似乎可以很好地拉出第一行并将其存储到第一个指针数组中,但是在第二个循环中,它似乎重置了所有指针数组,当我稍后尝试访问它时,这给了我内存分配错误。为什么会发生这种情况,尤其是当我在将内容存储到指针及其数组后不触摸它们时?

char** temp = nullptr;
    char buffer[256];
    int index = 0;

    // Open File
    fstream myFile;
    myFile.open("pantry.txt", ios::in);
    if (myFile.is_open())
    
        while (!myFile.eof())
        
            myFile >> buffer; // Pull line out of txt.file

            temp = new char* [index + 1]; // Create new pointer

            temp[index] = new char[strlen(buffer)+1]; // Create char array pointed at by new pointer
#pragma warning(suppress : 4996) // Turns off complier warning
            strcpy(temp[index], buffer); //Copy buffer into new char array
            index++; // Increment our index counter int

            
        

        for (int i = 0; i < index; i++)
        
            cout << temp[i] << endl;
        

如果分配和存储正确,我希望它能够准确地打印出 txt 文件。 相反,我得到了

Exception thrown at 0x7B9A08CC (ucrtbased.dll) in PE 12.4.exe: 0xC0000005: Access violation reading location 0xCDCDCDCD.

餐具室.txt

Basil
Flat Leaf Parsely
Thyme
Sage
Cumin
Steak Seasoning
Mace
Garlic Powder

【问题讨论】:

除非您有特定的理由不这样做(例如做不允许这样做的家庭作业),否则我强烈建议您创建`std::vector<:string>@987654325 @std::getline` 读取每一行,std::push_back 将每一行放入vector。有了这个,工作变得相当容易。 temp 应该代表什么?使用模糊的变量名称,您甚至可能不会注意到您一遍又一遍地为该变量分配新的东西,总是泄漏(并丢失)它曾经指向的东西。 您的问题的根本原因(除了没有像@JerryCoffin 说的那样使用现代c++)是您重新分配temp 每个循环,因此第二个循环您丢失了第一个循环中存储的所有内容,等等。 哦,我也刚刚注意到您使用的是while (!myFile.eof())。这通常也会导致问题。您通常需要while (read_from_file_succeeded()) 形式的东西。 在上面展开:Why is iostream::eof inside a loop condition (i.e. while (!stream.eof())) considered wrong? 【参考方案1】:

显示的代码中有多个错误。

while (!myFile.eof())

这是always a bug,除了显示代码的主要问题之外,还必须修复:

temp = new char* [index + 1];

为了帮助您理解这一行的问题,记住计算机编程的黄金法则会很有帮助:

您的计算机始终完全按照您的指示执行操作,而不是 你想让它做什么。

根据黄金法则,上面一行告诉你的计算机,确切地说:“new 某事,并将其分配给temp”。

这就是您的计算机每次执行此行时都会执行的操作。此行在此循环的每次迭代中执行一次。下次循环运行时,之前的 newed temp 将被另一个替换,泄漏它之前指向的所有内容。为什么你的电脑要在这条线上做其他事情?毕竟,这正是您告诉计算机要做的事情。这就是为什么您观察到这将在循环的每次迭代中“重置所有指针数组”,从而导致“内存分配错误”。

无论如何,这整个逻辑块都需要废弃并从头开始重写,这一次使用正确的逻辑。最简单的做法是实际使用 C++ 库的 std::vectorstd::string 对象,它们将为您正确分配所有内存。现代 C++ 代码很少需要 new 任何东西,而是使用 C++ 库的容器。

您的作业目标可能是演示如何正确使用低级内存分配和释放逻辑。在这种情况下,您将需要找到其他方法来执行此操作。由于您事先不知道行数,因此一种方法是构建一个链表,一次一行,因为从文件中读取每一行。只有在读取整个文件(并且行数已知)之后,才分配具有所有字符指针的最终数组,将指针移至数组,并删除临时链表。或者,也许实现一个类似std::vector 的算法,逐步分配一个新的指针数组,当它已满时,将所有字符指针复制到一个更大的数组,然后删除原来的。

当然,这是很多工作。但是,除非您的分配或任务的目的是正确实现低级内存分配和释放,否则为什么要经历所有的工作和痛苦来做 std::vectorstd::string 已经做的事情,当您可以简单地使用它们时,只需要五六行代码,就可以取代上面的所有代码?

【讨论】:

以上是关于如何从 .t​​xt 中提取文本并将其存储到动态二维数组中?的主要内容,如果未能解决你的问题,请参考以下文章

从文本文件中逐行提取数据并将其存储在python的列表中[重复]

如何从 android 手机中提取联系人并将其存储/导入到模拟器中的应用程序中?

XCTEST - 如何从屏幕截图中提取文本并将其与预期字符串进行比较

如何将数据库中的数据提取到 javascript 文件中并将其存储在数组中?

我正在尝试从文本文件数据中提取并将其添加到音频读取函数 Matlab

从动态表格视图中的文本字段获取文本并将其插入到数组中