c - 如何使用 realloc 来缩短字符串数组大小

标签 c malloc realloc

我试图获取某个字符串,将字符串设置为一定的大小,50个字符,然后在输入所有字符串后,它会对它们进行排序,然后将大小从50个字符重新分配到长度用户写入的字符串,如果一开始我给了它 50 个字节,并且有人输入“hi”,它将更改为所需的字节数。

#include <stdio.h>

#define MAX_CHARS 50

int main(void)
{
    int i = 0, j = 0;
    char* temp = 0;
    char** names = 0;
    int amount = 0;

    // Getting number of friends from user
    printf("Enter number of friends: ");
    scanf("%d", &amount);
    getchar();

    // Allocating space for the names.
    temp = (char*)malloc(MAX_CHARS * sizeof(char));
    names = (char*)malloc(amount * sizeof(char));

    for (i = 0; i < amount; i++)
    {
        names[i] = (char*)malloc((MAX_CHARS + 1) * sizeof(char));
    }

    // Getting the names from the user
    for (i = 0; i < amount; i++)
    {
        printf("Enter name of friend %d: ", i + 1);
        fgets(names[i], MAX_CHARS - 1, stdin);
    }

    for (i = 0; i < amount; i++)
    {
        for (j = i + 1; j < amount; j++)
        {
            if (strcmp(names[j], names[i]) < 0)
            {
                strcpy(temp, names[j]);
                strcpy(names[j], names[i]);
                strcpy(names[i], temp);
            }
        }
        // Reallocating the 50 bytes space to only the space needed.
        printf("%d", strlen(names[i]));
        (*names)[i] = (char*)realloc((*names)[i], strlen(names[i]) * sizeof(char));
    }

    for (i = 0; i < amount; i++)
    {
        printf("%s", names[i]);
    }

    free(names);
    getchar();
    return 0;
}

最佳答案

names是一个指向char的指针数组,所以在

names = (char*)malloc(amount * sizeof(char));

您没有分配足够的空间,稍后当您从中分配它时,行为将是未定义的

做( Actor 阵容没用)

names = malloc(amount * sizeof(char*));

正在做

(*names)[i] = (char*)realloc((*names)[i], strlen(names[i]) * sizeof(char));

无效,因为 (*names)[i] 是一个字符,不要忘记结束字符串的空字符的位置,所以你想要:

names[i] = realloc(names[i], strlen(names[i]) + 1);

请注意,根据定义,sizeof(char) 为 1

在不检查 mallocrealloc 的结果的情况下,您认为/希望有足够的内存,但这可能是错误的,在这种情况下这些函数返回 NULL,它是检查这种情况更安全。这意味着 realloc 首先保存在辅助 char* 中,以免丢失 names[i] 的当前值,您可以继续使用如果realloc返回NULL

待办事项

scanf("%d", &amount);

很危险,当输入无效时,您不知道这一点,并且金额在您使用它时未使用未定义的行为进行初始化,例如

if (scanf("%d", &amount) != 1)
{
   puts("invalid value");
   return -1;
}

考虑如何使用names[i]

names[i] = (char*)malloc((MAX_CHARS + 1) * sizeof(char));

你分配的1字节太多了,你可以这样做

 names[i] = malloc(MAX_CHARS);

警告行为:

fgets(names[i], MAX_CHARS - 1, stdin);

可能结束输入的换行符保存在 names[i] 中,您可能需要将其删除。在这种情况下,您必须在打印名称时进行调整,以在名称之间引入分隔符、空格或换行符。

另一种没有换行符的阅读方式是:

 scanf(" 49%[^\n]", names[i]);

49 允许限制在数组中写入的字符数(我删除了 1 以便为空字符腾出空间),并且前面的空格允许绕过输入开头的空格(此处 空格 表示“”,但也表示制表符、换行符等)。使用这种方式,名称可以包含空格,而 "%49s" 格式则不然。

无论如何,无论你使用什么,你都需要检查输入是否完成,否则你不会设置数组,当你稍后使用它时,行为将是未定义的。

当你对数组进行排序时:

strcpy(temp, names[j]);
strcpy(names[j], names[i]);
strcpy(names[i], temp);

但你不需要深入复制,只需交换它的指针即可:

char * aux = names[j];

names[j] = names[i];
names[i] = aux;

最后你想释放资源,但你只做了 free(names); 所以你不会释放其他数组

关于c - 如何使用 realloc 来缩短字符串数组大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61580863/

相关文章:

c - c中是否有一个函数可以返回char数组中char的索引?

C - 我在编写 "rotate right"函数时遇到问题

c - struct 的初始化函数(即 "constructor"),为什么变量没有正确初始化?

c - 内存泄漏链表

c++ - 动态分配的字符串

c - Realloc 设置指针为空

C++ malloc - 动态数组

c - 将 unsigned long 转换为字符串的缓冲区大小

c - 创建动态通用数组时,realloc 出现段错误

c - 为什么 `realloc()` 在某些神秘输入上失败?