Funkcja porównująca słowa do qsorta

1
   1 #include <stdio.h>
   2 #include <stdlib.h>
   3 
   4 int strlen( char *s ) {
   5         char *p= s;
   6         while( *s != '\0' )
   7                 s++;
   8         return s-p;
   9 }
  10 
  11 int strcmp( char *a, char *b ) {
  12         while( *a == *b && *b != '\0' && *a != '\0' ) { /* nadmiarowy! */
  13                 a++;
  14                 b++;
  15         }
  16         return *a - *b;
  17 }
  18 
  19 int fcmp( const void *a, const void *b ) {
  20         char **pa= (char**)a;
  21         char **pb= (char**)b;
  22 
  23         return strlen(*pa) - strlen(*pb);
  24 }
  25 
  26 int main( int argc, char **argv ) {
  27         int i;
  28 
  29         qsort( argv+1, argc-1, sizeof argv[0], fcmp );
  30 
  31         for( i= 0; i < argc; i++ )
  32                 printf( "%s - %d\n", argv[i], strlen( argv[i] ) );
  33 
  34         return 0;
  35 }

Mam tu taki fragment kodu z wykładu, nie rozumiem do końca na jakiej zasadzie działa funkcja fcmp porównująca słowa z linii 19. Czemu wewnątrz niej rzutujemy słowo dane jako argument (wiersz tablicy dwuwymiarowej argv) na char**? W głowie mam taki obraz, że wystarczy rzutowanie na char*, przypisanie również do char* i wtedy mamy dwa wskaźniki na ciągi znaków (słowa), zwracamy strlen(pa) - strlen(pb) (czyli różnica długości wskazywanych ciągów) i tyle, acz wiem że to zła wersja bo daje inne wyniki od oczekiwanych. Zatem czemu wewnątrz fcmp tworzymy dwuwymiarową tablicę, aby operować na jednym słowie?

Będę wdzięczny za każdą pomoc, bo we wtorek mam zaliczenie.

0

porównuje stringi ze względu na długość.

2

ale nie o to pytał — tylko dlaczego jest rzutowanie na char**.
a to dlatego, że qsort oczekuje, że ostatnim parametrem jest funkcja, która przyjmuje dwa parametry typu void*, które są wskaźnikami na porównywane elementy. porównywane elementy są tutaj typu char*, więc wskaźnik na char* to char**.

int fcmp( const void *a, const void *b )

a i b to niestety ale wskaźniki na porównywane teksty, a nie porównywane teksty. Trzeba najpierw rzutować void* na prawidłowy typ (char**), a potem dokonać dereferencji do char* żeby dostać się do właściwych napisów.

Lepiej to widać, gdybyś sortował tablicę int-ów. Wtedy wewnątrz funkcji porównującej musiałbyś rzutować void* na int*, a nie na int.

0

No racja ;) Dziękuje bardzo za pomoc.

1 użytkowników online, w tym zalogowanych: 0, gości: 1