Wie erhalte ich das Dateitrennzeichen in Standard-C/C++: / oder \?
Lesezeit: 9 Minuten
Ich möchte eine Funktion schreiben:
inline char separator()
{
/* SOMETHING */
}
die das Dateitrennzeichen des Systems in Standard C/C++/C++11 zurückgibt? (Ich meine Slash oder Backslash, je nach System). Gibt es eine Möglichkeit, dies zu erreichen?
Ich weiß, dass es “Standard C ++” sagt, aber wenn es Ihnen nichts ausmacht, Boost zu verwenden … stackoverflow.com/questions/8384477/…
Wie wichtig ist es? Die Windows-APIs akzeptieren alle sowohl Schrägstrich als auch umgekehrten Schrägstrich als Trennzeichen. cmd.exe ist pingelig; Es verwendet Schrägstriche, um Optionen anzuzeigen, und erfordert daher einen umgekehrten Schrägstrich in Pfaden. Für die Präsentation für Benutzer ist es wahrscheinlich besser, umgekehrte Schrägstriche zu verwenden, aber mit URLs, die Schrägstriche verwenden, sind die Leute wahrscheinlich nicht mehr so darauf fixiert wie früher.
– Jonathan Leffler
19. Oktober 2012 um 10:36 Uhr
@Markieren “Boost ist in Standard-C++ geschrieben, sollte also akzeptabel sein” – Nun, so ist es Qtalso einfach verwenden QDir::separator().toAscii().
– Christian Rau
19. Oktober 2012 um 10:39 Uhr
Aus MSDN: Alle Schrägstriche (/) werden in das Standard-Windows-Trennzeichen, den Backslash (\), konvertiert. Wenn sie vorhanden sind, wird eine Reihe von Schrägstrichen, die auf die ersten beiden Schrägstriche folgen, zu einem einzigen Schrägstrich zusammengefasst.
– mja
4. November 2018 um 14:29 Uhr
Simonc
Ich bin mir nicht sicher, wie ich es anders machen soll, als ifdefs zu überprüfen
Nur eine Anmerkung – Windows unterstützt auch den Schrägstrich (/) als Pfadtrennzeichen.
– Eugene Mayevski ‘Rückruf
19. Oktober 2012 um 9:56 Uhr
Noch ein Hinweis: warum eine Inline-Funktion und nicht eine const char?
– PaperBirdMaster
19. Oktober 2012 um 10:04 Uhr
Ich habe nur in dem vom OP vorgeschlagenen Stil geantwortet. Sie haben Recht, dass a const char wäre genauso gut. Ich werde das der Antwort hinzufügen
– Simonc
19. Oktober 2012 um 10:05 Uhr
@einpoklum Gute Frage. Mein Kommentar war nicht ganz korrekt. Win32-API-Funktionen akzeptieren Schrägstriche als Pfadtrennzeichen und konvertieren sie beim Aufrufen von NT-API-Funktionen in den umgekehrten Schrägstrich (außer bei Pfaden, die mit \\?\ beginnen). Die Details finden Sie auf msdn.microsoft.com/en-us/library/aa365247.aspx .
– Eugene Mayevski ‘Rückruf
26. Januar 2018 um 12:24 Uhr
Übermesser
Wenn Ihr Compiler c++17-Fähigkeiten bietet, können Sie verwenden std::filesystem::path::preferred_separator was je nach Plattform das bevorzugte Trennzeichen ergibt. Unter Windows wäre dies beispielsweise normalerweise der Fall \ während Sie unter Linux erhalten würden /.
Kleines Gejammer, nichts Großes. Die Dokumentation über was preferred_separator sein soll ist nur ein Beispiel; dh unter Windows erhalten Sie a \\ und auf POSIX erhalten Sie a /. Andere Plattformen können andere Ergebnisse liefern.
Für alle, die c++14 verwenden, können Sie std::experimental::filesystem::path::preferred_separator verwenden.
– TheTomer
30. März um 18:18 Uhr
David C.
Diese Frage deutet wirklich auf ein viel schlimmeres Problem hin.
Wenn Sie sich nur für UNIX vs. Winodws und nur für Verzeichnisse und Dateien interessieren, wird das, was Sie bereits gesehen haben, (meistens) funktionieren, aber das allgemeinere Problem, einen Pfadnamen in seine Komponenten einzufügen, ist ein viel hässlicheres Problem. Je nach Plattform kann ein Pfad einen oder mehrere der folgenden Punkte enthalten:
Datenträgerkennung
Liste der Verzeichnisse
Dateiname
Substream innerhalb der Datei
Versionsnummer
Während es dafür Bibliotheken von Drittanbietern gibt (wie verschiedene CPAN-Perl-Module, Boost und andere) und jedes Betriebssystem Systemfunktionen dafür enthält, ist dafür nichts in C integriert, und der C++-Standard hat diese Funktionalität nur erhalten (durch Einbindung das Boost-Modul) im Jahr 2017.
Einige Beispiele dafür, womit eine solche Funktion möglicherweise umgehen muss, sind:
UNIX- und UNIX-ähnliche Systeme verwenden eine Liste von Zeichenfolgen, die durch „https://stackoverflow.com/“-Zeichen getrennt sind, mit einem führenden „https://stackoverflow.com/“, um einen absoluten Pfad anzugeben (im Gegensatz zu einem relativen Pfad). . In einigen Kontexten (wie NFS) kann es auch ein Hostnamen-Präfix geben (mit einem “:”-Trennzeichen).
DOS und von DOS abgeleitete Betriebssysteme (Windows, OS/2 und andere) verwenden “\” als Verzeichnistrennzeichen (wobei die APIs auch “https://stackoverflow.com/” akzeptieren), aber Pfaden können auch Volume-Informationen vorangestellt werden . Dies kann ein Laufwerksbuchstabe (“C:”) oder ein UNC-Freigabename (“\\MYSERVER\SHARE\”) sein. Es gibt zusätzliche Präfixe, um verschiedene Arten von Servern darzustellen, und Suffixe, um nicht standardmäßige Streams innerhalb einer Datei darzustellen.
Macs (Classic Mac OS, Carbon und einige Cocoa-APIs) verwenden “:” als Verzeichnistrennzeichen, wobei der erste Begriff ein Volume-Name und kein Verzeichnisname ist. Mac-Dateien können auch Sub-Streams (“Forks”) enthalten, auf die über den gleichen Namen mit speziellen APIs zugegriffen wird. Dies ist besonders wichtig für die Ressourcengabeldas häufig in klassischer Mac-Software verwendet wird.
Mac OS X macht bei Verwendung der UNIX-APIs im Allgemeinen das, was UNIX-ähnliche Systeme tun, aber sie können auch benannte Substreams (“Forks”) darstellen, indem sie ein “.” gefolgt vom Fork-Namen zum Dateinamen.
Die neuesten Versionen von Cocoa (Mac OS X, iOS usw.) empfehlen aufgrund der ständig zunehmenden Komplexität dieses Problems die Verwendung einer URL-basierten API zur Darstellung von Dateien. Denken Sie an Dinge wie Cloud-basierte Dokumente und andere komplizierte vernetzte Dateisysteme.
Es ist erwähnenswert, dass die C++17-Dateisystembibliothek nicht alle diese Möglichkeiten abdeckt. Das std::filesystem::path besteht aus einem optionalen Stammname (eine Datenträgerkennung), eine optionale Wurzelverzeichnis (um absolute Pfade zu identifizieren) und eine Folge von Dateinamen, die durch Verzeichnistrennzeichen getrennt sind. Dies deckt alles ab, was wahrscheinlich auf UNIX-Plattformen gültig ist, und die meisten Anwendungsfälle für andere Plattformen, ist aber nicht umfassend. Zum Beispiel hat es keine Unterstützung für Substreams (verlässt sich auf das Betriebssystem, um sie irgendwie einem Dateinamen zuzuordnen – was von Mac OS X, aber nicht von klassischem MacOS gemacht wird). Es enthält auch keine Unterstützung für Dateiversionsnummern.
Ich empfehle Ihnen, sich anzusehen, was Sie mit dem Verzeichnistrenner machen möchten (den Basisnamen extrahieren, einen Pfad in eine Liste von Verzeichnissen aufteilen usw.) und eine Funktion dafür zu schreiben. Wenn Sie C++17 verwenden (und sicher sind, dass Ihr Code nicht von einem C++-Compiler vor Version 17 kompiliert wird), können Sie (wahrscheinlich) standardmäßigen C++-Bibliothekscode verwenden, um eine portable Implementierung dieser Funktion zu schreiben. Wenn nicht, muss diese Funktion plattformspezifisch verwendet werden #ifdefs für jede Plattform, die Sie unterstützen werden, mit a #error wenn keine der Bedingungen erfüllt ist, um Sie zu zwingen, Bedingungen für unerwartete Plattformen hinzuzufügen.
Oder verwenden Sie eine Bibliothek eines Drittanbieters (wie Boost), die Funktionen für all dies enthält, wenn dies akzeptabel ist.
Die akzeptierte Antwort funktioniert nicht unter Cygwin. Mit Cygwin kompilierte Programme, die unter Windows ausgeführt werden, können das Windows-Trennzeichen „\“ verwenden, aber es definiert nicht _WIN32 oder ähnliches. Eine modifizierte Lösung, die unter Cygwin funktioniert:
inline char separator()
{
#if defined _WIN32 || defined __CYGWIN__
return '\\';
#else
return "https://stackoverflow.com/";
#endif
}
oder
const char kPathSeparator =
#if defined _WIN32 || defined __CYGWIN__
'\\';
#else
"https://stackoverflow.com/";
#endif
Cygwin erkennt jedoch garantiert ‘/’, so dass dies kein wirkliches Problem sein sollte. Die Antwort funktioniert also einwandfrei – sie verwendet das Zeichen “/” und funktioniert ohne Probleme.
Cygwin erkennt jedoch garantiert ‘/’, so dass dies kein wirkliches Problem sein sollte. Die Antwort funktioniert also einwandfrei – sie verwendet das Zeichen “/” und funktioniert ohne Probleme.
– Paul Stelian
7. August 2020 um 21:07 Uhr
Ich bin überrascht, dass niemand Folgendes angeboten hat. Dies baut ein wenig auf dem auf, was andere hier anbieten.
Obwohl ich in diesem Beispiel versuche, den Namen der ausführbaren Datei, die zur Verwendung ausgeführt wird, dynamisch zu erfassen, wäre es nicht zu schwierig, den Sprung zu machen und dies nach Bedarf erneut anzuwenden.
Windows verwendet Schrägstriche zur Kennzeichnung von Argumenten. Sie könnten das also zuerst im ersten Argument überprüfen argv[0]die den Namen des ausgeführten Programms enthält.
Beachten Sie die folgenden Ergebnisse, wenn der Pfadname vor dem letzten Schrägstrich entfernt und verlassen wird sepd als Dateiname des Programms.
#include <string.h>
#include <stdio.h>
int main(int argc, char *argv[]){
//int a = 1
//int this = (a == 1) ? 20 : 30; //ternary operator
//is a==1 ? If yes then 'this' = 20, or else 'this' = 30
char *sepd = (strrchr(argv[0], '\/') != NULL) ?
strrchr(argv[0], '\/') :
strrchr(argv[0], '\\');
printf("%s\n\n", sepd);
printf("usage: .%s <host> \n\n", sepd);
while (getchar() != '\n');
}
Aber in Wirklichkeit ist dies ziemlich schmutzig, und mit dem jüngsten Schritt von Windows, Bash einzubeziehen (zu diesem Zeitpunkt noch nicht implementiert), kann dies zu unerwarteten oder unerwarteten Ergebnissen führen.
Es ist auch nicht so vernünftig und fehleranfällig wie das, was andere besonders angeboten haben #ifdef _WIN32.
Einige Programme unter Windows werden ebenfalls verwendet - und / kann auf Nicht-Windows-Plattformen verwendet werden. Das ist dir auch nicht garantiert argv[0] überhaupt irgendetwas enthält, und wenn doch, kann es außer dem Namen des Prozesses, der das Programm gestartet hat, möglicherweise etwas anderes enthalten — was möglicherweise nichts mit Ihrem Programm zu tun hat.
– Klarer
19. Juni 2018 um 12:06 Uhr
@Clearer: Sie haben Recht, dass es keine Garantie gibt argv[0] etwas Nützliches haben. Darüber hinaus sind Trennzeichen für Argumente vollständig von der Anwendung abhängig. Während die Befehle von Microsoft verwendet werden / und viele Apps (insbesondere die von Unix portierten) verwenden -können sie buchstäblich alles sein, was der App-Entwickler verwenden möchte.
– David C.
15. September 2020 um 17:02 Uhr
13998300cookie-checkWie erhalte ich das Dateitrennzeichen in Standard-C/C++: / oder \?yes
Ich weiß, dass es “Standard C ++” sagt, aber wenn es Ihnen nichts ausmacht, Boost zu verwenden … stackoverflow.com/questions/8384477/…
– ta.speot.is
19. Oktober 2012 um 9:45 Uhr
Boost ist in Standard-C++ geschrieben und sollte daher akzeptabel sein – siehe besonders boost.org/doc/libs/1_51_0/libs/filesystem/doc/…
– mmmmmm
19. Oktober 2012 um 9:47 Uhr
Wie wichtig ist es? Die Windows-APIs akzeptieren alle sowohl Schrägstrich als auch umgekehrten Schrägstrich als Trennzeichen.
cmd.exe
ist pingelig; Es verwendet Schrägstriche, um Optionen anzuzeigen, und erfordert daher einen umgekehrten Schrägstrich in Pfaden. Für die Präsentation für Benutzer ist es wahrscheinlich besser, umgekehrte Schrägstriche zu verwenden, aber mit URLs, die Schrägstriche verwenden, sind die Leute wahrscheinlich nicht mehr so darauf fixiert wie früher.– Jonathan Leffler
19. Oktober 2012 um 10:36 Uhr
@Markieren “Boost ist in Standard-C++ geschrieben, sollte also akzeptabel sein” – Nun, so ist es Qtalso einfach verwenden
QDir::separator().toAscii()
.– Christian Rau
19. Oktober 2012 um 10:39 Uhr
Aus MSDN: Alle Schrägstriche (
/
) werden in das Standard-Windows-Trennzeichen, den Backslash (\), konvertiert. Wenn sie vorhanden sind, wird eine Reihe von Schrägstrichen, die auf die ersten beiden Schrägstriche folgen, zu einem einzigen Schrägstrich zusammengefasst.– mja
4. November 2018 um 14:29 Uhr