2010-08-15 41 views
17

假設我有一個指針數組在C CHAR:如何在C中對指向char的指針數組進行排序?

char *data[5] = { "boda", "cydo", "washington", "dc", "obama" }; 

我想用快速排序排序此陣:

qsort(data, 5, sizeof(char *), compare_function); 

我無法拿出比較功能。出於某種原因,這不起作用:

int compare_function(const void *name1, const void *name2) 
{ 
    const char *name1_ = (const char *)name1; 
    const char *name2_ = (const char *)name2; 
    return strcmp(name1_, name2_); 
} 

我做了很多的搜索,發現我不得不使用**快速排序的內部:

int compare_function(const void *name1, const void *name2) 
{ 
    const char *name1_ = *(const char **)name1; 
    const char *name2_ = *(const char **)name2; 
    return strcmp(name1_, name2_); 
} 

而這個工作。

任何人都可以解釋在這個函數中使用*(const char **)name1嗎?我根本不理解它。爲什麼是雙指針?爲什麼我的原始功能沒有工作?

謝謝,Boda Cydo。

+2

的背景下'data'應聲明'const'。 – 2010-08-15 20:47:51

+0

比利,如果它是常量,它仍然可以排序嗎? – bodacydo 2010-08-15 20:48:59

+1

是的。該數組可以不是'const',但包含在該數組中的指針應該是'const'。你不能修改像這樣的編譯時常量字面值(這是未定義的行爲)。爲了得到這個,你需要'const char * data [5]'。如果你希望數組本身也是恆定的,那麼你應該做'const char * const data [5]'。 – 2010-08-15 20:53:04

回答

17

如果它有助於保持頭腦清醒,那麼應該將指針指向比較器的類型與傳遞到qsort(即qsort文檔稱爲base)的數據指針的原始類型相同。但是對於qsort是通用的,它只是將所有內容都作爲void*來處理,而不管其「真正」是什麼。

因此,如果您正在整理一系列整數,那麼您將傳遞一個int*(轉換爲void*)。 qsort會給你回指向比較器的兩個指針void*,你將其轉換爲int*,並取消引用以獲得實際比較的int值。

現在提供char*替換int

如果你正在排序的char*陣列,那麼你將傳遞一個char**(轉換爲void*)。 qsort將返回指向比較器的兩個void*指針,您將其轉換爲char**,並取消引用以獲取實際比較的char*值。

在你的例子中,因爲你正在使用一個數組,所以你傳入的char**char*數組的結果「衰減」到指向它的第一個元素的指針。由於第一個元素是char*,因此它的指針是char**

3

想象一下你的數據是double data[5]

您的比較方法將接收指針(double *,作爲void *傳遞給元素(double))。
現在再次用char *替換double。

2

qsort是足夠普遍的,以排列由指針以外的其他東西組成的數組。這就是尺寸參數在那裏的原因。它不能直接將數組元素傳遞給比較函數,因爲它在編譯時不知道它們有多大。因此它通過指針。在你的情況下,你得到指向char *char **

+0

我不明白,對不起。 'qsort'的第一個參數是'*'。我通過一個'**'。這意味着我有效地傳遞了一個'*'。但是一個'*'完全是'char *'。看到?這就是我困惑的原因。 – bodacydo 2010-08-15 20:59:36

+0

@bodacydo:重要的一點是比較函數需要指向數組的*元素*。由於數組中的每個元素都是一個指向字符的指針,所以比較函數在指向字符指針的指針上運行。 – jamesdlin 2010-08-15 21:08:30

0

man qsort

The contents of the array are sorted in ascending 
order according to a comparison function pointed to by 
compar, which is called with two arguments that **point** 
to the objects being compared. 

所以它聽起來像的比較函數獲取指針數組元素。現在指向char *的指針是char ** (即指向指向字符的指針)。

0

char *data[5] = { "boda", "cydo", "washington", "dc", "obama" };

是要求編譯器爲字符指針的大小爲5的陣列的語句。您已經將這些指針初始化爲字符串文字,但是對於編譯器,它仍然是一個由五個指針組成的數組。

當您將該數組傳遞到qsort時,根據C數組參數傳遞規則,指針數組衰減爲指向第一個元素的指針。

因此,在獲得包含常量的實際字符數組之前,您必須先處理一個間接級別。

2

比較函數將指針指向要排序的數組中的對象的類型。由於數組包含char *,因此您的比較函數需要指向char *,又名char **。這裏

0

@bodacydo是可以解釋其他程序員試圖傳達什麼樣的程序,但是這將是「整數」

#include <stdio.h> 


int main() 
{ 
    int i , j; 
    int *x[2] = {&i, &j}; 

    i = 10; j = 20; 

    printf("in main() address of i = %p, address of j = %p \r\n", &i, &j); 

    fun(x); 
    fun(x + 1); 

    return 0; 
} 


void fun(int **ptr) 
{ 
    printf("value(it would be an address) of decayed element received = %p, double dereferenced value is %d \r\n",*ptr, **ptr); 
    printf("the decayed value can also be printed as *(int **)ptr = %p \r\n", *(int **)ptr); 
} 
相關問題