19 Stimmen

Brauche Hilfe bei der Verwendung von qsort mit einem Array von Strukturen

Jetzt habe ich verschiedene Beispiele gesehen, aber ich verstehe nicht, was sie bedeuten.

Hier ist meine Struktur

typedef struct profil{
    char geschlecht[1];
    double svnr;       
       . . .
} PROFIL;

wo svnr die Sozialversicherungsnummer ist, nach der ich sortieren werde.

Ich weiß, dass Sie eine Vergleichsfunktion benötigen, aber ich weiß nicht, wie ich genau das Richtige finden soll.

36voto

koko.auth Punkte 401

Hier ist ein Beispiel für die Verwendung von qsort für ein Array von Strukturen in C

/* qsort Beispiel */
#include 
#include 

typedef struct {
    int preis;
    int id;
} auftrag;
auftrag liste[6];
int i = 0;

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

  auftrag *auftragA = (auftrag *)a;
  auftrag *auftragB = (auftrag *)b;

  return ( auftragB->preis - auftragA->preis );
}

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

    printf("Vor dem Sortieren\n");
    for(i=0; i<6; i++){ 
        liste[i].preis = rand()%10;
        liste[i].id = i; 
        printf ("Auftrags-ID = %d Preis = %d \n",liste[i].id, liste[i].preis);           
    }
    printf("NACH dem Sortieren\n");
    int n;
    qsort (liste, 6, sizeof(auftrag), vergleichen);
    for (n=0; n<6; n++)
         printf ("Auftrags-ID = %d Preis = %d \n",liste[n].id, liste[n].preis);          
    return 0;
}

Ich hoffe, es hilft

Katerina Dimitris

(alle Grüße an Pitsi)

12voto

Mitch Wheat Punkte 287474

Ihr Soc sollte höchstwahrscheinlich nicht vom Typ double sein, aber hier ist trotzdem ein Beispiel, was eine Vergleichsfunktion zurückgeben muss:

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;
}

Vielen Dank für den Hinweis auf das const void *.

Hier ist ein vollständiges Beispiel (archiviert): Strukturen mit der C qsort() Funktion sortieren

7voto

Jonathan Leffler Punkte 694013

Die strenge Version eines Vergleichers nimmt zwei konstante Zeiger auf void:

int vergleichen(const void *v1, const void *v2)
{
    const struct profil *p1 = v1;
    const struct profil *p2 = v2;
    if (p1->geschlecht > p2->geschlecht)
        return(+1);
    else if (p1->geschlecht < p2->geschlecht)
        return(-1);
    else if (p1->sozialversicherung > p2->sozialversicherung)
        return(+1);
    else if (p1->sozialversicherung < p2->sozialversicherung)
        return(-1);
    else
        return(0);
}

Dies vergleicht zuerst das Geschlechtsfeld und dann das Sozialversicherungsfeld. So behandeln Sie jede mehrteilige Vergleichung.

4voto

chqrlie Punkte 110208

Um das Array zu sortieren, verwenden Sie qsort() und geben Sie eine Vergleichsfunktion.

Hier ist eine Funktion, die das richtige Ergebnis für alle möglichen Werte des price-Members liefert:

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);
}

Notizen:

  • Die einfache Subtraktion von Werten liefert inkorrekte Ergebnisse, wenn der Unterschied nicht in den int-Typ passt. Zum Beispiel können -2 und INT_MAX nicht korrekt mit der Subtraktionsmethode verglichen werden. Dies würde auch nicht für Gleitkommazahlen funktionieren.

  • Die obige Methode kann für alle vergleichbaren Typen verwendet werden, einschließlich double mit Ausnahme von NaN.

Wenn Sie NaN behandeln möchten, hier ist wie Sie sie am Ende gruppieren können:

#include 

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);
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X