我试图获取某个字符串,将字符串设置为一定的大小,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
在不检查 malloc
和 realloc
的结果的情况下,您认为/希望有足够的内存,但这可能是错误的,在这种情况下这些函数返回 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/