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/…

    – 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


Benutzeravatar von simonc
Simonc

Ich bin mir nicht sicher, wie ich es anders machen soll, als ifdefs zu überprüfen

inline char separator()
{
#ifdef _WIN32
    return '\\';
#else
    return "https://stackoverflow.com/";
#endif
}

oder (wie von PaperBirdMaster vorgeschlagen)

const char kPathSeparator =
#ifdef _WIN32
                            '\\';
#else
                            "https://stackoverflow.com/";
#endif

  • Alle Windows-Versionen definieren __WIN32 ??

    – Jeyaram

    19. Oktober 2012 um 9:45 Uhr

  • 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

Benutzeravatar von Overblade
Ü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 /.

Sehen Dies für mehr Informationen.

  • 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.

    – Klarer

    19. Juni 2018 um 11:51 Uhr


  • Das ist nicht mehr experimentell: en.cppreference.com/w/cpp/filesystem/path

    – Erdferkel

    26. Juli 2021 um 5:04 Uhr

  • 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


Benutzeravatar von David C
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.
  • VMS ist ziemlich kompliziert (https://web.archive.org/web/20160324205714/http://www.djesys.com/vms/freevms/mentor/vms_path.html), aber es hat Komponenten, die ein Volume, einen Verzeichnispfad, eine Datei und eine Dateirevision darstellen.

Es gibt auch viele andere.

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.

Siehe auch Wikipedia-Eintrag zu Path und C++17 std::Dateisystem::Pfad Klasse

http://en.cppreference.com/w/cpp/filesystem

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.

  • Bitte überarbeiten Sie Ihre Antwort im Hinblick darauf, dass C++ a erhält Standard-Dateisystembibliothek in C++17.

    – einpoklum

    26. Januar 2018 um 12:20 Uhr

das kann sowas sein

#if defined(WIN32) || defined(_WIN32) 
#define PATH_SEPARATOR "\\" 
#else 
#define PATH_SEPARATOR "https://stackoverflow.com/" 
#endif 

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.

    – Paul Stelian

    7. August 2020 um 21:07 Uhr


Benutzeravatar von BullyWiiPlaza
BullyWiiPlaza

std::filesystem::path::preferred_separator sollte jetzt als sauber verwendet werden C++17 Bibliotheksfunktion, wie es scheint.

  • 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


1399830cookie-checkWie erhalte ich das Dateitrennzeichen in Standard-C/C++: / oder \?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy