How to sort argv tab with qsort and strcmp?

81 Views Asked by At

My qsort seems to not be sorting anything. When I pass strings to the program it doesn't sort

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int cmpstr(const void *a, const void *b){
    char const *aa = (char const *)a;
    char const *bb = (char const *)b;
    
    return strcmp(aa,bb);
}

int main(int argc, char * argv[]){
    qsort(argv, argc, sizeof(*argv), cmpstr);
    for(int i =0; i < argc; i++)
        printf("%s\n",argv[i]);
}    
2

There are 2 best solutions below

1
Vlad from Moscow On

The comparison function should look like

int cmpstr(const void *a, const void *b){
    char const *aa = *(char const **)a;
    char const *bb = *(char const **)b;
    
    return strcmp(aa,bb);
}

That is the function qosrt passes to the comparison function pointers to elements of the sorted array. In the given code the elements have the type char *. Pointers to elements have the type char **. So to get elements you need to dereference pointers of the type char **.

Here is a demonstration program. The following arguments are supplied to the program

"f" "e" "d" "c" "b" "a"

Within the program I excluded the element argv[0] because the corresponding string can be too long in some systems. argv[0] points to the program name.

#include <stdio.h>
#include <stdlib.h>
#include <string.h> 

int cmpstr( const void *a, const void *b ) {
    char const *aa = *( char const ** )a;
    char const *bb = *( char const ** )b;

    return strcmp( aa, bb );
}

int main( int argc, char * argv[] )
{
    for (int i = 1; i < argc; i++)
    {
        printf( "\"%s\" ", argv[i] );
    }

    putchar( '\n' );

    qsort( argv + 1, argc - 1, sizeof( *argv ), cmpstr );

    for (int i = 1; i < argc; i++)
    {
        printf( "\"%s\" ", argv[i] );
    }

    putchar( '\n' );
}

The program output is

"f" "e" "d" "c" "b" "a"
"a" "b" "c" "d" "e" "f"
0
Ingo Leonhardt On

the compare functions is called with pointers to members of the array to be sorted. In your case, the array members are of type char * so char ** is passed to cmpstr(). So what you have to do is:

int cmpstr(const void *a, const void *b){
    char const **aa = a;
    char const **bb = b;
    
    return strcmp(*aa,*bb);
}