【问题标题】:change static array into dynamic with malloc and realloc?使用 malloc 和 realloc 将静态数组更改为动态数组?
【发布时间】:2014-11-17 20:45:23
【问题描述】:

您好,以下代码读取标准输入并将其放入标准输出,但相反。我为此使用了一个静态数组,因为我知道 input.txt 中有多少字符。我的问题是如何使用 malloc 和 realloc 更改动态数组(指针)中的数组?我所有的尝试都失败了。

#include <stdio.h>
#include <stdlib.h>



    int main()
{
    char ch;
    int i,counter;
    char array[50];

    counter = 0;
    i = 0;

    while((ch=getchar()) != EOF)
    {

        array[i] = ch;
        i++;
        counter++;

    }

    for(i = (counter + 1); i >= 0; i--)
    {
        printf("%c",array[i]);
    }

    printf("\n");

    return 0;
}

【问题讨论】:

  • 您实际尝试过什么?您当前的代码仍然有静态数组。
  • 我有很多错误,所以我认为最好发布代码,这确实有效。
  • 好吧,如果我们没有看到失败的代码,我们也无能为力,不是吗?
  • 听起来不错。我会再试一次,然后我把代码贴在静态数组代码下面。
  • 好的,问题是我不知道如何正确使用它们。很多页面有很多不同的使用方式,但对我没有帮助。那么有人可以帮助我吗?

标签: c arrays malloc stdin realloc


【解决方案1】:

即使您知道您使用的输入永远不会超过 50 个字符,您也应该强制执行该限制。当程序以任意输入运行时,您最终将访问数组末尾之外的数据。

不管怎样,这是你的程序核心,提取成一个函数:

void rev1()
{
    char array[50];     // Allocate 50 bytes on the stack
    int i = 0;
    char ch;

    while (i < 50 && (ch = getchar()) != EOF) array[i++] = ch;    
    while (i--) putchar(array[i]);
    printf("\n");

    // Do nothing - array goes out of scope
}

如果你只是想在堆上使用相同的定长缓冲区,代码非常相似。您应该定义一个指向char 而不是数组的指针,然后调用malloc 以获得所需的内存。使用完该内存后,您必须使用free 释放它。

这是使用堆内存的第二个版本:

void rev2()
{
    char *array;
    int i = 0;
    char ch;

    array = malloc(50 * sizeof(*array));    // Allocate on the heap
    if (array == NULL) exit(1);             // Check for failure

    while (i < 50 && (ch = getchar()) != EOF) array[i++] = ch;    
    while (i--) putchar(array[i]);
    printf("\n");

    free(array);        // Explicitly release data after use
}

注意事项:

  • sizeof(*array) 在这种情况下是 sizeof(char),它始终为 1,因此通常被省略。但是p = malloc(count * sizeof(*p)) 是一种非常有用的分配模式,用于分配count 元素的数组,如果您更改指向的事物的类型,它仍然可以工作。

  • 堆上的内存分配可能会失败;然后malloc 将返回NULL。你必须迎合这种情况。简单的策略是只打印一条错误消息并中止程序。根据您需要内存的目的,您可能会选择其他失败策略。

  • 注意函数的核心如何,循环和第一版完全一样。

  • 您还必须强制执行 50 个字符的限制。数组在堆上,但没有增长。

  • 使用后释放内存。如果你不这样做,你就会“泄漏内存”,也就是说,你会阻止大块的内存。这里,array - 保存数组的指针变量,而不是数组本身 - 是一个超出范围的局部变量。忘记free这里的内存将意味着你丢失了它的地址,无法再次访问它。

  • 变量array指向内存的开始。此变量必须传递给free。不要更改此变量,例如通过增加它,否则你将失去你的记忆“钥匙”。

稍微复杂的版本会根据需要重新分配内存。如果您的数组增长,您可以使用realloc 而不是malloc。即使内存不同,已分配的数据仍保留在原地:

void rev3()
{
    char *array = NULL;     // Initially unallocated NULL array
    size_t size = 0;        // Allocated size, initially 0
    int i = 0;
    char ch;

    while ((ch = getchar()) != EOF) {
        if (i >= size) {                    // Check current bounds
            size += 50;                     // Increase memory
            array = realloc(array,          // Reallocate
                size * sizeof(*array));
            if (array == NULL) exit(1);
        }
        array[i++] = ch;    
    }

    while (i--) putchar(array[i]);
    printf("\n");

    free(array);        // Explicitly release data after use
}

注意事项:

  • realloc(NULL, size) 的行为类似于 malloc(size)。因此,您可以从 NULL 指针开始轻松实现重新分配方案。

  • 虽然内核在内部跟踪分配的大小,但您无法知道它,因此您必须自己跟踪这些信息,在这种情况下使用size

  • 同样,您必须确保分配成功。我在上面使用了快速而肮脏(和静默)的程序终止,但您可以选择其他策略。

  • 在这种情况下,核心循环的参与程度更高。在追加到内存之前,您必须检查是否应该增加它。填充内存后,访问(在分配的范围内)照常进行。

【讨论】:

    【解决方案2】:

    显而易见的解决方案:

    #include <stdlib.h>
    #include <stdio.h>
    
    void readandprint(void)
    {
      int c = getchar();
      if (c == EOF)
        return;
      readandprint();
      printf("%c", c);
      return;
    }
    
    int main()
    {
      readandprint();
      printf("\n");
      return 0;
    }
    

    【讨论】:

    • 对不起,如果我的问题,我不明白这个答案。
    • @student96:你试过了吗?
    • 不,我应该如何使用这段代码?如何使用函数本身?
    • @student96:它叫做recursion。不理解的人注定要重蹈覆辙。而 C 程序的传统做法是编译和运行它们。
    【解决方案3】:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void){
        int ch;//It must be int for comparison with the EOF.
        int i, counter;
        char *array = malloc(50);
        int size = 50;
    
        counter = 0;
    
        while((ch=getchar()) != EOF){
            array[counter++] = ch;
            if(counter == size){
                char *temp = realloc(array, size += 50);
                if(temp==NULL){
                    free(array);
                    fprintf(stderr, "realloc error!\n");
                    return -1;
                }
                array = temp;
            }
        }
    
        while(counter){
            printf("%c", array[--counter]);
        }
    
        free(array);
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-13
      • 1970-01-01
      • 2021-04-07
      • 2018-08-29
      • 2012-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多