qsort
-
Hallo!
Habe ein String array mit 1460 Einträgen (fix).
eine funktion cmp (strings vergleichen),
sowie einen qsort aufruf der mein string array sortieren sollint cmp(const void *p1, const void *p2) { char **s1 = (char **)p1, **s2 = (char **)p2; return strcmp(*s1, *s2); } // main.... char trigram[1460][4]; qsort(&trigram[0], 1460, 4, cmp);
Beim Aufruf von qsort bekomme ich einen Segfault. Was mache ich falsch?
-
Deine Casts sind falsch. Wieso char**? So müsste es gehen (nicht getestet):
int cmp(const void *p1, const void *p2) { typedef char string4[4]; string4 *s1 = (string4*)p1, *s2 = (string4*)p2; /* oder gleich char (*s1)[4] = (char (*)[4])p1 usw. wenn man darauf steht */ return strcmp(*s1, *s2); }
-
Ein char[4] ist nicht das selbe wie ein char*, das ist grob das Problem. Du interpretierst in cmp den String als Zeiger (jetzt unter der Annahme, dass sizeof(char*) == 4, sonst ist das noch ein bisschen wilder), und der endet natürlich im Nirvana.
Was du in diesem speziellen Fall mit fester Stringlänge machen kannst, ist Folgendes:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char trigram[][4] = { "foo", "bar", "baz", "qux", "abc" }; int i; qsort(trigram, 5, 4, (int(*)(void const *, void const *)) strcmp); // Cast, um Compiler ruhigzustellen for(i = 0; i < 5; ++i) { puts(trigram[i]); } return 0; }
-
Danke! Hat pefekt geklappT
-
Das geht auch ordentlich
#include <stdio.h> #include <stdlib.h> #include <string.h> int strcmp_wrap(const void* s1, const void* s2) { return strcmp( s1, s2 ); } int main() { char trigram[][4] = { "foo", "bar", "baz", "qux", "abc" }; int i; qsort(trigram, 5, 4, strcmp_wrap); for(i = 0; i < 5; ++i) { puts(trigram[i]); } return 0; }
-
Könnte mir mal jemand den Cast erklären:
[cpp] int compare(const void *a, const void *b){ return(strcmp(*(const * char *)a, *(const * char *)b); } [/cpp]
Intuitiv würde ich den cast so machen:
[cpp] strcmp((const char *)a, (const char *)b); [/cpp]
-
n0nam333 schrieb:
Könnte mir mal jemand den Cast erklären:
[cpp] int compare(const void *a, const void *b){ return(strcmp(*(const * char *)a, *(const * char *)b); } [/cpp]
Nein. Das funktioniert ja auch nicht. Wo kommt das überhaupt her?
-
camper schrieb:
Das geht auch ordentlich
#include <stdio.h> #include <stdlib.h> #include <string.h> int strcmp_wrap(const void* s1, const void* s2) { return strcmp( s1, s2 ); } int main() { char trigram[][4] = { "foo", "bar", "baz", "qux", "abc" }; int i; qsort(trigram, 5, 4, strcmp_wrap); for(i = 0; i < 5; ++i) { puts(trigram[i]); } return 0; }
genau
qsort(trigram, sizeof(trigram)/sizeof(trigram[0]), sizeof(char*), strcmp_wrap);
-
ochtnunk muss sein schrieb:
genau
qsort(trigram, sizeof(trigram)/sizeof(trigram[0]), sizeof(char*), strcmp_wrap);
Na, Sorgfalt muss aber auch sein.
sizeof(char*) ist in diesem Fall falsch, und sizeof(char[4]) ist immer 4. sizeof(*trigram) ginge.
-
camper schrieb:
n0nam333 schrieb:
Könnte mir mal jemand den Cast erklären:
[cpp] int compare(const void *a, const void *b){ return(strcmp(*(const * char *)a, *(const * char *)b); } [/cpp]
Nein. Das funktioniert ja auch nicht. Wo kommt das überhaupt her?
Ähm, doch der funktioniert. Kannst mir ja mal eine andere Lösung geben und mir die erklären.
-
n0nam333 schrieb:
camper schrieb:
n0nam333 schrieb:
Könnte mir mal jemand den Cast erklären:
[cpp] int compare(const void *a, const void *b){ return(strcmp(*(const * char *)a, *(const * char *)b); } [/cpp]
Nein. Das funktioniert ja auch nicht. Wo kommt das überhaupt her?
Ähm, doch der funktioniert. Kannst mir ja mal eine andere Lösung geben und mir die erklären.
Nein, das funktioniert nicht. Welcher Compiler schluckt das?
-
gcc
-
n0nam333 schrieb:
gcc
Kein neuerer. Und damit meine ich einen der letzten paar Jahre. Welcher soll das schlucken?
edit: Und um die Ursprungfrage nochmal deutlich zu beantworten: Das kann man nicht erklären, außer dass es falsch ist und keinen Sinn macht. Da steht nämlich übersetzt: Caste zu a zu einem Zeiger auf einen char der ein Zeiger auf const ist. Und wie du merkst, ist das ziemlicher Unsinn.
-
Ich behaupte mal ganz dreist, dass kein C-Compiler, ganz gleich welchen Jahrzehnts, das je geschluckt hat. Es gibt stumpf keine sinnvolle Möglichkeit, das zu parsen.
Wenn, wie ich vermute, (const char **) gemeint ist, greift das schon genannte Problem, dass a und b nicht auf Zeiger zeigen -- Arrays sind halt keine Zeiger.