【问题标题】:Print an array that was re-allocated several times in C打印在 C 中多次重新分配的数组
【发布时间】:2021-08-27 20:56:09
【问题描述】:

基本上:

我正在从文本文件中提取字符。每个单词都以一个结尾 \n 在文本文件中。

我想创建一个char ** 数组,其中仅包含每个单词的第一个字符。

为此,我正在扫描文本文件并在我的chars 数组上运行。 如果当前的char\n,则在插入chars 数组时将其替换为null terminator \0

这样,当我使用 char **words_arr 在该阵列上运行时,我将能够在 words 之间分离。

我希望**words_arr 指向单词的每个第一个字符,这意味着每个\0 后面都有一个字符,表示单词的结尾。

size_t words = 1, total_characters = 30;
char **original_address, **words_arr, *chars, character;

chars = (char *)malloc(sizeof(char) * total_characters);
words_arr = original_address = (char **)malloc(sizeof(char *) * (words);

while (i < total_characters)
    {
        character = fgetc(text_file);
        
        if (character == EOF)
        {
            break;
        }
        if (character == '\n')
        {
            *chars =  '\0';
            *words_arr = chars + 1;
            ++words;
            words_arr = (char **)realloc(original_address, sizeof(char *) * (words));
            words_arr += words-1;
        }
        else
        {
            *chars = character;
        }
        ++chars;
        ++i;
    }

另外,我不知道我会有多少单词,这就是我使用realloc 函数的原因,尽管我不确定我做得对。

现在,我可以打印 chars 数组并查看所有单词,并且每个单词都从新行开始。

但是当我尝试打印 words 数组时,我遇到了分段错误。

我正在尝试使用以下方法打印它们:

i = 0;
    
    chars -= total_characters;
    
    while (i < total_characters)
    {
        runner = chars + i;
        if (*runner == '\0')
        {
            printf("\n");
        }
        else
        {
            printf("%c", *runner);
        }
        ++i;
    }
    
    printf("\n\n");
    
    words_arr -= words;
    
    i = 0;
    
    while (i < words)
    {
        printf("%s", *(words_arr + i));
        ++i;
    }

正如我所说,第一次打印或chars 数组成功。 words_arr 的第二次打印返回 Segmentation fault

谢谢。

【问题讨论】:

  • realloc 可能会使数组无效以重新分配original_address。在那之后重复使用它是不好的。
  • malloc() 家族的投射结果也是considered as a bad practice
  • 如果我理解正确,您是否已将整个文件读入内存?如果是这样,只需遍历所有内容并计算\n:s(同时将它们更改为\0)。这样您就知道要分配多少,并且只能进行 one 分配。然后再次运行它以分配指针。
  • 作为一个小问题,请注意EOF不是字符;即您需要一个int 来保存所有字符 EOF。这就是为什么fgetc() 的返回类型是not char
  • 我建议你做一些小函数来管理内存。测试每个函数是否都做正确的事情变得更容易。它可能看起来像这样:example

标签: arrays c pointers segmentation-fault realloc


【解决方案1】:

这部分:

words_arr = (char **)realloc(original_address, sizeof(char *) * (words));

是错误的(出于多种原因)。

realloc 成功返回(即分配新内存)时,original_address 的值不再有效。但是在您的代码中,您在循环中再次使用original_address

您需要在每个realloc 之后更新original_address,以便它对下一个realloc 有效。

【讨论】:

  • 但在下一次迭代中,我应该更新words_arr,而不是在开始时而是在最后更新的元素之后。所以我应该这样做:words_arr = realloc(original_address,.....) 然后original address = words_arr 然后words_arr += words 这样它就可以在正确的地方为下一次迭代做好准备?
  • 好吧,我尝试了以下操作:original_address = (char **)realloc(original_address, sizeof(char *) * (words));words_arr = original_address + words - 1;,然后是 while (i &lt; wordsprintf("%s", *(original_address + i));,我仍然得到 seg fault
  • @NoobCoder 使用realloc 的正确方法是:char** tmp = realloc(..); if(tmp) { original_address = tmp; } else { /* error handling */ }:您需要在重新分配之前检查返回值,因为重新分配可能会失败。如果你不检查,你会丢失指向仍然有效内存的原始指针,如果你没有另一个,你就会有内存泄漏。
猜你喜欢
  • 2016-05-24
  • 1970-01-01
  • 1970-01-01
  • 2012-06-17
  • 1970-01-01
  • 2021-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多