qsort()的问题 - 排序没有正确完成(C)

时间:2010-10-11 06:15:44

标签: c sorting qsort

我对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;

因为我如何定义我的数组。谢谢!

3 个答案:

答案 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(记录数),以便更容易调试并检查它的行为是什么样的。