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

How to pull text out of a .txt and store it into a dynamic 2d array?

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

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.

pantry.txt

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

显示的代码中存在多个错误。

while (!myFile.eof())

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

temp = new char* [index + 1];

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

Your computer always does exactly what you tell it to do instead of what you want it to do.

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

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

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

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

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