web-dev-qa-db-fra.com

Existe-t-il un équivalent C ++ à getcwd?

Je vois le getcwd de C via: man 3 cwd

Je soupçonne que C++ en a un similaire, qui pourrait me renvoyer une chaîne std ::.

Si oui, comment s'appelle-t-il et où puis-je trouver sa documentation?

Merci!

32
anon

D'accord, je réponds même si vous avez déjà accepté une réponse.

Un meilleur moyen que d'encapsuler l'appel getcwd serait d'utiliser boost :: filesystem , où vous obtenez un objet path à partir de la fonction current_path(). La bibliothèque de système de fichiers Boost vous permet de faire beaucoup d'autres choses utiles que vous auriez autrement besoin de faire beaucoup d'analyses de chaînes, comme vérifier si des fichiers/répertoires existent, obtenir le chemin parent, rendre les chemins complets, etc. Vérifiez-le, il est également portable - ce que beaucoup de code d'analyse de chaîne que l'on utiliserait autrement ne le sera probablement pas.

Mise à jour (2016): Le système de fichiers a été publié en tant que spécification technique en 2015, basé sur Boost Filesystem v3. Cela signifie qu'il peut déjà être disponible avec votre compilateur (par exemple Visual Studio 2015). Il me semble également probable qu'il fera partie d'une future norme C++ (je suppose C++ 17, mais je ne connais pas l'état actuel).

Mise à jour (2017): La bibliothèque du système de fichiers a été fusionnée avec ISO C++ en C++ 17, pour

std::filesystem::current_path();
25
villintehaspam

Le constructeur de std::string Peut prendre en toute sécurité un char* Comme paramètre. Étonnamment, il y a aussi version Windows .

Edit: en fait c'est un peu plus compliqué:

std::string get_working_path()
{
   char temp[MAXPATHLEN];
   return ( getcwd(temp, sizeof(temp)) ? std::string( temp ) : std::string("") );
}

La mémoire n'est pas un problème - temp est un tampon basé sur la pile, et le constructeur std :: string effectue une copie. Vous pourriez probablement le faire en une seule fois, mais je ne pense pas que la norme le garantirait.

À propos de l'allocation de mémoire, via POSIX:

La fonction getcwd () doit placer un chemin d'accès absolu du répertoire de travail courant dans le tableau pointé par buf et retourner buf. Le chemin d'accès copié dans le tableau ne doit contenir aucun composant qui soit un lien symbolique. L'argument taille est la taille en octets du tableau de caractères pointé par l'argument buf. Si buf est un pointeur nul, le comportement de getcwd () n'est pas spécifié.

21
Kornel Kisielewicz

Essayons de réécrire ce simple appel C en C++:

std::string get_working_path()
{
    char temp [ PATH_MAX ];

    if ( getcwd(temp, PATH_MAX) != 0) 
        return std::string ( temp );

    int error = errno;

    switch ( error ) {
        // EINVAL can't happen - size argument > 0

        // PATH_MAX includes the terminating nul, 
        // so ERANGE should not be returned

        case EACCES:
            throw std::runtime_error("Access denied");

        case ENOMEM:
            // I'm not sure whether this can happen or not 
            throw std::runtime_error("Insufficient storage");

        default: {
            std::ostringstream str;
            str << "Unrecognised error" << error;
            throw std::runtime_error(str.str());
        }
    }
}

Le fait est que lorsque vous encapsulez une fonction de bibliothèque dans une autre fonction, vous devez supposer que toutes les fonctionnalités doivent être exposées, car une bibliothèque ne sait pas ce qui l'appellera. Vous devez donc gérer les cas d'erreur plutôt que de simplement les avaler ou espérer qu'ils ne se produiront pas.

Il est généralement préférable de laisser le code client appeler simplement la fonction de bibliothèque et de traiter l'erreur à ce stade - le code client ne se soucie probablement pas de la raison de l'erreur, et n'a donc qu'à gérer le cas de réussite/échec, plutôt que tous les codes d'erreur.

12
Pete Kirkham

Vous aurez juste besoin d'écrire un petit wrapper.

std::string getcwd_string( void ) {
   char buff[PATH_MAX];
   getcwd( buff, PATH_MAX );
   std::string cwd( buff );
   return cwd;
}
6
Brian Gianforcaro

Toutes les fonctions C sont également des fonctions C++. Si vous avez besoin d'un std::string, créez-en un à partir du char* que getcwd obtient pour vous.

3
Rob Kennedy

J'ai utilisé getcwd() en C de la manière suivante:

char * cwd;
cwd = (char*) malloc( FILENAME_MAX * sizeof(char) );
getcwd(cwd,FILENAME_MAX);

Le fichier d'en-tête nécessaire est stdio.h. Lorsque j'utilise le compilateur C, cela fonctionne parfaitement.

Si je compile exactement le même code à l'aide du compilateur C++, il signale le message d'erreur suivant:

identifier "getcwd" is undefined

Ensuite, j'ai inclus unistd.h et compilé avec le compilateur C++. Cette fois, tout fonctionne. Quand je suis revenu au compilateur C, cela fonctionne toujours!

Tant que vous incluez les deux stdio.h et unistd.h, le code ci-dessus fonctionne pour les compilateurs C ET C++.

3
Zhongming Qu

J'ai également utilisé boost :: filesystem comme indiqué dans une autre réponse ci-dessus. Je voulais juste ajouter que puisque la fonction current_path () ne retourne pas de chaîne std ::, vous devez la convertir.

Voici ce que j'ai fait:

std::string cwd = boost::filesystem::current_path().generic_string();
1
crecre