Array sortieren
-
Hallo,
bin echt am verzweifeln. Ich habe in einem Programm ein Array, das ich gerne sortieren möchte:
struct ARRAY { int n1; String s1; String s2; }; ARRAY Array[1000]; int nElements;
Aus Turbo-C++-Zeiten kenne ich noch die Funktion qsort(). Hier funktionierte das z.B. so:
char *array[1000]; typedef (*fcmp) (const void*, const void*); int cmp(char **e1, char **e2) { return strcmp(*e1,*e2); } qsort(array, z, sizeof(array[0]), (fcmp)cmp);
Ok, hier meine vergeblichen Versuche in Borland C++:
Die Vergleichsfunktion:
int TForm1::Compare(const void *a, const void *b) { ... }
Versuch 1
qsort((void*)Array, nElements, sizeof(Array[0]), Compare);
Ergebnis: E2034 Konvertierung von 'int (* (_closure )(const void *,const void *))(const void *,const void )' nach 'int ()(const void *,const void *)' nicht möglich.
Versuch 2
qsort((void*)Array, nElements, sizeof(Array[0]), &Compare);
Ergebnis: Daselbe
Versuch 3
qsort((void*)Array, nElements, sizeof(Array[0]), (int (*)(const void *,const void *))&Compare);
Ergebnis: Dasselbe
Versuch 4
typedef int (*fcmp)(const void*,const void*); qsort((void*)Array, nElements, sizeof(Array[0]), (fcmp)&Compare);
Ergebnis: Dasselbe, jedoch heißt es nicht mehr "nicht möglich", sondern "nicht zulässig"!
Versuch 5
typedef int (TForm1::*fcmp)(const void*, const void*); qsort((void*)Array, nElements, sizeof(Array[0]), (fcmp)&TForm1::Compare);
Ergebnis: E2034 Konvertierung von 'int (TForm1::*)(const void *,const void )' nach 'int ()(const void *,const void *)' nicht möglich.
Zur Hilfe!
Stefan
-
Stefen B.,
versuch's mal mit dieser Deklaration:
static int TForm1::Compare(const void *a, const void *b)...
-
Danke, ich habe die "Schnapsidee" mit qsort() inzwischen verworfen und eine eigene Sortierfunktion geschrieben, wobei mir aufgefallen ist, daß qsort() auch gar nicht funktioniert hätte, da man die Array-Elemente nicht einfach im Speicher kopieren darf, da sie ja String-Objekte enthalten.
Danke trotzdem,
Stefan
-
Schau mal im Examples-verzeichnis des BCB. Da hats ein Sortierbeispiel als Beispiel für Threads...
-junix
-
Stefan B. schrieb:
Danke, ich habe die "Schnapsidee" mit qsort() inzwischen verworfen ...
Funktioniert aber. Der Trick besteht nur darin, den Sortier-Handler als static zu deklarieren, um den versteckten this-Pointer von Borland zu vermeiden. Alternativ kann man die Funktion natürlich auch global machen. Die Hilfe zu qsort verweist übrigens auf ein einfaches Beispiel.
...da man die Array-Elemente nicht einfach im Speicher kopieren darf, da sie ja String-Objekte enthalten.
Wieso? Erklär mal, was Du meinst.
-
Hallo dschensky,
dschensky schrieb:
Stefan B. schrieb:
Danke, ich habe die "Schnapsidee" mit qsort() inzwischen verworfen ...
Funktioniert aber. Der Trick besteht nur darin, den Sortier-Handler als static zu deklarieren, um den versteckten this-Pointer von Borland zu vermeiden. Alternativ kann man die Funktion natürlich auch global machen. Die Hilfe zu qsort verweist übrigens auf ein einfaches Beispiel.
Ok, werd' ich mir für nächstes Mal vormerken...
...da man die Array-Elemente nicht einfach im Speicher kopieren darf, da sie ja String-Objekte enthalten.
Wieso? Erklär mal, was Du meinst.
Nun ja, ich hatte zuerst eine simple Bubblesort-Routine geschrieben und die einzelnen Array-Elemente mittels memcpy() vertauscht - in etwa so:
memcpy(&TempElement, &Array[i], sizeof(Array[0])); memcpy(&Array[i], &Array[i+1], sizeof(Array[0])); memcpy(&Array[i+1], &TempElement, sizeof(Array[0]));
Leider kam es dadurch beim späteren Zugriff auf einzelne Elemente wie
strTemp = Array[i].String1;
zu Speicherverletzungen. Meine Vermutung war, daß man Speicherbereiche, die Pointer auf AnsiString-Klassen enthalten, nicht einfach mit Low-Level-Funktionen wie memcpy() umkopieren darf, da diese Pointer von der Laufzeitumgebung verwaltet werden. - Kann sein, daß ich da falsch liege, aber nachdem ich statt memcpy() jeden Member des Struct einzeln per Zuweisungsoperator umkopiert habe, also z.B.
TempElement.n1 = Array[i].n1; TempElement.n2 = Array[i].n2; TempElement.s1 = Array[i].s1;
statt
memcpy(&TempElement, &Array[i], sizeof(Array[0]));
funktionierte es. Meine Vermutung, daß qsort() nicht funktioniert hätte, beruht darauf, daß qsort() ähnlich wie memcpy() einfach Speicherbereiche kopiert.
Viele Grüße,
Stefan
-
Stefan B.: Das problem mit den Speicherzuvriffsverletzungen lässt sich umgehen, wenn du deinen Array als Linked-List organisierst. So musst du dann nur Zeigerwerte ändern, statt Elemente umzukopieren.
-junix