Qsort sorting wrongly

1

My activity and read a phrase and sorted in alphabetical order, but it is giving error

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

int ordena(const void * a, const void * b)
{
   return strcmp((char *)a, (char *)b); 
}

int main(int argc, char** argv)
{
  char **nomes, frase[900], *ponteiro;
  nomes = malloc(sizeof(char*) * 3000);
  int indice, cont = 0, i;
  for(indice = 0; indice < 3000; indice++)
  {
    nomes[indice] = malloc(sizeof(char) * 100);
  }

  scanf("%[^\n]", frase);

  ponteiro = strtok(frase, " ");
  while(ponteiro != NULL)
  {
     strcpy(nomes[cont], ponteiro);
     cont++;
     ponteiro = strtok(NULL, " ");
  }
  qsort((void*)nomes, cont, sizeof(nomes[0]), ordena);
  for(i = 0; i < cont; i++)
  {
    printf("%s\n", nomes[i]);
  }

   return 0;
}

Example of meat orange juice pickle orange pickles

Example of delivery meat orange oranges pickle pickles juice

    
asked by anonymous 23.05.2018 / 00:40

2 answers

4

Your problem is actually quite typical in qsort , which is to forget that the compare function receives pointers to the array values. So if you have an array of ints the compare function gets two int* . In your case if you have an array of char* the function will get two char** , which makes this:

int ordena(const void * a, const void * b)
{
   return strcmp((char *)a, (char *)b);
                     ^----------^ 
}

Do not be correct.

Instead you have to interpret each parameter as a char** and access the value that will be the char* you want:

int ordena(const void * a, const void * b)
{
    char **palavra1 = (char**) a; //interpretar como char**
    char **palavra2 = (char**) b; //interpretar como char**
    return strcmp(*palavra1, *palavra2); //comparar o apontado de cada um
}

With this change the output gives:

carne
laranja
laranja
picles
picles
suco

See the run on Ideone

As a side note, cast for void* on qsort is not necessary, and ends up being simpler and readable without it:

qsort((void*)nomes, cont, sizeof(nomes[0]), ordena);
        ^---este
    
23.05.2018 / 02:30
0

Pay close attention to the deallocation of RAM after use! free on them!

See if this resolves:

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

char** palavras;

int comparador(const void* item1, const void* item2)
{
    char* elemento1 = *(char**)item1;
    char* elemento2 = *(char**)item2;

    return strcmp(elemento1, elemento2);
}

int main()
{
    char palavra[80];
    int qtdPalavras;
    int tamanhoPalavra;
    int i;

    do
    {
        palavras = NULL;

        fflush(stdin);
        printf("Digite a frase (8 para sair): ");

        qtdPalavras = 0;
        do {
            scanf("%s", palavra);
            tamanhoPalavra = strlen(palavra);
            if (*palavra != '8')
            {
                palavras = (char**)realloc(palavras, (qtdPalavras + 1) * sizeof(char*));
                palavras[qtdPalavras] = (char*)malloc((tamanhoPalavra + 1) * sizeof(char));
                strcpy(palavras[qtdPalavras], palavra);
                ++qtdPalavras;
            }
        } while (*palavra != '8');

        if (qtdPalavras)
        {
            printf("Ordenando a lista de palavras...\n");
            qsort(palavras, qtdPalavras, sizeof(char*), comparador);
            printf("Lista ordenada:\n");
            for (i = 0; i < qtdPalavras; ++i)
            {
                printf("%s ", palavras[i]);
            }
            printf("\n");
        }

        for (i = 0; i < qtdPalavras; ++i)
        {
            free(palavras[i]);
        }

        free(palavras);
    } while (qtdPalavras);

    return 0;
}
    
23.05.2018 / 03:01