Necesito ayuda para usar qsort con una variedad de estructuras

6 minutos de lectura

avatar de usuario
Julián Hernández

Ahora, he visto varios ejemplos, pero no entiendo lo que significan.

Aquí está mi estructura

typedef struct profile{
    char gender[1];
    double soc;
       . . .
} PROFILE;

donde soc es el número de seguro social que voy a ordenar.

Sé que necesita una función de comparación, pero no sé cómo encontrar exactamente lo que necesito.

  • double parece un tipo bastante absurdo para un número de seguro social. probablemente debería ser char [10] (si desea permitir la entrada de valores no estrictamente numéricos) o uint32_t.

    – R.. GitHub DEJA DE AYUDAR A ICE

    24 de mayo de 2011 a las 4:03

  • No dejes que los detractores te molesten. double puede no ser ideal, pero es perfectamente adecuado para contener un valor entero de 9 dígitos. Al menos no te encontrarás con el problema de las representaciones fraccionarias redondeadas.

    – Mark Ransom

    24 de mayo de 2011 a las 4:11

  • @Mark Ransom: ¡No creo que decir negativo sea el término apropiado para señalar un diseño/código incorrecto! ¡Desde cuándo un número de seguro social tiene una representación fraccionaria!

    – Trigo Mitch

    24 de mayo de 2011 a las 4:13


  • @Mark Ransom: No creo que haya ninguna regla en Stack Overflow que prohíba ofrecer consejos no solicitados sobre temas que no están directamente relacionados con la pregunta. Si lo hay, lo he violado muchas veces. Además, no estoy de acuerdo contigo. El doble definitivamente está mal.

    – JeremyP

    24 de mayo de 2011 a las 14:13

  • @Mark Ransom: Sí, funcionará, pero no tiene mucho sentido, sobre todo si se analizan los requisitos de validación de un SSN de EE. UU. Por cierto, el equivalente británico a un SSN es el número NI que en realidad comienza con dos alfas.

    – JeremyP

    24 mayo 2011 a las 15:34

avatar de usuario
koko.auth

Aquí hay un ejemplo de uso qsort para una matriz de estructuras en C

/* qsort example */
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int price;
    int id;
} order;
order list[6];
int i = 0;

int compare (const void * a, const void * b)
{

  order *orderA = (order *)a;
  order *orderB = (order *)b;

  return ( orderB->price - orderA->price );
}

int main ()
{
    srand ( time(NULL) );

    printf("Before sorting\n");
    for(i=0; i<6; i++){ 
        list[i].price = rand()%10;
        list[i].id = i; 
        printf ("Order id = %d Price = %d \n",list[i].id, list[i].price);           
    }
    printf("AFTER sorting\n");
    int n;
    qsort (list, 6, sizeof(order), compare);
    for (n=0; n<6; n++)
         printf ("Order id = %d Price = %d \n",list[n].id, list[n].price);          
    return 0;
}

Espero eso ayude

katerina dimitris

(todos los saludos a pitsi)

  • Muy útil, especialmente el compare(). 🙂

    – gsamaras

    7 de marzo de 2016 a las 2:01

  • Tu compare la función es incorrecta: la diferencia entre los precios puede ser mayor que el rango de tipo int. Por ejemplo: -3 y INT_MAX produce INT_MAX + 3 por tu expresión que no encaja en tipo intinvoca un comportamiento indefinido y en la mayoría del hardware actual se evalúa como un número negativo, aunque la comparación debería devolver un número positivo.

    – chqrlie

    11/11/2016 a las 19:05

  • Este ordena de mayor a menor. Si desea lo contrario, solo tiene que cambiar orderA y orderB en la expresión de retorno, ¿correcto?

    – Matheus Rotta

    1 de diciembre de 2016 a las 18:56

  • Eso es correcto, es decir, debe cambiarlo a return(orderA->price - orderB->price)

    – volkang

    4 de febrero de 2020 a las 9:12


  • return ( (*(order *)b).price > (*(order *)a).price ? 1 : -1); una línea concisa puede ser más fácil cambiar el orden…

    – LincolnFive

    12 de enero de 2021 a las 3:49

avatar de usuario
trigo mitch

Tu Soc es casi seguro que no debe ser del tipo doublepero de todos modos, aquí hay un ejemplo de lo que debe devolver una función de comparación:

int compare(const void *p1, const void *p2)
{
    const struct profile *elem1 = p1;    
    const struct profile *elem2 = p2;

   if (elem1->soc < elem2->soc)
      return -1;
   else if (elem1->soc > elem2->soc)
      return 1;
   else
      return 0;
}

Gracias por señalar el const void *.

Aquí hay un ejemplo completo (archivado): Clasificación de estructuras con la función C qsort()

  • -1 porque no puedes pasar esto a qsort sin un yeso peludo, los parámetros deben ser consty esto se puede escribir más simplemente como return (int)(elem1->soc - elem2->soc);

    – Chris Lutz

    24 de mayo de 2011 a las 4:32

  • @Mitch: entonces el póster está usando un compilador extraño. Pero arreglaste tu código, así que me retracté de mi voto negativo.

    – Chris Lutz

    24 de mayo de 2011 a las 4:48

  • @ChrisLutz: el sencillo método de resta es incorrecto en el caso general. Vea mi respuesta para ejemplos contrarios.

    – chqrlie

    11 de noviembre de 2016 a las 19:07

  • El artículo de MS ahora se puede encontrar en jeffpar.github.io/kbarchive/kb/073/Q73853 Y observe que la comparación no usa punteros vacíos.

    – Alan Corey

    28/10/2018 a las 22:25

La versión estricta de un comparador toma dos punteros vacíos constantes:

int compare(const void *v1, const void *v2)
{
    const struct profile *p1 = v1;
    const struct profile *p2 = v2;
    if (p1->gender > p2->gender)
        return(+1);
    else if (p1->gender < p2->gender)
        return(-1);
    else if (p1->soc > p2->soc)
        return(+1);
    else if (p1->soc < p2->soc)
        return(-1);
    else
        return(0);
}

Esto compara primero el campo de género, luego el campo soc. Así es como maneja cualquier comparación multiparte.

  • ¡Tu función de comparación es sexista! (También el soc la comparación se puede hacer como return (int)(p1->soc - p2->soc);. El elenco es innecesario si el OP (sanamente) cambia el tipo de soc a una int.)

    – Chris Lutz

    24 de mayo de 2011 a las 4:33


  • @Chris: au contraire: mi función es perfectamente gentil; damas antes que caballeros, ¿no lo saben? El mecanismo de sustracción funciona siempre que no pueda haber desbordamiento; el mecanismo de comparación funciona independientemente.

    –Jonathan Leffler

    24 de mayo de 2011 a las 4:56

  • Descubierto al investigar una pregunta reciente, estoy sorprendido por la sugerencia de @ChrisLutz con su representante. +1 para JL.

    – Veleta

    11 de noviembre de 2016 a las 19:06

avatar de usuario
chqrlie

Para ordenar la matriz, utilice qsort() y pasar una función de comparación.

Aquí hay uno que produce el resultado correcto para todos los valores posibles de la price miembro:

typedef struct profile {
    char gender[1];
    double soc;
    int price;
    ...
} PROFILE;

int compare_price(const void *a, const void *b) {
    const PROFILE *oa = a;
    const PROFILE *ob = b;

    return (oa->price > ob->price) - (oa->price < ob->price);
}

int compare_soc(const void *a, const void *b) {
    const PROFILE *oa = a;
    const PROFILE *ob = b;

    return (oa->soc > ob->soc) - (oa->soc < ob->soc);
}

Notas:

  • la simple resta de valores produce resultados incorrectos si la diferencia no cabe en el int escribe. Por ejemplo -2 y INT_MAX no se puede comparar correctamente con el método de resta. Tampoco funcionaría para valores de punto flotante.

  • el método anterior se puede utilizar para todos los tipos comparables, incluidos double excepto por NaN.

Si desea manejar NaNaquí está cómo agruparlos al final:

#include <math.h>

int compare_soc_nan_at_the_end(const void *a, const void *b) {
    const PROFILE *oa = a;
    const PROFILE *ob = b;

    if (isnan(oa->soc)) {
        return isnan(ob->soc) ? 0 : 1;
    } else
    if (isnan(ob->soc)) {
        return -1;
    } else {
        return (oa->soc > ob->soc) - (oa->soc < ob->soc);
    }
}

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad