我写了这个代码来对名称进行排序,代码可以正常运行,但是程序结束时总是出现错误:堆坏了。有人可以帮我解释它为什么会发生以及如何修复它? 我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TEMP_SIZE 50
void swap(char *str1, char *str2);
int main(void)
{
int number = 0, i = 0, j = 0;
char** names = 0;
char temp[TEMP_SIZE] = { 0 };
printf("Enter number of friends: ");
scanf("%d", &number);
names = (char**)malloc(number * sizeof(char*));
for (i = 0; i < number; i++)
{
printf("Enter name of friend %d: \n", i + 1);
scanf("%s", temp);
names[i] = (char*)malloc(strlen(temp) * sizeof(char) + 1);
strcpy(names[i], temp, strlen(temp) + 1);
}
for (j = 0; j < number - 1; j++)
{
for (i = 0; i < number - 1; i++)
{
if (strcmp(names[i], names[i + 1]) > 0)
{
swap(names[i + 1], names[i]);
}
}
}
for (i = 0; i < number; i++)
{
printf("Friend %d: %s\n", i + 1, names[i]);
}
for (i = number - 1; i >= 0; i--)
{
free(names[i]);
}
free(names);
getchar();
getchar();
return 0;
}
void swap(char *str1, char *str2)
{
char *temp = 0;
temp = (char *)malloc((strlen(str1) + 1) * sizeof(char));
strcpy(temp, str1);
strcpy(str1, str2);
strcpy(str2, temp);
free(temp);
}
如果你能帮助我,我会很高兴和感激的!
答案 0 :(得分:3)
当字符串长度不同时,上面的swap
函数将覆盖已分配字符串的边界,从而破坏堆。您可能只想交换存储在names数组索引中的指针,而不是覆盖已分配的字符串缓冲区的内容。
您也可以使用stdlib qsort
对数组进行排序。
答案 1 :(得分:1)
swap
函数的问题在于它期望两个字符串都有
相同的长度或两个存储位置足够大以容纳
字符串。考虑这个例子:
char str1[] = "Hello";
char str2[] = "This is a so much longer string";
swap(str1, str2);
会崩溃,因为str1
不足以存储str2
的内容,所以
strcpy
调用将超出内存限制,因此您会溢出
缓冲区。这是您面临的问题。
你需要解决方案:
name[i]
分配1024个字节,无论长度如何
这个名字。我们可以假设没有名称超过1024个字符。 (不要这么做,丑陋的解决方案)。names
是char**
而name[i]
是char*
s,所以交换指针
很容易,因为你不必担心它们的记忆长度
指着。交换功能可能如下所示
void swap_ptrs(char **x, char **y)
{
char *tmp = *x;
*x = *y;
*y = tmp;
}
而不是调用
swap(names[i + 1], names[i]);
你打电话给:
swap_ptrs(names + i + 1, names + i);
将交换指针。
修改强>
我意识到你甚至不需要swap_ptrs
功能,你可以这样做:
if (strcmp(names[i], names[i + 1]) > 0)
{
char *tmp = names[i];
names[i] = names[i + 1];
names[i + 1] = tmp;
}
正如jspcal指出的那样,最优雅和最强大的解决方案是使用qsort
:
int comp(const void *x, const void *y)
{
const char *a = *((const char **) x);
const char *b = *((const char **) y);
return strcmp(a, b);
}
int main(void)
{
...
qsort(names, number, sizeof *names, comp);
...
}