TStrings sortieren



  • ich habe Dateinamen in einem TStrings, bzw in einer ListBox (LMDExtListBox von LMD-Tools). Leider werden die Dateien dort falsch sortiert. hier ein beispiel:
    121030_102_MeinText_Z1
    121030_102_MeinText_Z10
    121030_102_MeinText_Z11
    121030_102_MeinText_Z12
    121030_102_MeinText_Z1
    121030_102_MeinText_Z2
    ...
    121030_103_MeinText_Z1
    121030_103_MeinText_Z10
    ..usw..

    er soll aber so sortieren:
    121030_102_MeinText_Z1
    121030_102_MeinText_Z2
    121030_102_MeinText_Z3
    121030_102_MeinText_Z4
    121030_102_MeinText_Z6
    121030_102_MeinText_Z7
    121030_102_MeinText_Z8
    121030_102_MeinText_Z9
    121030_102_MeinText_Z10
    121030_102_MeinText_Z11
    121030_102_MeinText_Z12
    121030_103_MeinText_Z1
    ..usw.

    Lass ich mir die Dateien zB in einem OpenDialog anzeigen wird korrekt sortiert.



  • Dafür gibt es in der Shell die Funktion StrCmpLogicalW(), die du in einer Callback-Funktion für TStringList::CustomSort() benutzen kannst.



  • ich arbeite mit dem BCB 5.

    Die Funktion StrCmpLogicalW ist unbekannt. Habe auch schon versucht sie über den Header Shlwapi.h zu inkludieren.

    Edit: Gerade mal nachgesehen in der Shlwapi.h in meinem CBuilder-Verzeichnis. Dort gibt es keine Funktion mit diesem Namen.



  • Im Link von audacia lese ich, daß diese Funktion in der ShellAPI erst seit Windows XP existiert. Da der Builder 5 noch unter Windows 98 Zeiten erschien, kennt er sie nicht.
    Andererseits handelt es sich ja nur um einen Aufruf aus einer dll.
    In der Shlwapi.h vom Builder XE steht da folgende Zeile:

    LWSTDAPI_(int) StrCmpLogicalW(LPCWSTR psz1, LPCWSTR psz2);

    Das scheint mir noch nicht so schwierig.
    Wie man das aber über eine Callback-Funktion für TStringList::CustomSort() benutzen kann, ist schon etwas höhere Mathematik, kann ich so nicht sagen.



  • W. Posur schrieb:

    Wie man das aber über eine Callback-Funktion für TStringList::CustomSort() benutzen kann, ist schon etwas höhere Mathematik, kann ich so nicht sagen.

    Laut Dokumentation übernimmt TStringList::CustomSort() ein Argument vom Typ TStringListSortCompare. Das ist offenbar ein Funktionszeiger:

    typedef int __fastcall (*TStringListSortCompare)(TStringList* List, int Index1, int Index2);
    

    Die Funktion, die man an TStringList::CustomSort() übergeben muß, nimmt also einen Zeiger auf die Stringliste und die Indices der zu vergleichenden Strings entgegen und gibt einen Wert <0, =0 oder >0 zurück, über dessen Bedeutung die Docwiki-Seite zu TStringListSortCompare sich detailliert ausläßt. Um diesen Wert zu bekommen, kann nun StrCmpLogicalW() verwendet werden. Was ist jetzt daran schwierig?



  • das mit der Callback-Funktion bekomme ich hin. Habe es mit einer anderen Sortierfunktion probiert und das funktioniert. Den Code für den Natural Sort habe ich leider nicht, da ich ja die Methode StrCmpLogicalW nicht verwenden kann. Hat jemand für mich die Implementierung dieser Methode bzw eine andere Methode, die mir Liste sortiert?



  • Wieso kannst du die Methode
    StrCmpLogicalW
    nicht verwenden ?
    Muß dein Programm etwa noch mit Windows 98/ME kompatibel sein ?
    Ansonsten ist es doch eine Funktion der Windows-API ab Windows XP. Die Aufrufparameter stehen im Link von audacia.



  • ich verwende unter Windows XP den BCB 5. Wenn ich die shlwapi mit

    #include <Shlwapi.h>
    

    inkludiere und die Funktion über

    lstSorted->CustomSort(ListeSort);
    

    aufrufe erhalte ich diese Fehlermeldung:

    [C++ Fehler] unitMain.cpp(224): E2268 Aufruf der undefinierten Funktion 'StrCmpLogicalW'
    

    hier noch die Callback-Funktion:

    int __fastcall ListeSort(TStringList *list, int Item1, int Item2)
    {
       return StrCmpLogicalW(list->Strings[Item1],list->Strings[Item2]);
    }
    

    Edit: wenn ich im Verzeichnis C:\Programme\Borland\CBuilder5\Include in die shlwapi.h schau gibt es auch die Funktion StrCmpLogicalW nicht. Ich habe vom Builder 10 die shlwapi.h und shlwapi.lib bekommen. Wenn ich die shlwapi.lib dem Projekt hinzufüge und die neue shlwapi.h inkludiere bekomme ich mehrere Fehler wegen fehlender Header usw:

    [C++ Fehler] shlwapi.h(19): E2209 include-Datei 'SpecStrings.h' kann nicht geöffnet werden.
    [C++ Fehler] shlwapi.h(21): E2209 include-Datei 'shtypes.h' kann nicht geöffnet werden.
    [C++ Fehler] shlwapi.h(98): E2189 extern-Variable kann nicht initialisiert werden.
    [C++ Fehler] shlwapi.h(98): E2451 Undefiniertes Symbol '__in'
    [C++ Fehler] shlwapi.h(98): E2293 ) erwartet
    [C++ Fehler] shlwapi.h(99): E2189 extern-Variable kann nicht initialisiert werden.
    [C++ Fehler] shlwapi.h(99): E2293 ) erwartet
    [C++ Fehler] shlwapi.h(100): E2189 extern-Variable kann nicht initialisiert werden.
    [C++ Fehler] shlwapi.h(100): E2293 ) erwartet
    [C++ Fehler] shlwapi.h(101): E2189 extern-Variable kann nicht initialisiert werden.
    [C++ Fehler] shlwapi.h(101): E2293 ) erwartet
    [C++ Fehler] shlwapi.h(133): E2189 extern-Variable kann nicht initialisiert werden.
    [C++ Fehler] shlwapi.h(133): E2293 ) erwartet
    [C++ Fehler] shlwapi.h(135): E2189 extern-Variable kann nicht initialisiert werden.
    [C++ Fehler] shlwapi.h(135): E2108 Ungültige Verwendung von typedef 'DWORD'
    [C++ Fehler] shlwapi.h(135): E2293 ) erwartet
    [C++ Fehler] shlwapi.h(136): E2189 extern-Variable kann nicht initialisiert werden.
    [C++ Fehler] shlwapi.h(136): E2108 Ungültige Verwendung von typedef 'LONGLONG'
    [C++ Fehler] shlwapi.h(136): E2293 ) erwartet
    [C++ Fehler] shlwapi.h(137): E2189 extern-Variable kann nicht initialisiert werden.
    [C++ Fehler] shlwapi.h(137): E2108 Ungültige Verwendung von typedef 'LONGLONG'
    [C++ Fehler] shlwapi.h(137): E2293 ) erwartet
    [C++ Fehler] shlwapi.h(138): E2189 extern-Variable kann nicht initialisiert werden.
    [C++ Fehler] shlwapi.h(138): E2108 Ungültige Verwendung von typedef 'LONGLONG'
    [C++ Fehler] shlwapi.h(138): E2293 ) erwartet
    [C++ Fehler] shlwapi.h(138): E2228 Zu viele Fehlermeldungen oder Warnungen
    

    an die beiden fehlenden Header vom 10er Builder komm ich jetzt auch nicht ran.



  • Also, im MSDN steht ja das die Funktion in der Shlwapi.dll zu finden ist.
    Die DLL befindet sich unter Windows\system32.
    Hab mir die DLL gerade mal mit dem Dependency Walker angeschaut, und da wird die Funktion StrCmpLogicalW exportiert.

    Ich würde jetzt einfach sagen DLL dynamisch laden und die Funktion mit den Parametern verwenden welche im MSDN stehen, bzw Bau dir einfach ein Wrapper Funktion.



  • Hallo zusammen,

    ich habe momentan ein so ähnliches Problem.
    Ich möchte Zahlen als String dargestellt sortieren.
    Die Funktion StrCmpLogicalW() funktioniert leider nicht mit negativen Zahlen.
    Kennt jemand alternativen?

    Konvertierung von String nach int bzw double ist leider nicht wirklich eine Alternative, da die Strings auch Buchstaben enthalten können.

    MfG Stephan





  • natsort schrieb:

    http://sourcefrog.net/projects/natsort/

    Auf den ersten Blick ganz gut, allerdings werden die Nachkommastellen nicht berücksichtigt und die Sortierung von positiven und negativen Zahlen stimmt auch nicht überein.
    Im Prinzip das gleiche Ergebnis wie bei StrCmpLogicalW();


Anmelden zum Antworten