【问题标题】:proper memory allocation for strings字符串的正确内存分配
【发布时间】:2016-02-16 03:04:31
【问题描述】:

所以我遇到了这个问题,我已经尝试解决了大约 8 个小时......我已经放弃了在没有帮助的情况下寻找答案。我试过分别使用realloc()malloc(),所以任何输入都会很棒!

在 C 中的目的是允许创建“地图”,稍后我将使用 ncurses 来创建地图。

来自文件的输入如下

10X16 de4 dw9 ds8 g8,7 m3,4 h6,5 p2,2 
6X20 dn5 ds4 W4,3 e2,12 M1,1
10X13 ds3 dw9
10X12
5X4
6x12

代码如下:

char *importLevel()
{
    FILE *fPointer; 
    fPointer = fopen("Level", "r"); //Opens text file to read
    char* rooms[150];// set up for memory allocation
    char commands[150];// set up for pulling data from read file

    while (!feof(fPointer))
    {
        fgets(commands,150, fPointer); // this takes each line from the file
    }

    *rooms = (char *) malloc(150 * sizeof(char)); //  memory allocation
    for (int i = 0; i < 150; i++)
    {
        if (rooms[i] != NULL)
        {
            *rooms[i] = commands[i]; // supposed to give rooms the string
        }
    }

    fclose(fPointer);// close file

    return *rooms; // return pointer
 }

我希望我没有现在感觉的那么愚蠢!谢谢:)

编辑:我当时觉得自己很愚蠢

【问题讨论】:

  • 你的代码是废话。所以首先,你需要解释你想要在这段代码中做什么。
  • 对不起@BLUEPIXY 我是新来的
  • 您似乎也是 C 的新手。您需要提供 很多 更多上下文,例如……这段代码应该做什么?你输入的格式是什么?你为什么用C来解决这个问题?等
  • 我非常愿意,我将在代码的每个部分添加 cmets,以便您了解它们的用途
  • 在 c 中的目的是允许创建“地图”,稍后我将使用 ncurses 来创建地图。

标签: c compiler-errors


【解决方案1】:

这里有很多事情要解决。

while (!feof(fPointer))
{
    fgets(commands,150, fPointer); // this takes each line from the file
}

这将在每次循环中覆盖commands 中的数据。当循环退出时,您将读取并丢弃除最后一行之外的所有数据。您可能希望使用二维数组,或者更有可能在阅读时将数据存储到rooms。第二种方式速度更快,占用内存更少。

*rooms = (char *) malloc(150 * sizeof(char));

这看起来像是您正在尝试创建一个二维数组。相反,你会想做这样的事情:

for (int ii = 0; ii < 150; ++ii)
  rooms[ii] = malloc(150 * sizeof(char));

请注意,此 malloc 不会初始化内存。所以你的支票

if (rooms[i] != NULL)

会给你不确定的结果。 rooms[i] 的内容未定义。如果要将数组初始化为全零,请尝试使用memset

然后:

*rooms[i] = commands[i];

不会复制来自commands 的数据,而是只会复制来自commands 的第一个字符。要复制整个字符串,您需要使用strcpystrncpy 来避免潜在的缓冲区溢出问题。 memcpy 也是复制一些字节而不是以 null 结尾的 C 字符串的选项。

最后,返回*rooms 是一个等待发生的错误。最好将rooms 作为参数传递并分配给它。请参阅Allocate memory 2d array in function C 了解如何执行此操作。

【讨论】:

  • strndup 是另一个不错的选择,可以一次性获得mallocstrncpy
【解决方案2】:

其他人指出了您需要进行的一些更改。所以,看看他们所说的,并将您的版本与下面的版本进行比较。这应该会有所帮助。

这是您的程序的更正版本。我不得不根据你的代码和数据猜测你的一些意图[请原谅无偿的风格清理]:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <malloc.h>

char **
importLevel()
{
    FILE *fPointer;
    char commands[150];                 // file line buffer
    int roomcnt = 0;
    char *cp;
    char *bp;
    char **rooms = NULL;                // set up for memory allocation

    fPointer = fopen("Level", "r");     // Opens text file to read
    if (fPointer == NULL) {
        printf("importLevel: unable to open file -- %s\n",strerror(errno));
        exit(1);
    }

    while (1) {
        // this takes each line from the file
        cp = fgets(commands, sizeof(commands), fPointer);
        if (cp == NULL)
            break;

        // setup buffer for strtok
        bp = commands;

        // parse all words on line
        while (1) {
            // NOTE: the first assumes you want "g8,7" within a room
            // the second assumes you want "g8,7" as two separate rooms
#if 1
            cp = strtok(bp," \n");
#else
            cp = strtok(bp," ,\n");
#endif

            // strtok wants this on 2nd and subsequent loops for this line
            bp = NULL;

            // bug out if no more words on this line
            if (cp == NULL)
                break;

            // increase room list size (allow space for terminator)
            // NOTE: rooms will be preserved when we return from this function
            rooms = realloc(rooms,sizeof(char *) * (roomcnt + 2));

            // NOTE: cp is pointing to something in our stack frame that
            // will go away when we return or when we read the next line
            // so we must preserve it in the heap now
            cp = strdup(cp);

            // add the contents of the room
            rooms[roomcnt] = cp;

            // advance count of number of rooms
            ++roomcnt;
        }
    }

    // add terminator to list
    if (rooms != NULL)
        rooms[roomcnt] = NULL;

    fclose(fPointer);                   // close file

    return rooms;                       // return pointer
}

附:不要心情不好。无论程序员多么有经验,我们会犯“愚蠢”的错误。而且,我们每天都制作它们。欢迎加入俱乐部!

【讨论】:

    猜你喜欢
    • 2011-03-22
    • 2021-07-27
    • 2020-04-13
    • 1970-01-01
    • 2017-09-04
    • 2010-09-27
    • 2022-01-17
    • 1970-01-01
    相关资源
    最近更新 更多