Domanda

Supponiamo che io sono un array di puntatori a char in C:

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

E desidero ordinare questo array utilizzando qsort:

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

Non sono in grado di venire con la funzione di confronto. Per qualche motivo questo non funziona:

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_);
}

Ho fatto un sacco di ricerca e ha scoperto che ho dovuto usare ** all'interno di qsort:

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_);
}

E funziona.

Qualcuno può spiegare l'uso di *(const char **)name1 in questa funzione? Non capisco affatto. Perché il doppio puntatore? Perché non il mio lavoro funzione originale?

Grazie, Boda Cydo.

È stato utile?

Soluzione

Se aiuta cose proseguire dritto in testa, il tipo che si dovrebbe lanciare i puntatori al vostro confronto è lo stesso come il tipo originale del puntatore di dati che si passa in qsort (che i documenti qsort chiamano base). Ma per qsort di essere generica, solo che si occupa di tutto come void*, indipendentemente da ciò che "realmente" è.

Quindi, se siete ordinare un array di int, allora si passerà in un int* (convertito in void*). qsort ti restituirà due puntatori void* al comparatore, che si converte a int*, e risolvere il riferimento per ottenere i valori int che in realtà confrontare.

Ora sostituire int con char*:

se siete ordinare un array di char*, allora si passerà in un char** (convertito in void*). qsort ti restituirà due puntatori void* al comparatore, che si converte a char**, e risolvere il riferimento per ottenere i valori char* effettivamente confrontano.

Nel tuo esempio, perché si sta utilizzando una matrice, il char** che si passa è il risultato della matrice di char* "decomposizione" ad un puntatore al suo primo elemento. Dato che il primo elemento è un char*, un puntatore ad essa è un char**.

Altri suggerimenti

Immaginate la vostra dati erano double data[5].

Il metodo compare avrebbe ricevuto puntatori (doppia *, passata come * vuoto) agli elementi (doppia).
Ora sostituire doppia con char * di nuovo.

qsort è abbastanza generale da matrici di ordinamento, comprensivi di altre cose di puntatori. Ecco perché il parametro di dimensione è lì. Esso non può passare gli elementi della matrice alla funzione di confronto direttamente, in quanto non conosce al momento della compilazione quanto grandi siano. Quindi passa puntatori. Nel tuo caso si ottiene puntatori a char *, char **.

La funzione di confronto prende puntatori al tipo di oggetto che di nella matrice che si desidera ordinare. Dal momento che l'array contiene char *, la vostra funzione di confronto prende puntatori a char *, aka char **.

da 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.

Così suona come la funzione di confronto ottiene puntatori agli elementi dell'array. Ora un puntatore ad una char * è un char ** (Cioè un puntatore a un puntatore a un carattere).

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

è una dichiarazione che chiede il compilatore per una serie di dimensioni 5 dei puntatori di caratteri. Hai inizializzato questi puntatori a stringhe letterali, ma per il compilatore, è ancora un array di cinque puntatori.

Quando si passa tale matrice in qsort, la matrice di puntatori decade in un puntatore che punta al primo elemento, in base al parametro di matrice C passando regole.

Pertanto è necessario elaborare un livello di indirezione prima di poter raggiungere gli array di caratteri effettivi che contengono le costanti.

@bodacydo ecco un programma che può spiegare ciò che altri programmatori stanno cercando di trasmettere, ma questo sarebbe nel contesto di "interi"

#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 );
}

Forse è più facile dare un esempio di codice da me. Sto cercando di ordinare un array di TreeNodes e le prime righe del mio aspetto comparatori come:

int compareTreeNode(const void* tt1, const void* tt2) {
   const TreeNode *t1, *t2;
   t1=*(const TreeNode**)tt1;
   t2=*(const TreeNode**)tt2;

Dopo che fate il vostro confronto con T1 e T2.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top