Generisches Vergleichen
Teil des Abschnitts Object Oriented Programming der C-Journey von Coddy — Lektion 52 von 61.
Generische Funktionen wie qsort und bsearch in der Standardbibliothek von C benötigen eine Möglichkeit, Elemente zu vergleichen, ohne deren Typen zu kennen. Die Lösung ist eine Vergleichsfunktion — eine Funktion, die Sie schreiben und die der generische Algorithmus immer dann aufruft, wenn er zwei Elemente vergleichen muss.
Die Standardsignatur für Vergleichsfunktionen ist:
int compare(const void* a, const void* b);Beide Parameter sind const void*, da die generische Funktion nicht weiß, welchen Typ Sie sortieren. Der Rückgabewert folgt einer bestimmten Konvention:
| Rückgabewert | Bedeutung |
|---|---|
| Negativ | a kommt vor b |
| Null | a ist gleich b |
| Positiv | a kommt nach b |
Innerhalb Ihrer Vergleichsfunktion wandeln Sie die void*-Pointer in den tatsächlichen Typ um und vergleichen die Werte. So vergleichen Sie Ganzzahlen:
int compare_ints(const void* a, const void* b) {
int val_a = *(const int*)a;
int val_b = *(const int*)b;
return val_a - val_b;
}Der Subtraktionstrick funktioniert gut für Ganzzahlen: Wenn a kleiner ist, ist das Ergebnis negativ; wenn gleich, Null; wenn größer, positiv. Diese Funktion kann nun an qsort übergeben werden, um ein Ganzzahl-Array in aufsteigender Reihenfolge zu sortieren.
Aufgabe
EinfachSchreiben Sie eine Funktion compare_ints, die zwei Ganzzahlen nach der Standardkonvention für Vergleichsfunktionen vergleicht, wie sie von generischen Algorithmen wie qsort verwendet wird.
Ihre Funktion sollte die beiden Werte vergleichen und ein Ergebnis zurückgeben, das deren Ordnungsbeziehung angibt.
Konvention für den Rückgabewert:
- Geben Sie einen negativen Wert zurück, wenn die erste Ganzzahl vor der zweiten steht (first < second)
- Geben Sie Null zurück, wenn beide Ganzzahlen gleich sind
- Geben Sie einen positiven Wert zurück, wenn die erste Ganzzahl nach der zweiten steht (first > second)
Parameter:
a(int): Die erste zu vergleichende Ganzzahlb(int): Die zweite zu vergleichende Ganzzahl
Rückgabewert: Eine Ganzzahl, die die Ordnung angibt: negativ, wenn a < b, Null, wenn a == b, positiv, wenn a > b.
Hinweis: Der Subtraktionstrick aus der Lektion bietet eine elegante Einzeiler-Lösung.
Spickzettel
Vergleichsfunktionen ermöglichen es generischen Algorithmen wie qsort und bsearch, Elemente zu vergleichen, ohne deren Typen zu kennen.
Die Standardsignatur für Vergleichsfunktionen:
int compare(const void* a, const void* b);Parameter sind const void*, da die generische Funktion den zu sortierenden Typ nicht kennt.
Konvention für Rückgabewerte:
| Rückgabewert | Bedeutung |
|---|---|
| Negativ | a kommt vor b |
| Null | a ist gleich b |
| Positiv | a kommt nach b |
Innerhalb der Vergleichsfunktion werden void*-Pointer in den tatsächlichen Typ umgewandelt (cast) und die Werte verglichen:
int compare_ints(const void* a, const void* b) {
int val_a = *(const int*)a;
int val_b = *(const int*)b;
return val_a - val_b;
}Der Subtraktionstrick funktioniert für Ganzzahlen: Wenn a kleiner ist, ist das Ergebnis negativ; wenn gleich, null; wenn größer, positiv.
Probier es selbst
int compare_ints(int a, int b) {
// Code hier schreiben
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Object Oriented Programming
1Grundlagen der modularen Programmierung
Header-DateienInclude GuardsQuelldateienStatische FunktionenWiederholung: Modularer Taschenrechner4Kapselung
Konzept der Opaque PointersOpaque Structs definierenGetter und SetterValidierung in SetternRückblick: Die geheime Box7Funktionszeiger
Funktionszeiger deklarierenFunktionszeiger aufrufenTypedef für FunktionszeigerFunktionen als Argumente übergebenZusammenfassung: Calculator Dispatch10Generische Container
Wiederholung: Void-PointerGenerischer WrapperGenerisches SwapGenerisches VergleichenWiederholung: Generisches Array2Objekte und Methoden
Structs als ObjekteDer 'Self'-PointerConst-CorrectnessPointer vs. WertHilfsmethodenZusammenfassung: Point Manager5Projekt: Einfaches Bankkonto
Projekt-SetupImplementierung des Kontos3Objekt-Lebenszyklus
Konstruktor-MusterDestruktor-MusterStack-InitialisierungTiefe KopieRückblick: String-Wrapper6Vererbung durch Komposition
Struct-EinbettungDie First-Member-RegelZugriff auf Parent-MemberUpcastingRückblick: Formenhierarchie9Projekt: Formen-Zeichner
ProjektübersichtKreis-Implementierung