2010-10-11 71 views
4

我有一個關於qsort的問題。qsort問題() - 排序不正確(C)

這有點奇怪,但我的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是我製作的結構的一個typedef,它有一個char * name參數。

另外(修改以避免溢出):

​​

結果是完全怪異,不上升或下降(即: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

歡迎SO。對我來說+1是一個很好的書面問題和格式良好的代碼。 – Arun 2010-10-11 06:19:45

+1

你可以顯示你調用qsort()的代碼嗎?在「升序」的情況下,記錄是按名稱排序的? – psmears 2010-10-11 06:20:54

+1

順便說一句,在比較函數中使用減法並不是一個好主意:在整數溢出的情況下,你會得到不一致的比較結果。 – zvrba 2010-10-11 06:24:18

回答

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; 
} 
+0

非常感謝,你是對的,它應該是:const Rec * rec1 = *(Rec **)a;我的問題已修復,非常感謝! – Jary 2010-10-11 07:17:15

+0

使用'const Rec rec1 = *(Rec *)a'來複制整個記錄,但不需要。這就是爲什麼我在'cmp_Rec_ptr_by_name'中使用了指針指針。 – 2010-10-11 22:09:43

+0

非常感謝! – Jary 2010-10-15 23:43:32

1

您不應該通過從另一箇中減去數字來比較數字。這通常會導致使用簽名類型溢出,並且根本無法使用無符號類型。與三態結果比較數字通用成語是下面

(a > b) - (a < b) 

否則,你的比較函數看起來很好,所以這個問題必須在調用排序功能的方式。

+0

謝謝,我沒有想到這一點。我會解決這個問題,如果其他語句。 – Jary 2010-10-11 07:09:35

0

聽到行爲是什麼,預感可能是名稱實際上不是名稱,如果strcmp()有兩個參數交換,結果仍然是上升的。一個建議可能是使用printf打印出名稱,並且將名稱減少到2或3(記錄數),以便更容易調試並檢查其行爲如何。