Home > OS >  I'm not making the comparison I am intending to
I'm not making the comparison I am intending to

Time:02-21

I am trying to write a program that compares strings by their length and sorts them with qsort. I have been able to make them sort alphabetically, now I'm trying to sort them by length. What am I doing wrong with my comparison method? I'm unsure about pointers and feel that issue lies there. Thanks

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


int stringCmp(const void *str1, const void *str2); //Function prototype.

int main (int argc, char *argv[])
{
  int i;
  char **arr = malloc(argc * sizeof(char *));
  printf("Original Args:\n");
  for (i = 0; i < argc-1; i  ){
    arr[i] = argv[i 1];
    printf("%s\n",arr[i]);
  }

  qsort(arr, argc-1, sizeof *arr, stringCmp);

  printf("\nSorted Args:\n");
  for (i = 0; i < argc-1; i  ){
    printf("%s\n", arr[i]);
  }
  free (arr);
  return 0;
}

int stringCmp(const void *str1, const void *str2)
{
  return strlen(str1) - strlen(str2);
  // return strcmp(*(char **)str1,*(char**) str2);
}

CodePudding user response:

As with the commented out call to strcmp, the pointers received by the function actually have type char ** so you need to cast to that type.

return strlen(*(char **)str1) - strlen(*(char **)str2);

CodePudding user response:

It seems you need to allocate argc - 1 pointers instead of argc pointers

char **arr = malloc( ( argc - 1 ) * sizeof(char *));

As for the comparison function then it can be defined the following way

int cmp( const void *s1, const void *s2 )
{
    size_t n1 = strlen( *( const char ** )s1 );
    size_t n2 = strlen( *( const char ** )s2 );
    
    return ( n2 < n1 ) - ( n1 < n2 );
}

Here is a demonstration program.

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

int cmp( const void *s1, const void *s2 )
{
    size_t n1 = strlen( *( const char ** )s1 );
    size_t n2 = strlen( *( const char ** )s2 );
    
    return ( n2 < n1 ) - ( n1 < n2 );
}

int main(void) 
{
    char * s[] = { "12345", "1234", "123", "12", "1" };
    const size_t N = sizeof( s ) / sizeof( *s );
    
    for ( size_t i = 0; i < N; i   )
    {
        printf( "%s ", s[i] );
    }
    putchar( '\n' );

    qsort( s, N, sizeof( *s ), cmp );
    
    for ( size_t i = 0; i < N; i   )
    {
        printf( "%s ", s[i] );
    }
    putchar( '\n' );
}

The program output is

12345 1234 123 12 1 
1 12 123 1234 12345 

Pay attention to that to implements the comparison function like

return strlen(*(char **)str1) - strlen(*(char **)str2);

will be incorrect because values of an expression of the unsigned integer type size_t can not be negative. And conversion such a value to the type int results in undefined behavior.

  • Related