我在 linux 中的 qsort 有什么问题?
What's the wrong with my qsort in linux?
我正在使用 Mac OS 来实现命令排序的部分功能:
我的部分代码如下:
int compare(const void *p, const void *q) {
return strcmp(*(char **)p, *(char **)q);
}
void sort_file(char *filename, int unique, int reverse) {
/* TODO: Complete this function */
/* Note: you will probably need to implement some other functions */
char buf[1024][1024];
int i=0;
FILE * fp;
if(!(fp=fopen(filename,"r"))){
perror("Open error!");
exit(0);
}
while(fgets(buf[i],1024,fp)){
printf("%s",buf[i]);
i++;
}
qsort(buf, i, sizeof(char *), compare);
}
结果总是显示segmentation fault: 11
谁能告诉我这是什么问题以及如何修改它?
我还想知道,如果我不知道一行和文件中代码的最大大小,如何定义我的数组?
我从这个页面得到了这个想法:
http://www.anyexample.com/programming/c/qsort__sorting_array_of_strings__integers_and_structs.xml
您没有指针数组;你有一个数组数组。数组数组中的每个元素都有一个特定的固定步长 1024 char
。 qsort
需要知道这一点,而你却没有告诉它。首先改变这个:
qsort(buf, i, sizeof(char *), compare);
对此:
qsort(buf, i, sizeof *buf, compare);
现在 qsort
知道每个 "thing" 在您的字符数组中有多大。
接下来,您的比较器应该被更改以说明正在传递的地址以及它与您的数组相关的内容。传递给比较器的每个地址都是元素所在的位置。但是你的元素每个都是char[1024]
。一些char[1024]
的地址不是一些char**
,而是char(*)[1024]
。这里不涉及指向指针的指针。您的比较器可以简单地是:
int compare(const void *p, const void *q)
{
const char (*lhs)[1024] = p;
const char (*rhs)[1024] = q;
return strcmp(*lhs, *rhs);
}
接下来,您控制循环中没有限制器来防止数组溢出。简而言之,这:
while(fgets(buf[i],1024,fp))
应该是这样的:
while(i < 1024 && fgets(buf[i],1024,fp))
理想情况下,1024 应该在某处表示为常数,以避免出现幻数。
最后,您在函数中泄漏了一个开放 FILE*
。这不是一个好计划。确保 fclose()
您的文件指针。
我看到的问题:
qsort
的参数错误
qsort(buf, i, sizeof(char *), compare);
需要:
qsort(buf, i, sizeof(buf[0]), compare);
由于buf+1
和buf
相差1000char
s,所以用sizeof(char*)
作为第三个参数是错误的
compare
中的参数转换错误
原来的指针是char (*)[1000]
类型,不是char**
。因此你需要使用:
int compare(const void *p, const void *q) {
char (*p1)[1000] = (char (*)[1000])(p);
char (*q1)[1000] = (char (*)[1000])(q);
return strcmp(*p1, *q1);
}
我正在使用 Mac OS 来实现命令排序的部分功能: 我的部分代码如下:
int compare(const void *p, const void *q) {
return strcmp(*(char **)p, *(char **)q);
}
void sort_file(char *filename, int unique, int reverse) {
/* TODO: Complete this function */
/* Note: you will probably need to implement some other functions */
char buf[1024][1024];
int i=0;
FILE * fp;
if(!(fp=fopen(filename,"r"))){
perror("Open error!");
exit(0);
}
while(fgets(buf[i],1024,fp)){
printf("%s",buf[i]);
i++;
}
qsort(buf, i, sizeof(char *), compare);
}
结果总是显示segmentation fault: 11
谁能告诉我这是什么问题以及如何修改它?
我还想知道,如果我不知道一行和文件中代码的最大大小,如何定义我的数组?
我从这个页面得到了这个想法: http://www.anyexample.com/programming/c/qsort__sorting_array_of_strings__integers_and_structs.xml
您没有指针数组;你有一个数组数组。数组数组中的每个元素都有一个特定的固定步长 1024 char
。 qsort
需要知道这一点,而你却没有告诉它。首先改变这个:
qsort(buf, i, sizeof(char *), compare);
对此:
qsort(buf, i, sizeof *buf, compare);
现在 qsort
知道每个 "thing" 在您的字符数组中有多大。
接下来,您的比较器应该被更改以说明正在传递的地址以及它与您的数组相关的内容。传递给比较器的每个地址都是元素所在的位置。但是你的元素每个都是char[1024]
。一些char[1024]
的地址不是一些char**
,而是char(*)[1024]
。这里不涉及指向指针的指针。您的比较器可以简单地是:
int compare(const void *p, const void *q)
{
const char (*lhs)[1024] = p;
const char (*rhs)[1024] = q;
return strcmp(*lhs, *rhs);
}
接下来,您控制循环中没有限制器来防止数组溢出。简而言之,这:
while(fgets(buf[i],1024,fp))
应该是这样的:
while(i < 1024 && fgets(buf[i],1024,fp))
理想情况下,1024 应该在某处表示为常数,以避免出现幻数。
最后,您在函数中泄漏了一个开放 FILE*
。这不是一个好计划。确保 fclose()
您的文件指针。
我看到的问题:
qsort
qsort(buf, i, sizeof(char *), compare);
需要:
qsort(buf, i, sizeof(buf[0]), compare);
由于buf+1
和buf
相差1000char
s,所以用sizeof(char*)
作为第三个参数是错误的
compare
原来的指针是char (*)[1000]
类型,不是char**
。因此你需要使用:
int compare(const void *p, const void *q) {
char (*p1)[1000] = (char (*)[1000])(p);
char (*q1)[1000] = (char (*)[1000])(q);
return strcmp(*p1, *q1);
}