Nur mal eine Frage: Wenn ich mit readdir() mir alle Verzeichnisse bzw Dateien auflisten lasse erscheinen die aufsteigend nach Name. Ist das so korrekt bzw. kann ich die Sortierung irgendwie beeinflussen ? (Win 7, C)
Seiten des API ist keine Reihenfolge definiert. Sie hängt also vom Filesystem ab. Das kann bei NTFS anders aussehen als bei FAT.
Joachim D. schrieb: > erscheinen die aufsteigend nach Name. Wahrscheinlich wurden sie in dieser Reihenfolge reinkopiert. Wenn du genaueres wissen willst kopier noch eine rein, die mit A anfängt, und schau nach ob sie am Anfang oder am Ende steht. Abgesehen davon: entweder das API sagt ausdrücklich, dass die Reihenfolge sortiert ist und wie, oder man muss selbst sortieren. Dass es eine "physikalische" Reihenfolge gibt, ist aus dem Bewusstsein geraten, da die nirgends mehr angezeigt wird. Meines Wissens bietet der Windows-Explorer garkeine unsortierte Anzeige an, auch DIR nicht, jedenfalls ist sortiert Voreinstellung. Georg
Filesystem wie NTFS mit innerer Baumstruktur haben ein inhärentes Sortierverhalten, was aber der internen Zeichencodierung folgt, nicht der je nach Sprache grammatikalisch gewünschten. Andere Filesysteme wie FAT speichern völlig unsortiert.
:
Bearbeitet durch User
Joachim D. schrieb: > Also doch Einlesen und dann qsort ;) Da gibt's doch ne elegante Möglichkeit... :-)
1 | #include <iostream> |
2 | #include <filesystem> |
3 | #include <vector> |
4 | #include <string> |
5 | #include <iterator> |
6 | #include <algorithm> |
7 | |
8 | int main () { |
9 | std::vector<std::string> files; |
10 | std::transform (std::filesystem::directory_iterator("/home"), std::filesystem::directory_iterator(), std::back_inserter (files), [] (auto& e) { return e.path (); } ); |
11 | std::sort (files.begin (), files.end ()); |
12 | |
13 | std::copy (files.begin (), files.end (), std::ostream_iterator<std::string> (std::cout, "\n")); |
14 | std::cout << std::endl; |
15 | }
|
Kompilieren / linken mit -lstdc++fs -std=c++17
Dr. Sommer schrieb: > Da gibt's doch ne elegante Möglichkeit... :-) Außer das der TO nach Win7 und C gefragt hat. Warum muss eigentlich jeder Thread hier dar nach C Fragt damit enden das irgendwer mit C++ um die Ecke kommt? Ja C++ ist eine schöne Mächtige Sprache und wenn man die Wahl hat sollte man C++ nehmen, aber die Wahl hat nicht jeder vielleicht ist der TO in einen Legacy Projekt, oder es gibt Vertrags rechtliche gründe C zu nehmen und schon ist die Lösung nicht mehr elegant.
imonbln schrieb: > Außer das der TO nach Win7 und C gefragt hat. Das geht auch unter Win7. Und die meisten C-Compiler liefern auch C++-Compiler mit. Vielleicht kompiliert er ja sogar unwissenderweise mit C++, da z.B. die C-Unterstützung von MSVC nicht so dolle ist. Und vielleicht hat er ja Interesse daran, das Programm kompakter zu machen. Und vielleicht interessiert es ja auch andere Leser.
Ich kompiliere wissenderweise mit einem C-Compiler. Mit C++ habe ich bis jetzt ein Projekt mit dem Gnu-Compiler durchgezogen. Der C-Code zum Laden eines Verzeichnisses mit anschließendem Sortieren ist auch nicht "größer" wie das C++-Bespiel. C ist erheblich weniger Tipparbeit.
Joachim D. schrieb: > C ist erheblich weniger Tipparbeit. Hm, echt? Wie schaffst du das? Ich komm in C auf die doppelte Anzahl Zeichen:
1 | #include <sys/types.h> |
2 | #include <dirent.h> |
3 | #include <stdlib.h> |
4 | #include <stdio.h> |
5 | #include <string.h> |
6 | |
7 | int cmp (const void* a, const void* b) { |
8 | return strcmp (a, b); |
9 | }
|
10 | |
11 | int main () { |
12 | DIR* dirHandle = opendir("/home"); |
13 | if (!dirHandle) return 1; |
14 | |
15 | int ret = 0; |
16 | size_t curSize = 32, read = 0; |
17 | char** files = (char**) malloc (sizeof(char*) * curSize); |
18 | if (!files) { |
19 | ret = 1; |
20 | goto closeDir; |
21 | }
|
22 | memset (files, 0, sizeof(char*) * curSize); |
23 | |
24 | struct dirent* dirEntry; |
25 | while ((dirEntry = readdir(dirHandle)) != NULL) { |
26 | if (read >= curSize) { |
27 | char** newBlock; |
28 | curSize *= 2; |
29 | if ((newBlock = realloc (files, curSize * sizeof (char*))) == NULL) { |
30 | ret = 1; |
31 | goto freePaths; |
32 | }
|
33 | files = newBlock; |
34 | }
|
35 | if ((files[read] = strdup (dirEntry->d_name)) == NULL) { |
36 | ret = 1; |
37 | goto freePaths; |
38 | } else { |
39 | ++read; |
40 | }
|
41 | }
|
42 | ret = 0; |
43 | qsort (files, read, sizeof (char*), cmp); |
44 | |
45 | for (size_t i = 0; i < read; ++i) { |
46 | puts (files [i]); |
47 | }
|
48 | |
49 | freePaths:
|
50 | for (size_t i = 0; i < read; ++i) free (files [i]); |
51 | free (files); |
52 | |
53 | closeDir:
|
54 | closedir(dirHandle); |
55 | |
56 | return ret; |
57 | }
|
Mache aber auch nicht mehr viel C. Was gibt's noch für Abkürzungen?
Dr. Sommer schrieb: > int main () { > std::vector<std::string> files; ..... Elegant ist ja was Anderes, alleine vom Äußeren, den ewigen Wiederholungen. Trotzdem danke, kann ja sein dass man beruflich mal mit dem Rotz zu tun bekommt dann ist man schon abgehärtet.
:
Wiederhergestellt durch Moderator
@Sommer Also das liegt nicht an dir, ist auch meine persönliche Meinung, aber recht viel hässlicher kann eine Programmiersprache nicht sein mit ewigen Pfaden zu irgendwelchen Libraries mit tausend Sonderzeichen, die stechen förmlich ins Auge.
tutut schrieb: > Also das liegt nicht an dir, ist auch meine persönliche Meinung, aber > recht viel hässlicher kann eine Programmiersprache nicht sein mit ewigen > Pfaden zu irgendwelchen Libraries Wenn das dein Hauptproblem ist, schreib einfach "using std::string;" etc. Ist letztlich in vielen Sprachen so außer C, wo alle Bezeichner aller Bibliotheken im selben Namespace sind und kollidieren können.
Joachim D. schrieb: > Na, das mache ich etwas kompakter ;) Na, da bin ich gespannt! So sieht der "Rotz" aus wenn man sich mittels "using" die Bezeichner abkürzt:
1 | #include <iostream> |
2 | #include <filesystem> |
3 | #include <vector> |
4 | #include <string> |
5 | #include <iterator> |
6 | #include <algorithm> |
7 | |
8 | using std::vector; |
9 | using std::string; |
10 | using std::transform; |
11 | using std::filesystem::directory_iterator; |
12 | using std::back_inserter; |
13 | using std::sort; |
14 | using std::copy; |
15 | using std::ostream_iterator; |
16 | using std::cout; |
17 | |
18 | int main () { |
19 | vector<string> files; |
20 | transform (directory_iterator ("/home"), directory_iterator (), back_inserter (files), [] (auto& e) { return e.path (); } ); |
21 | sort (files.begin (), files.end ()); |
22 | |
23 | copy (files.begin (), files.end (), ostream_iterator<string> (cout, "\n")); |
24 | }
|
Also wenn schon kompakter und nicht C, wärs dann damit: ;-) print join "\n", sort </home/*>;
:
Bearbeitet durch User
Aber aber, Perl ist doch pöse, wegen seiner schrecklichen Syntax. :-))
Wie groß sind denn die binaries beider Varianten (also ohne daß jetzt wesentliche Teile in ingendwelchen dlls ausgelagert sind)?
Jörg W. schrieb: > Aber aber, Perl ist doch pöse, wegen seiner schrecklichen Syntax. :-)) Eben. Genau wie C und C++. :-))
Dr. Sommer schrieb:
1 | copy (files.begin (), files.end (), ostream_iterator<string> (cout, "\n")); |
Ich hab immer den Eindruck, dass copy mit ostream_iterator hauptsächlich verwendet wird, weil es Leute irgendwie für cool halten, dass man das kann. In der Praxis würde ich aber einfach schreiben:
1 | for (auto& file: files) cout << file << '\n'; |
Und ich finde auch, dass statt dem hier:
1 | transform (directory_iterator ("/home"), directory_iterator (), back_inserter (files), [] (auto& e) { return e.path (); } ); |
das folgende vielleicht uncooler, dafür aber kürzer und lesbarer ist:
1 | for (auto& e: diretory_iterator("/home")) files.push_back(e.path()); |
Dr. Sommer schrieb: > using std::vector; > using std::string; > using std ... ... Danke, schon besser. Tu uns den Gefallen und mach das ab jetzt immer so (ich hab des offenen schon deine Beiträge gelesen und nix verstanden)
nunja aber die Vergleichsfunktion mit strcmp() hat einen blöden Nachteil.. strcmp() vergleicht Zeichenweise und bricht ab beim Ende der Zeichenkette oder bei ersten Zeichen das ungleich ist ab und liefert größer/kleiner zurück. Es vergleicht plump die Values und berücksichtigt nicht der Wertung der Zeichen. CcAazZ usw.. unter dem Aspekt kommt nicht das gewünschte Ergebnis zu Stande wenn man in die ASCII Tabelle schaut... alphasort (const void *a, const void *b) schon ob das portable ist weiß ich jetzt nicht.. Die Frage ist noch nicht beantwortet :)
:
Bearbeitet durch User
Marco H. schrieb: > alphasort (const void *a, const void *b) schon ab das portable ist weiß > nicht.. Ist das nicht seit 20 Jahren obsolet? Oder verstehe ich das falsch und das ist doch voll Unicode kompatibel? ;-) Ernsthaft, dieses Bytearrygeraffel (Um Strings zu speichern) sollte man langsam mal lassen. Programme die intern nicht komplett Unicode nutzen sind schon lange nicht mehr zeitgemäß und machen nur Ärger.
Dr. Sommer schrieb: > Ich komm in C auf die doppelte Anzahl Zeichen Kein Wunder, du kannst es auch nicht. Dr. Sommer schrieb: > Mache aber auch nicht mehr viel C Offenkundig mehr in Basic, den gotos und Krückencode nach zu urteilen. Wieso else nach goto kommt ist auch zweifelhaft. Und seit wann man in C eine Deklaration wie "int ret" mitten im Code haben darf auch.
test schrieb: > Programme die intern nicht komplett Unicode nutzen sind schon lange > nicht mehr zeitgemäß und machen nur Ärger Welchen Unicode ? UTF8, UTF16, 16 oder 32 bit wchar_t, big endian oder small endian ?
MaWin schrieb: > Kein Wunder, du kannst es auch nicht. Wer kann das schon richtig. MaWin schrieb: > Offenkundig mehr in Basic, den gotos und Krückencode nach zu urteilen. goto Ist in C halt das was strukturierter Fehler Behandlung am Nächsten kommt. Richtige Sprachen haben dafür Exceptions. MaWin schrieb: > Wieso else nach goto kommt ist auch zweifelhaft. } übersehen? MaWin schrieb: > Und seit wann man in C eine Deklaration wie "int ret" mitten im Code > haben darf auch. Seit 20 Jahren (C99).
wollte nur darauf hinweisen das der Sachverhalt nicht so ganz einfach ist ;) Dann strcoll() https://docs.microsoft.com/de-de/cpp/c-runtime-library/reference/strcoll-wcscoll-mbscoll-strcoll-l-wcscoll-l-mbscoll-l?view=vs-2019 Goto ist aus vielerlei Hinsicht unschön... außer in der Linux Kernel Programmierung. Bei Treibern wird es benutzt um bei Fehlern aufzuräumen. Außerdem gibt es kein Problem was sich nicht ohne Goto lösen lässt.
:
Bearbeitet durch User
MaWin schrieb: > Welchen Unicode ? UTF8, UTF16, 16 oder 32 bit wchar_t, big endian oder > small endian ? Unicode nennt man die verbindliche Zuordnung von Nummern zu Symbolbedeutungen. UTF8 usw. sind Methoden um diese Nummern in einer Bytefolge zu speichern. Du vermischt hier also vollkommen unterschiedliche Dinge miteinander.
Das heißt, du willst also den Speicherverbrauch des Programms für Strings schlicht vervierfachen und 32-Bit Codepoints speichern. Richtig? Oder doch lieber UTF8, UTF16BE, UTF16LE oder was anderes nutzen?
S. R. schrieb: > Das heißt, du willst also den Speicherverbrauch des Programms für > Strings schlicht vervierfachen und 32-Bit Codepoints speichern. Richtig? Der Speicherverbrauch vervierfacht sich nur, wenn das Programm ausschließlich aus Strings besteht und weder irgendwelchen Programmcode, noch andere Ressourcen wie z.B. Grafiken enthält. Tatsächlich ist es in einigen Sprachen üblich, UCS-4 für Strings zu verwenden. > Oder doch lieber UTF8, UTF16BE, UTF16LE oder was anderes nutzen? Dann muss man allerdings zwischen der Länge des Strings im Bezug auf Speicher und im Bezug auf Anzahl Zeichen unterscheiden. Man müsste dann also entweder jedesmal mühsam die Zahl an Zeichen ausrechnen, wenn man sie braucht, oder man müsste beide Werte speichern und bei jeder Änderung aktualisieren. Das lohnt sich auf einem aktuellen PC nicht, nur um ein paar Dutzend Kilobytes RAM zu sparen.
S. R. schrieb: > Das heißt, du willst also den Speicherverbrauch des Programms für > Strings schlicht vervierfachen und 32-Bit Codepoints speichern. Richtig? Nur mal so aus Neugier... Was machst du in deinem "ein String ist ja nur ein Byte Array" Programm, wenn dein Nutzer z.B. eine Datei mit Japanischen Zeichen im Dateinamen hat? Abstürzen lassen oder eine Meldung zeigen die den Nutzer auffordert, derartig seltsame Sachen zu lassen?
Die eigentliche Frage bei Unicode ist doch: Was ist die korrekte Reihenfolge von drei Dateien mit den Namen "?", "文件" und "♫"? Marco H. schrieb: > Außerdem gibt es kein Problem was sich nicht ohne Goto lösen lässt. Korrekt, aber für das strukturierte Aufräumen nach Fehlern eignet es sich überraschend gut. Außer Beschimpfungen zu meinem C-Code wurde bisher kein besserer gezeigt. Daher gehe ich mal davon aus, dass es doch nicht signifikant besser geht.
Dr. Sommer schrieb: > Die eigentliche Frage bei Unicode ist doch: Was ist die korrekte > Reihenfolge von drei Dateien mit den Namen "?", "文件" und "♫"? Das coole an Unicode ist das uns das komplett egal sein kann. Man ruft die Unicode konforme Sortierfunktion auf und gut ist. Die kümmert sich auch darum so etwas korrekt zu sortieren. -- A‐B A.B A‑B -- Der erste und der dritte Eintrag dieser Liste sind unterschiedlich (sie unterscheiden sich im mittleren Zeichen), aber man möchte sie bei einer alphabetischen Sortierung trotzdem als identisch betrachten.
test schrieb: > Man ruft die Unicode konforme Sortierfunktion auf und gut ist. Die ist dann aber ziemlich komplex. libicu gibt es z.B. dafür.
Dr. Sommer schrieb: > Die ist dann aber ziemlich komplex. Und? Wofür hat man das Betriebssystem auf der Kiste? Und der Arduino oder das Linux auf dem Toaster darf gerne weiterhin 8-Bit ASCII nutzen, da hat jeder Verständnis für.
test schrieb: > Und der Arduino oder das Linux auf dem Toaster darf gerne weiterhin > 8-Bit ASCII nutzen, da hat jeder Verständnis für. Ein ordentlicher Toaster basiert auf BSD und beherrscht selbstverständlich moderne Zeichensätze.
test schrieb: > Und? Wofür hat man das Betriebssystem auf der Kiste? Nix Und, das ist schon gut so. Man sollte aber eben im Hinterkopf behalten dass da viel Komplexität drin steckt.
Rolf M. schrieb: >> Das heißt, du willst also den Speicherverbrauch des Programms >> für Strings schlicht vervierfachen und 32-Bit Codepoints speichern. >> Richtig? > > Der Speicherverbrauch vervierfacht sich nur, wenn das Programm > ausschließlich aus Strings besteht und weder irgendwelchen > Programmcode, noch andere Ressourcen wie z.B. Grafiken enthält. Darum schrieb ich "für Strings". Muss ich sowas noch hervorheben oder jedesmal einen Vortrag mit allen Details ausarbeitern? > Tatsächlich ist es in einigen Sprachen üblich, > UCS-4 für Strings zu verwenden. Die meisten mir bekannten Sprachen verwenden allerdings utf8. Die JVM nutzt intern UCS16, kann also ohnehin nur die BMP (Basic Multilingual Plane). test schrieb: > Nur mal so aus Neugier... Was machst du in deinem "ein String ist > ja nur ein Byte Array" Programm, wenn dein Nutzer z.B. eine Datei > mit Japanischen Zeichen im Dateinamen hat? Nix. Ich gebe die an das Betriebssystem weiter. Warum sollte ich den Dateinamen in einen String wandeln wollen? Solange ich da nix rumparsen muss, kann mir der Name doch egal sein. > Abstürzen lassen oder eine Meldung zeigen die den Nutzer > auffordert, derartig seltsame Sachen zu lassen? Dazu müsste ich erstmal rauskriegen, dass der Dateiname irgendwie seltsam ist. Dafür zusätzlichen Code in mein Programm tun? Nee, danke. Im Übrigen ist utf8 dafür wesentlich besser geeignet als UCS32. Platzsparender für fast alle relevanten Anwendungsfälle sowieso.
S. R. schrieb: > Solange ich da nix rumparsen > muss, kann mir der Name doch egal sein. Zum Sortieren muss man das aber, wofür man dann Unicode und UTF-XY beherrschen muss.
Dr. Sommer schrieb: >> Solange ich da nix rumparsen >> muss, kann mir der Name doch egal sein. > > Zum Sortieren muss man das aber, wofür man > dann Unicode und UTF-XY beherrschen muss. Stimmt, aber das überlasse ich in der Regel auch dem Betriebssystem. :-D
Dr. Sommer schrieb: > test schrieb: > Und? Wofür hat man das Betriebssystem auf der Kiste? > > Nix Und, das ist schon gut so. Man sollte aber eben im Hinterkopf > behalten dass da viel Komplexität drin steckt. Ja, ist ja auch ein extrem komplexes Problem. Genau wie Datum/Uhrzeit/Zeitpunkte. Wenn man damit zu tun hat... Das ist quasi ein unlösbares Problem *). Aber man kann es wenigstens versuchen, aber es ist halt extrem komplex. Nur gut das alle brauchbaren Sprachen da entsprechenden Funktionen mitliefern (die halbwegs brauchbar sind). Da schnell mal selbst was zusammenzufummeln geht üblicherweise schief. *) Wenn man einen Zeitpunkt (Datum und Uhrzeit) und einen Ort hat, dann braucht es eine ziemlich komplexe Datenbank um rauszufinden wie lange es her war. Es gibt Schaltsekunden, Länder ändern ihre Sommer-/Winterzeit Regeln und sie ändern ihre Zeitzonen. Und wieviel Zeit ist zwischen dem 28.10.2018 2:30Uhr (Deutschland) und jetzt vergangen? ;-)
test schrieb: > Genau wie Datum/Uhrzeit/Zeitpunkte. Wenn man damit zu tun hat... Das ist > quasi ein unlösbares Problem *). Aber man kann es wenigstens versuchen, > aber es ist halt extrem komplex. Oh ja... Damit hatte ich auch schon viel Spaß. S. R. schrieb: > Stimmt, aber das überlasse ich in der Regel auch dem Betriebssystem. :-D Welche Betriebssysteme haben denn nativ Unicode-Sortierfunktionen? Und sind die dann im Kernel implementiert?
Dr. Sommer schrieb: >> Stimmt, aber das überlasse ich in der Regel auch dem Betriebssystem. > Welche Betriebssysteme haben denn nativ Unicode-Sortierfunktionen? Wenn ich eine Dialogbox aufmache, um den Nutzer eine Datei auswählen zu lassen, ist mir die Sortierung relativ egal. In der Regel kann der Nutzer sogar selbst aussuchen, was er gern hätte. Textprogramme bekommen ihre Dateinamen bei mir in der Regel direkt übergeben. Wenn dann ein open() fehlschlägt, weder mein Problem noch ein katastrophales Ereignis. Dr. Sommer schrieb: > Und sind die dann im Kernel implementiert? Nö, aber ziemlich sicher im verwendeten Toolkit.
S. R. schrieb: > Wenn ich eine Dialogbox aufmache, um den Nutzer eine Datei auswählen zu > lassen, ist mir die Sortierung relativ egal. Du hast wohl noch nie eine grosse Directory gesehen. Dir als Entwickler glaube ich das. Testszenarien bei Entwicklern sind eigentlich immer schön übersichtlich. Fluchen tut ja auch nicht der Entwickler, sondern der Anwender. > In der Regel kann der > Nutzer sogar selbst aussuchen, was er gern hätte. Glücklicherweise ja. Es gibt aber leider Software, in der das nicht möglich ist. Das kann recht unangenehm auffallen.
:
Bearbeitet durch User
A. K. schrieb: >> Wenn ich eine Dialogbox aufmache, um den Nutzer eine Datei auswählen zu >> lassen, ist mir die Sortierung relativ egal. > Du hast wohl noch nie eine grosse Directory gesehen. Doch, aber in der Regel habe ich die selbst verursacht und kann damit einigermaßen umgehen. Notfalls mit "rm -rf". :-) A. K. schrieb: > Testszenarien bei Entwicklern sind eigentlich immer schön > übersichtlich. Fluchen tut ja auch nicht der Entwickler, > sondern der Anwender. Ich frage mich gerade, welches Szenario du gerade im Hinterkopf hast. :-) Wenn ich 10.000 Dateien in einem Ordner habe, wie soll meine Software es dem Benutzer denn einfacher machen, eine Datei auszusuchen? Der Standard-Dialog ist jedenfalls wesentlich besser getestet und sollte besser funktionieren als eine von mir zusammengefrickelte Alternative.
S. R. schrieb: > Der Standard-Dialog i Wenn du den benutzt ist's ja gut. Der kann ja auch sortieren. S. R. schrieb: > Ich frage mich gerade, welches Szenario du gerade im Hinterkopf hast. > :-) Leute die alles nach "Eigene Dateien" speichern. Die finden dann Sachen nur nach dem "zuletzt geändert" Datum. Ok, danach zu sortieren ist einfach. Manche benennen auch ihre Ordner "1. Privat", "2. Arbeit", usw und erwarten dass die dann auch immer entsprechend sortiert sind.
S. R. schrieb: >>> Wenn ich eine Dialogbox aufmache, um den Nutzer eine Datei auswählen zu >>> lassen, ist mir die Sortierung relativ egal. > > Standard-Dialog ist jedenfalls wesentlich besser getestet und sollte > besser funktionieren als eine von mir zusammengefrickelte Alternative. Das ist ja auch meist der richtige Ansatz. Eine chronologisch statt namentlich sortierte Listbox mit 50 Einträgen, wie z.B. in der VMware Netzwerk-Auswahl, ist der falsche.
:
Bearbeitet durch User
Dr. Sommer schrieb: > Welche Betriebssysteme haben denn nativ Unicode-Sortierfunktionen? Und > sind die dann im Kernel implementiert? IIRC Windows (macht Sinn, Windows selber braucht das ja auch selbst), aber vermutlich gehört so etwas auch bei Linux und Apple zum Lieferumfang. Wobei es mir persönlich erstmal egal ist ob meine Entwicklungsumgebung die Betriebssystemfunktionen kapselt oder es selbst macht.
S. R. schrieb: > --SCHNIPP-- > Die meisten mir bekannten Sprachen verwenden allerdings utf8. > Die JVM nutzt intern UCS16, kann also ohnehin nur die BMP (Basic > Multilingual Plane). > --SCHNIPP-- Surrogate-Paare. Damit kommt man auch in die anderen Bereiche rüber ===> https://de.wikipedia.org/wiki/UTF-16 Abschnitt Kodierung
Tom G. schrieb: > Surrogate-Paare. Oh, danke für den Hinweis. Also die Nachteile von UTF8 und UCS-2 vereint.
Dr. Sommer schrieb: > Außer Beschimpfungen zu meinem C-Code wurde bisher kein besserer > gezeigt. Daher gehe ich mal davon aus, dass es doch nicht signifikant > besser geht.
1 | #define _DEFAULT_SOURCE
|
2 | #include <dirent.h> |
3 | #include <stdio.h> |
4 | #include <stdlib.h> |
5 | |
6 | int
|
7 | main(void) |
8 | {
|
9 | struct dirent **namelist; |
10 | int n; |
11 | |
12 | n = scandir(".", &namelist, NULL, alphasort); |
13 | if (n == -1) { |
14 | perror("scandir"); |
15 | exit(EXIT_FAILURE); |
16 | }
|
17 | |
18 | while (n--) { |
19 | printf("%s\n", namelist[n]->d_name); |
20 | free(namelist[n]); |
21 | }
|
22 | free(namelist); |
23 | |
24 | exit(EXIT_SUCCESS); |
25 | }
|
Mit Fnmatch sind auch ausgefallene Sortierungen möglich.. Ob das poartable ist weiß ich nicht..
1 | static int filter_match(const struct dirent *pDirent){ |
2 | |
3 | if(fnmatch(LOG_FILENAME"*", pDirent->d_name, 0) == 0 && pDirent->d_type == DT_REG)return 1; |
4 | |
5 | return 0; |
6 | }
|
hier mal ein einfacher filter welcher mit versionsort(), mir meine logfiles sortiert so das ich herausfinden kann welches das ältere ist um dies dann zu löschen ;) Der Platzhalter "*" Filter -> test0.log test1.log usw...
:
Bearbeitet durch User
Ah danke, diese Möglichkeiten kannte ich noch nicht. Wüsste aber nicht, warum mein C Code so schlecht sein sollte nur weil er das klassische readdir benutzt. Der C++ Code ist übrigens Standard-C++ und damit portabel.
Es wird noch komplizierter ;) scandir() hat einen blöden Nachteil.. zumindest unter Linux, wird ein doppel pointer vom type struct dirent erwartet. Diese Struktur enthält nur Informationen zum namen und type. Keine Attribute, size,Description,time etc. was aber genau so vom Interesse wäre wie der Name. Also müsste man das Array mit Hilfe von qsort() und stat() erneut sortieren. Ich frage mich gerade zu solchen Problemen müsste es doch Bibliotheken geben? Kennt jemand welche ?
Marco H. schrieb: > Keine Attribute, size,Description,time Weil dies unter Posix-Umgebungen Eigenschaften des jeweiligen Objektes sind, nicht von dessen Verzeichniseintrag. Es benötigt also in jedem Falle ohnehin die Indirektion, aus dem Verzeichniseintrag das Objekt zu ermitteln, um an dessen Eigenschaften zu gelangen. Wozu aber benötigt man beim Sortieren der Anzeige denn die Objektattribute?
Marco H. schrieb: > Diese Struktur enthält nur Informationen zum namen und type. > Keine Attribute, size,Description,time etc. was aber genau so vom > Interesse wäre wie der Name. Und das hat einen soliden Grund. Viele Filesysteme unterscheiden zwischen der Information in der Directory und der Information zum eigentlichen File (Inode). Muss der opendir-API nur die Information aus der Directory abliefern, geht es sehr schnell. Muss er jedoch auch die Information aus den Inodes mitliefern, muss für jedes einzelne File ein eigener Disk-Zugriff auf die Inode-Information erfolgen. Unix/Linux-Prinzip: Keep it simple. Den stat()-Aufruf für die Inode-Information kann der Nutzer des APIs genauso gut selber anfügen, wenn er sie benötigt.
:
Bearbeitet durch User
Das war mir bewusst, ich wollte damit nur hinweisen das der Aufwand etwas steigt ;) Aber sehr gut erklärt Danke. Wenn funktioniert sieht das dann so aus :)
Marco H. schrieb: > Wenn funktioniert sieht das dann so aus :) Ich würde solche Listen ja bevorzugt case-insensitiv sortieren, also erst alles nach Kleinbuchstaben wandeln, dann sortieren (und die Originale anzeigen). "F" vor "7" vor "t" ist eher unintuitiv.
Also ich arbeite auch viel mit readdir(). Es wurde ja schon gesagt, das
readdir() die Namen in der Reihenfolge liefert, wie das Dateisystem sie
gespeichert hat.
Welche zusätzlichen Daten readdir() liefert oder liefern kann, hängt vom
Betriebssystem und von Dateisystem ab. Bei Ubuntu Linux und dem
Dateisystem ext4 kann man z.B. aus dem vollen schöpfen. Aber auch da
bekommt man manchmal als Ergebnis DT_UNKNOWN, nämlich bei einigen
Netzwerkfreigaben. da muss man dann trotzdem stat() bemühen.
> Ich würde solche Listen ja bevorzugt case-insensitiv sortieren,...
Das ist zumindest unter Linux nicht die beste Idee, da das Dateisystem
da keine Unterschiede macht. Dazu kommt dann noch, das man bei der
Sortierung evtl. noch spezielle Eigenheiten der Sprache berücksichtigen
möchte, damit öäüß richtig einsortiert werden.
Aber möglicherweise ist scandir() eine Alternative (wenn es auf dem
Zielsystem verfügbar ist). Da könnte man die Sortierung beeinflussen.
Manfred M. schrieb: >> Ich würde solche Listen ja bevorzugt case-insensitiv sortieren,... > Das ist zumindest unter Linux nicht die beste Idee, da das > Dateisystem da keine Unterschiede macht. Das Dateisystem unterscheidet zwischen Groß- und Kleinschreibung, aber deswegen muss es die Sortierung in der Anzeige ja nicht tun. Schau mal in die Ausgabe von "ls", denn die sortiert (zumindest bei mir) ohne Berücksichtigung der Groß-/Kleinschreibung. > Dazu kommt dann noch, das man bei der Sortierung evtl. noch > spezielle Eigenheiten der Sprache berücksichtigen möchte, > damit öäüß richtig einsortiert werden. Das sowieso. Aber wenn man schon Unicode implementiert (hat), dann kann man auch gleich locale-aware sortieren. Zumal selbst gleiche Zeichen unterschiedlich sortiert werden (dt. "ö"=="o", sv. "ö"==letzter Buchstabe, dk/no. "ö"=="ø"==vorletzter Buchstabe).
S. R. schrieb: > Schau mal in die Ausgabe von "ls", denn die sortiert (zumindest bei mir) > ohne Berücksichtigung der Groß-/Kleinschreibung. Hängt stark von der locale ab.
1 | $ env LC_COLLATE=C ls |
2 | AbCDe Bdda abcde bodec Æbedc |
3 | $ env LC_COLLATE=de_DE.UTF-8 ls |
4 | abcde AbCDe Æbedc Bdda bodec |
5 | $ env LC_COLLATE=da_DK.UTF-8 ls |
6 | abcde AbCDe Bdda bodec Æbedc |
Klassisch wurde die ASCIIbetische Sortierung auf UNIX-Systemen durchgeführt. Deshalb sind manche Filenamen wie z.B. Makefile oder README groß geschrieben - damit sie zuerst angezeigt werden.
Beim Makefile kommt noch dazu, dass "makefile" Vorrang vor "Makefile" hat, sodass man durch Kopieren auf die klein geschriebene Variante schnell eine eigene Modifikation durchführen kann.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.