mit dem stringgrid zeichen sortieren
-
hi,
ich schaffe es einfach nich in einem stringgrid zahlen und zeichen zu sortieren,
dank dem FAQ kann ich zahlen sortieren,
http://www.c-plusplus.net/forum/viewtopic-var-t-is-39156.htmlaber sobald ich buchsteben eingebe bekomme ich die fehlermeldung das diese zeichen kein integer ist,
wenn ich aber den code (qsort) anschaue sehe ich das dort strings verglichen werden, oder stimmt das nicht?
könnt mir hinweise geben, dann versuche ich auf die lösung zu kommen,
für jede kommentare offen,mfg
HubiS
void __fastcall TForm1::QuickSortColumn(TStringGrid *grid, int Column, int links, int rechts, bool Desc) { Column = 0; // rechte und linke grenze festlegen int i = links; int j = rechts; // den mittelwert bestimmen (sortierung aufteilen) int m = StrToInt(grid->Cells[Column][(int) ((links + rechts) / 2)]); do { // sortier-reihenfolge festlegen while (Desc ? (StrToInt(grid->Cells[Column][i]) < m) : (StrToInt(grid->Cells[Column][i]) > m)) i++; while (Desc ? (m < StrToInt(grid->Cells[Column][j])) : (m > StrToInt(grid->Cells[Column][j]))) j--; if (i <= j) { // Zeilen tauschen AnsiString tmp; tmp = grid->Rows[i]->CommaText; grid->Rows[i]->CommaText = grid->Rows[j]->CommaText; grid->Rows[j]->CommaText = tmp; i++; j--; } } while (i < j); // rekursiver aufruf if (links < j) QuickSortColumn(grid, Column, links, j, Desc); if (i < rechts) QuickSortColumn(grid, Column, i, rechts, Desc); // damit ich nicht die CheckBox benutze, geht bestimmt einfacher, if (CheckBox1 -> Checked == 0) CheckBox1 -> Checked = 1; else {CheckBox1 -> Checked = 0;} }aufruf mit ->
QuickSortColumn(StringGrid1, StringGrid1 -> Row, StringGrid1->FixedRows, StringGrid1->RowCount - 1, CheckBox1 -> Checked);
-
Hallo
aber sobald ich buchsteben eingebe bekomme ich die fehlermeldung das diese zeichen kein integer ist,
Und was wundert dich daran?
wenn ich aber den code (qsort) anschaue sehe ich das dort strings verglichen werden, oder stimmt das nicht?
Wenn Strings verglichen werden, heißt das doch nicht, das diese in Zahlen umgewandelt werden müßen. Sondern es werden (ums kurz zumachen) die einzelnen Chars nacheinander von links nach rechts verglichen, und diese sind ja integer.
Du kannst/must also Strings genauso wie Zahlen vergleichen.
bis bald
akari
-
wenn ich zB "a" mit "1" (eins) vergleiche bekomme ich in der ausgabe das a größer als 1 ist,
nur mal zum verständnis:
string -> zeichen von null bis Z, auch sonder zeichen,
char -> nur zeichen ohne buchstaben,
int -> nur Zahlenmein quellcode:
void __fastcall TForm1::Button1Click(TObject *Sender) { if (Edit1 -> Text < Edit2 -> Text) Panel1 -> Caption = Edit1 -> Text + " < " + Edit2 -> Text; if (Edit1 -> Text > Edit2 -> Text) Panel1 -> Caption = Edit1 -> Text + " > " + Edit2 -> Text; }kann ich ein stringgrid mit ein edit feld vergleichen, meine jetzt die "bauart",
wenn ich das ändere
StrToInt(grid->Cells[Column][i]) < min
grid->Cells[Column][i] < mtauchen probleme auf,
ist mein ansatz richtig ..??
-
naja du kannst den quicksort entsprechend für dich anpassen und so erweitern, dass du die entsprechenden spalten nach ihrem datentyp sortierst. um es ein weniger portabler für andere bcb-projekte zu machen, kannste auch deinem stringgrid auch über die Object-Eigenschaft nen Wert zuweisen, den du hier beim sortieren ausliest und der die art der daten in der spalte festlegt. dann musst du nicht für jedes stringgrid nen eigenen sortieralgo schreiben.
// m muss natürlich dann auch je nach spalte und sortiertyp unterschiedlich sein! switch (Column) { // Spalte 1 (Strings sortieren) // Spalte 3 case 0 : case 2 : { while (Desc ? AnsiCompareStr(grid->Cells[Column][i], m) < 0 : AnsiCompareStr(grid->Cells[Column][i], m) > 0) i++; while (Desc ? AnsiCompareStr(m, grid->Cells[Column][j]) < 0 : AnsiCompareStr(m, grid->Cells[Column][j]) > 0) j--; break; } // Spalte 2 (Zahlen sortieren) case 1 : { while (Desc ? (StrToInt(grid->Cells[Column][i]) < m) : (StrToInt(grid->Cells[Column][i]) > m)) i++; while (Desc ? (m < StrToInt(grid->Cells[Column][j])) : (m > StrToInt(grid->Cells[Column][j]))) j--; break; } }das sollte zwar funktionieren, ist allerdings nicht wirklich schön.
Wenn es wirklich effizient sein soll (sehr viele Datensätze). Dann schreibst du dir besser einen eigenen Indexsortierer und sortierst jeweils die entsprechende Spalte und passt lediglich die Indizes in einer separaten Liste an. Das ist schnell, denn du sparst die ganzen Zuweisungen und Kopierereien, da du lediglich die Indizes (integer) vertauschst. danach schreibst du die daten gemäß der umsortierten Indexliste wieder in deine Tabelle.
-
also soweit dankr für die infos,
nur stimmt da was net,
ich habe vergessen zu erwähnen das bei mir
Column = 0 ist,weil ich nur die erste spalte sortieren will,
zB:
|_____Film______|__Size__|
|.Matrix........|.700.MB.|
|.23............|.600.MB.|
|.30.über.nacht.|.650.MB.|so will ich meine tabelle benutzen,
wenn jetzt auf film gedrückt wird werden die filme sortiert,deshalb ja auch zahlen und buchstaben,
der rest ist mir erstmal egal,
hier der nicht funktionsfähige modifizierte code
void __fastcall TForm1::QuickSortColumn(TStringGrid *grid, int Column, int links, int rechts, bool Desc) { //Column = 0; // rechte und linke grenze festlegen int i = links; int j = rechts; // den mittelwert bestimmen (sortierung aufteilen) int m = StrToInt(grid->Cells[Column][(int) ((links + rechts) / 2)]); do { // sortier-reihenfolge festlegen // while (Desc ? ((grid->Cells[Column][i]) < m) : (StrToInt(grid->Cells[Column][i]) > m)) i++; // while (Desc ? (m < StrToInt(grid->Cells[Column][j])) : (m > StrToInt(grid->Cells[Column][j]))) j--; // while (Desc ? AnsiCompareStr(grid->Cells[Column][i], m) < 0 : AnsiCompareStr(grid->Cells[Column][i], m) > 0) i++; // while (Desc ? AnsiCompareStr(m, grid->Cells[Column][j]) < 0 : AnsiCompareStr(m, grid->Cells[Column][j]) > 0) j--; // m muss natürlich dann auch je nach spalte und sortiertyp unterschiedlich sein! switch (Column) { // Spalte 1 (Strings sortieren) // Spalte 3 // case 0 : case 0 : { while (Desc ? AnsiCompareStr(grid->Cells[Column][i], m) < 0 : AnsiCompareStr(grid->Cells[Column][i], m) > 0) i++; while (Desc ? AnsiCompareStr(m, grid->Cells[Column][j]) < 0 : AnsiCompareStr(m, grid->Cells[Column][j]) > 0) j--; break; } // Spalte 2 (Zahlen sortieren) case 1 : { while (Desc ? (StrToInt(grid->Cells[Column][i]) < m) : (StrToInt(grid->Cells[Column][i]) > m)) i++; while (Desc ? (m < StrToInt(grid->Cells[Column][j])) : (m > StrToInt(grid->Cells[Column][j]))) j--; break; } } if (i <= j) { // Zeilen tauschen AnsiString tmp; tmp = grid->Rows[i]->CommaText; grid->Rows[i]->CommaText = grid->Rows[j]->CommaText; grid->Rows[j]->CommaText = tmp; i++; j--; } } while (i < j); // rekursiver aufruf if (links < j) QuickSortColumn(grid, Column, links, j, Desc); if (i < rechts) QuickSortColumn(grid, Column, i, rechts, Desc); // damit ich nicht die CheckBox benute, geht bestimmt einfacher, if (CheckBox1 -> Checked == 0) CheckBox1 -> Checked = 1; else {CheckBox1 -> Checked = 0;} }
-
na wenn du nur eine spalte sortieren willst, kannste das geswitche auch weglassen, allerdings muss m (wie schon geschrieben) auch vom Typ AnsiString sein! Also einfach die Konvertierung weglassen.
-
@sunday
ich danke dir für die hilfe,nur habe ich ein problem wenn alles sortiert wird,
weren die zahlen nicht nach der größe 1,3,4,5,... etcsondern wie zeichen behandelt,
a, aa, aaa, b, bb, bbb,
hier die zahlen -> 1, 11, 111, 2, 22, 222, ... etcund bei kombinationen von zeichen und zahlen das gleiche problem auftaucht,
ein bsp.1.: test1, test11, test111, test2, test22, test222, ... etc
bsp.2.: test11, test11, tfst1, tfst2,
hilfe bitte,
mfg
HubiS
void __fastcall TForm1::QuickSortColumn(TStringGrid *grid, int Column, int links, int rechts, bool Desc) { Column = 0; // rechte und linke grenze festlegen int i = links; int j = rechts; // den mittelwert bestimmen (sortierung aufteilen) //int m = StrToInt(grid->Cells[Column][(int) ((links + rechts) / 2)]); AnsiString m = (grid->Cells[Column][((links + rechts) / 2)]); do { // sortier-reihenfolge festlegen // while (Desc ? ((grid->Cells[Column][i]) < m) : (StrToInt(grid->Cells[Column][i]) > m)) i++; // while (Desc ? (m < StrToInt(grid->Cells[Column][j])) : (m > StrToInt(grid->Cells[Column][j]))) j--; // while (Desc ? (StrToInt(grid->Cells[Column][i]) < m) : (StrToInt(grid->Cells[Column][i]) > m)) i++; // while (Desc ? (m < StrToInt(grid->Cells[Column][j])) : (m > StrToInt(grid->Cells[Column][j]))) j--; while (Desc ? AnsiCompareStr(grid->Cells[Column][i], m) < 0 : AnsiCompareStr(grid->Cells[Column][i], m) > 0) i++; while (Desc ? AnsiCompareStr(m, grid->Cells[Column][j]) < 0 : AnsiCompareStr(m, grid->Cells[Column][j]) > 0) j--; if (i <= j) { // Zeilen tauschen AnsiString tmp; tmp = grid->Rows[i]->CommaText; grid->Rows[i]->CommaText = grid->Rows[j]->CommaText; grid->Rows[j]->CommaText = tmp; i++; j--; } } while (i < j); // rekursiver aufruf if (links < j) QuickSortColumn(grid, Column, links, j, Desc); if (i < rechts) QuickSortColumn(grid, Column, i, rechts, Desc); // damit ich nicht die CheckBox benute, geht bestimmt einfacher, if (CheckBox1 -> Checked == 0) CheckBox1 -> Checked = 1; else {CheckBox1 -> Checked = 0;} }
-
Huberts schrieb:
....
nur habe ich ein problem wenn alles sortiert wird,
weren die zahlen nicht nach der größe 1,3,4,5,... etcsondern wie zeichen behandelt,
a, aa, aaa, b, bb, bbb,
hier die zahlen -> 1, 11, 111, 2, 22, 222, ... etcund bei kombinationen von zeichen und zahlen das gleiche problem auftaucht,
ein bsp.1.: test1, test11, test111, test2, test22, test222, ... etc
bsp.2.: test11, test11, tfst1, tfst2,
...Das Ergebniss ist genau so, wie man es bei lexikalischer Sortierung erwartet.
Wenn du Spalten hast, in denen ausschließlich Zahlen stehen, könntest du diese numerisch sortieren, aber bei gemischten Ausdrücken geht das nicht.void __fastcall TForm1::QuickSortColumn(TStringGrid *grid, int Column, int links, int rechts, bool Desc, bool AlphaSort) { if (AlphaSort) ; //deine neue alphanumerische Sortierfunktion else ; //die alte rein numerische Sortierung }Machmal hilft bei lexikalischer Sortierung folgender Workaround: Einfach die Zahl mit Nullen auffüllen, z.B. 01.Lied_1, 02.Lied_2, 12.Lied_12. Aber bei den von dir genannten Beispielen geht das nicht.
-
Am besten ist es wohl, wenn du dir hier deine eigene Vergleichsfunktion schreibst.