J'aimerais écrire une fonction:
inline char separator()
{
/* SOMETHING */
}
qui renvoie le séparateur de fichiers du système en standard C/C++/C++ 11? (Je veux dire slash ou backslash selon le système). Y a-t-il un moyen d'y parvenir?
Je ne sais pas comment le faire autrement qu'en vérifiant ifdefs
inline char separator()
{
#ifdef _WIN32
return '\\';
#else
return '/';
#endif
}
ou (comme suggéré par PaperBirdMaster)
const char kPathSeparator =
#ifdef _WIN32
'\\';
#else
'/';
#endif
Cette question fait vraiment allusion à un problème beaucoup plus méchant.
Si vous vous souciez simplement d'UNIX et de Winodws et que vous vous souciez uniquement des répertoires et des fichiers, alors ce que vous avez déjà vu fonctionnera (généralement), mais la question plus générique de la jonction d'un nom de chemin d'accès à ses composants est un problème beaucoup plus laid. Selon la plate-forme, un chemin peut inclure un ou plusieurs des éléments suivants:
Bien qu'il existe des bibliothèques tierces (comme divers modules CPAN Perl, Boost et autres) pour cela, et que chaque système d'exploitation en inclut des fonctions système, rien n'est intégré à C pour cela et le standard C++ n'a obtenu que cette fonctionnalité (en incorporant le module Boost) en 2017.
Voici quelques exemples de problèmes pouvant être traités par une telle fonction:
Il y en a beaucoup d'autres aussi.
Il est à noter que la bibliothèque de systèmes de fichiers C++ 17 ne couvre pas toutes ces possibilités. Le std::filesystem::path
consiste en un nom-racine facultatif (un identificateur de volume), un répertoire racine facultatif (pour identifier les chemins absolus) et une séquence de noms de fichiers séparés par des séparateurs de répertoires. Cela couvre tout ce qui est susceptible d'être valable sur les plateformes UNIX et la majorité des cas d'utilisation d'autres plateformes, mais n'est pas complet. Par exemple, il ne prend pas en charge les sous-flux (le système d'exploitation permet de les mapper sur un nom de fichier - ce qui est effectué par Mac OS X mais pas par MacOS classique). Il n’inclut pas non plus la prise en charge des numéros de version de fichier.
Voir aussi Entrée de Wikipedia sur Path et le C++ 17 std :: filesystem :: path class
http://fr.cppreference.com/w/cpp/filesystem
Je vous recommande de regarder ce que vous voulez faire avec le séparateur de répertoire (extraire le nom de base, diviser un chemin d'accès en une liste de répertoires, etc.) et d'écrire une fonction pour le faire. Si vous utilisez C++ 17 (et que vous êtes certain que votre code ne sera pas compilé par un compilateur C++ antérieur à 17), vous pouvez (probablement) utiliser le code de bibliothèque C++ standard pour écrire une implémentation portable de cette fonction. Sinon, cette fonction devra utiliser des #ifdef
s spécifiques à la plate-forme pour chaque plate-forme que vous prendrez en charge, en utilisant un #error
si aucune des conditions n'est remplie, pour vous obliger à ajouter des conditions aux plates-formes inattendues.
Ou utilisez une bibliothèque tierce (comme Boost) qui inclut des fonctions pour tout cela, si cela est acceptable.
ça peut être quelque chose comme ça
#if defined(WIN32) || defined(_WIN32)
#define PATH_SEPARATOR "\\"
#else
#define PATH_SEPARATOR "/"
#endif
La réponse acceptée ne fonctionne pas sous Cygwin. Les programmes compilés par Cygwin fonctionnant sous Windows peuvent utiliser le séparateur de style Windows '\', mais ne définissent pas _WIN32 ou autres. Une solution modifiée qui fonctionne sous Cygwin:
inline char separator()
{
#if defined _WIN32 || defined __CYGWIN__
return '\\';
#else
return '/';
#endif
}
ou
const char kPathSeparator =
#if defined _WIN32 || defined __CYGWIN__
'\\';
#else
'/';
#endif
Si votre compilateur offre déjà des fonctionnalités c ++ 17, vous pouvez utiliser std::experimental::filesystem::path::preferred_separator
qui devrait renvoyer /
ou \
en fonction de votre plateforme.
Voir this pour plus d'informations.
Je suis surpris que personne n'ait offert ce qui suit. Cela s'appuie un peu sur ce que les autres proposent ici.
Bien que, dans cet exemple, j'essaie de saisir dynamiquement le nom de l'exécutable en cours d'utilisation, il ne serait pas trop difficile de faire le saut et de réappliquer cette opération comme vous le souhaitez.
Windows utilise une barre oblique pour désigner les arguments. Vous pouvez donc vérifier cela en premier dans le premier argument argv[0]
, qui contient le nom du programme en cours d'exécution.
Notez les résultats suivants en supprimant le chemin précédent de la dernière barre oblique, en laissant sepd
comme nom de fichier du programme.
#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');
}
Mais dans les faits, il s’agit là d’une situation assez sale et, avec la dernière initiative de Windows visant à inclure Bash (qui n’a pas encore été implémentée), cela peut produire des résultats inattendus ou imprévus.
Ce n’est pas non plus aussi sain d’esprit et insensible aux erreurs que ce que d’autres ont proposé, en particulier #ifdef _WIN32
.