Verständnisprobleme bei qsort



  • Hi,

    wie ihr ja wisst, wird der qsort-Funktion ein Zeiger auf eine Funktion übergeben. In meinem Fall vergleicht diese Funktion jeweils 2 Strings. Das ganze soll (laut Buch) ungefähr folgendermaßen aussehen:

    int main(void)
    {
       char *daten[10], puffer[80];
       int count;
    
       /*Einlesen der Array*/
    
       for (count = 0; count < 10; count++)
       {        
          fgets(puffer,80,stdin);      
          puffer[strlen(puffer)-1] = 0;
          daten[count] = malloc(strlen(puffer)+1);    
          strcpy(daten[count], puffer);
       }
    
       qsort(daten, 10, sizeof(daten[0]), vergl);
    
       return 0;
    }
    
    int vergl(const void *s1, const void *s2)
    {
        return (strcmp(*(char **)s1, *(char **)s2));
    }
    

    Mein Problem liegt jetzt bei der Vergleichsfunktion vergl !
    In der Main-Funktion wird ja in jedes Element des Zeigerarrays "daten" ein String gespeichert. Jedes Element zeigt somit auf einen String. Somit zeigt "daten" auf das erste Element der Array, welches wiederum auf einen String zeigt. "daten" ist somit ein Zeiger auf einen Zeiger.
    Soweit so gut...
    Soweit ich das verstanden habe, werden der Funktion "vergl" zwei Zeiger auf die Elemente des Array übergeben. Also müssten der Funktion "vergl" zwei "Zeiger auf einen Zeiger" übergeben werden. Tatsächlich ist hier nur ein einfacher Zeiger auf void.
    Wieso heißt es im Funktionskopf nicht
    int vergl(const void **s1, const void **s2)?
    Der Rest der Funktion würde dann für mich einen Sinn machen:
    Die beiden "Zeiger auf einen Zeiger" werden dann in (char **) gekastet. Dies wird dann dereferenziert, so dass man zwei Strings erhält, die dann durch "strcmp" verglichen werden!
    Kann jemand mir bitte erklären, was in der Vergleichsfunktion genau passiert?
    mfg



  • Heraklit schrieb:

    Soweit ich das verstanden habe, werden der Funktion "vergl" zwei Zeiger auf die Elemente des Array übergeben.

    Soweit richtig.

    Also müssten der Funktion "vergl" zwei "Zeiger auf einen Zeiger" übergeben werden.

    Die Logik versteh ich nicht. Wie kommst Du da drauf?



  • #include <stdio.h>
    #include <stdlib.h>
    
    int mycompare(const void *a, const void *b)
    {
    	int x = (*(int*)a - *(int*)b);
    	return (x>0)-(x<0);
    }
    
    int main()
    {
    	int i;
    	int a[] = {43, 18, 50, 79, 28, 17, 94, 76, 17, 73};
    
    	qsort(a, 10, sizeof(int), mycompare);
    
    	for(i = 0; i < 10; ++i)
    		printf("%d ", a[i]);
    
    	return 0;
    }
    


  • int vergl(const void *s1, const void *s2)
    {
        return (strcmp(*(char **)s1, *(char **)s2));
    }
    

    const void * -> zeiger auf einem Byte im Speicher
    const char * -> zeiger auf einem Zeichen im Speicher

    int vergl(void *s1, void *s2)
    {
        return (strcmp((char *)s1, (char *)s2));
    }
    


  • vergl schrieb:

    int vergl(void *s1, void *s2)
    {
        return (strcmp((char *)s1, (char *)s2));
    }
    

    Die Eintraege sind aber Strings und keine einzelnen Zeichen.



  • Doch doch, das passt schon.
    strcmp vergleicht die char* solange bis ein \0 auftaucht.



  • Nein, die ursprüngliche Funktion ist richtig. Siehe:

    Heraklit schrieb:

    In der Main-Funktion wird ja in jedes Element des Zeigerarrays "daten" ein String gespeichert.

    Aber das ganze hat sich ja scheinbar eh erledigt, da sich der Op ja nicht zurückmeldet.


Anmelden zum Antworten