c语言 - 如何使用 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*)malloc(amount * sizeof(char));

您没有分配足够的内容,以后当您将其分配出去时,行为将未定义

做(演员表没用)

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

行为

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

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

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

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

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

待办事项

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);,因此您不释放其他数组

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

分配错误

//                                v----------v s/b the size of a pointer 
// names = (char*)malloc(amount * sizeof(char));
names = malloc(sizeof *names * amount);
//             ^-----------^ Much easier to code right    

偏差 1(或 2)错误

// fgets(names[i], MAX_CHARS - 1, stdin);
fgets(names[i], MAX_CHARS + 1, stdin);
// realloc((*names)[i], strlen(names[i]) * sizeof(char));
realloc((*names)[i], (strlen(names[i]) + 1)* sizeof(char));

在输入中保留

fgets(names[i], MAX_CHARS - 1, stdin);
// add
names[i][strcspn(names[i], "n")] = ''; // to lop off potential n

具有不匹配的 printf 说明符的潜在 UB。

// printf("%d", strlen(names[i]));
printf("%zu", strlen(names[i]));

未能释放分配

// add before `free(names);`
for (i=0; i<amount; i++) free(names[i]);

排序效率低下

当只有指向名称的指针需要交换时,代码会交换名称。 还要考虑qsort()


建议的中间代码,省略了排序详细信息。 建议在所有输入的名称后进行排序。

// Allocating space for the names.
// No need to allocate, a simple array will do.
// Let us double it size to help detect and consume long-ish names
char temp[MAX_CHARS * 2];
names = malloc(sizeof *names * amount);
if (names == NULL) Handle_OutOfMemory();
// Getting the names from the user
for (i = 0; i < amount; i++) {
printf("Enter name of friend %d: ", i + 1);
if (fgets(temp, sizeof temp, stdin)) {
Handle_Unexpected_Eary_EOF();
}
temp[strcspn(temp, "n")] = ''; // lop off potential n 
size_t len = strlen(temp);
if (len > MAX_CHARS) Handle_LongLine();
names[i] = malloc(len + 1);  // only allocated what is needed
if (names[i] == NULL) Handle_OutOfMemory();
strcpy(name[i], temp);
}
for (i = 0; i < amount; i++) {
printf("<%s>n", names[i]);
}
// Sort by your own code or take time to learn `qsort()`
qsort(names, amount, sizeof names[0], TBD_compare_function);
for (i = 0; i < amount; i++) {
printf("<%s>n", names[i]);
free(names[i]);
}
free(names);
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define SIZE 50
#define NEWSIZE 25
int main(void)
{
char *str = malloc(SIZE);
/* now there are 25 bytes
* allocated for str, unless
* an error occurs
*/
void *tmp = realloc(str, NEWSIZE);
if (!tmp) {
perror("ERROR");
exit(EXIT_FAILURE);
}
str = tmp;
exit(EXIT_SUCCESS);
}

相关内容

  • 没有找到相关文章

最新更新