首页 > 解决方案 > 如何从 .t​​xt 中提取文本并将其存储到动态二维数组中?

问题描述

我需要从我的 .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

标签: c++arraysvisual-c++dynamicdynamic-arrays

解决方案


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

while (!myFile.eof())

除了所示代码的主要问题之外,这始终是一个必须修复的错误:

temp = new char* [index + 1];

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

您的计算机始终完全按照您的指示执行操作,而不是您希望它执行的操作。

根据黄金法则,上面这行代码准确地告诉您的计算机:“new某物,并将其分配给temp”。

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

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

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

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


推荐阅读