我对qsort有疑问。
这有点奇怪,但我的qsort函数没有给我正确的输出。奇怪的是,我的一些比较函数与我过去的项目完全相同,但它们根本没有给我正确的输入。我不确定如何测试它。
例如:
int comp_name_asc(const void *a, const void *b)
{
const Rec *prec1 = (const Rec *) a;
const Rec *prec2 = (const Rec *) b;
return strcmp(prec1->name, prec2->name);
}
int comp_name_desc(const void *a, const void *b)
{
const Rec *prec1 = (const Rec *) a;
const Rec *prec2 = (const Rec *) b;
return strcmp(prec2->name, prec1->name);
}
第二个函数应该是降序,但结果是相同的:它总是按升序排列。我检查过以确保在正确的时间输入正确的功能。 Rec是我制作的struct的typedef,它有一个char * name参数。
另外(修改以避免溢出):
int comp_size_asc(const void *a, const void *b)
{
const Rec *prec1 = (const Rec *) a;
const Rec *prec2 = (const Rec *) b;
if (prec1->byteSize > prec2->byteSize)
return 1;
else if (prec1->byteSize < prec2->byteSize)
return -1;
else
return 0;
}
结果非常奇怪,不是上升或下降(即:500,515,100,200 ......)。 byteSize的类型为off_t,方法是:
char *path; // Build the path
struct stat sb;
if (lstat(path, &sb) == 0) {
// Read sb.st_size
我真的不确定如何调试它。我所知道的是,输入了适当的比较函数,并且过去曾使用过类似的比较函数。
任何想法或我如何调试这将是受欢迎的。谢谢。
编辑:
添加对qsort的调用:
int index = 0;
Rec **array = (Rec **) malloc(sizeof(Rec *) * capacity);
// Adds element to the array...
qsort(array, index, sizeof(Rec *), comp_name_desc);
(每次将一个元素添加到数组时,索引都会递增。)
感谢。
编辑:
下面给出了解决方案。谢谢!
我不得不改变:
const Rec *prec1 = (const Rec *) a;
到
const Rec *prec1 = *(const Rec **) a;
因为我如何定义我的数组。谢谢!
答案 0 :(得分:2)
你永远不应该通过减去数字来比较数字。这通常会导致带有签名类型的溢出,并且根本无法使用无符号类型。用于将数字与三态结果进行比较的通用惯用法如下
(a > b) - (a < b)
否则,您的比较函数看起来很好,所以问题必须与调用排序函数的方式有关。
答案 1 :(得分:2)
你有一个Rec
数组,或者更确切地说是一组Rec
指针?我问,因为比较函数作为参数指针进入数组,而不是直接作为记录。
以下是两种方式的演示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Rec {
char *name;
} Rec;
/*
* The pointers a and b point directly into the array,
* where the Records themselves are.
*/
static int
cmp_Rec_by_name(const void *a, const void *b) {
const Rec *rec1 = (Rec *)a;
const Rec *rec2 = (Rec *)b;
return strcmp(rec1->name, rec2->name);
}
/*
* The pointers point directly into the array, where
* not the records but pointers to them are. So they
* are a pointer to a pointer to a record.
*/
static int
cmp_Rec_ptr_by_name(const void *a, const void *b) {
const Rec *rec1 = *(Rec **)a;
const Rec *rec2 = *(Rec **)b;
return strcmp(rec1->name, rec2->name);
}
static void
sort_Rec(void) {
Rec record[3];
record[0].name = strdup("hello");
record[1].name = strdup("world");
record[2].name = strdup("how are you");
qsort(record, 3, sizeof (Rec), cmp_Rec_by_name);
for (int i = 0; i < 3; i++)
printf("%s\n", record[i].name);
}
static void
sort_Rec_ptr(void) {
Rec *(record[3]);
record[0] = malloc(sizeof (Rec));
record[1] = malloc(sizeof (Rec));
record[2] = malloc(sizeof (Rec));
record[0]->name = strdup("hello");
record[1]->name = strdup("world");
record[2]->name = strdup("how are you");
qsort(record, 3, sizeof (Rec *), cmp_Rec_ptr_by_name);
for (int i = 0; i < 3; i++)
printf("%s\n", record[i]->name);
}
int
main() {
sort_Rec();
sort_Rec_ptr();
return 0;
}
答案 2 :(得分:0)
听到行为是什么,如果strcmp()
交换了两个参数并且结果仍在提升,则预感可能是名称实际上不是名称。一个建议可能是使用printf
打印出名称,并将名称减少到2或3(记录数),以便更容易调试并检查它的行为是什么样的。