2017-07-17 5 views
0

Dans mon programme, une partie des ressources nécessaires est un répertoire pour stocker les données. Comme c'est la coutume, j'ai décidé de faire ce répertoire ~/.program/. En C++, la bonne façon de rendre ce répertoire (sur les systèmes UNIX) est ce code:Utiliser une variable à l'intérieur d'une chaîne

#include <sys/stat.h> 
#include <unistd.h> 
#include <iostream> 

using namespace std; 

void mkworkdir() 
{ 
    if(stat("~/.program",&st) == 0) 
    { 
     cout << "Creating working directory..." << endl; 
     mkdir("~/.program/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 
     mkdir("~/.program/moredata", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 
    } 

    else 
    { 
     cout << "Working directory found... continuing" << endl; 
    } 
} 

int main() 
{ 
    mkworkdir(); 
    return 0; 
} 

Maintenant, la fiabilité de l'utilisation du ~ dans mkdir("~/.program/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) est discutable au moins, donc ce que je veux vraiment faire est invite pour le nom d'utilisateur, stocker cela dans un string (comme string usern; cin >> usern;), puis faire mkdir("/home/{$USERN}/.program/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) (comme dans shell). Cependant, je n'ai aucune idée de comment obtenir un équivalent de $ USERN dans une chaîne, comme dans, je ne sais pas comment obtenir une construction C++ extensible dans une chaîne. Ce que je veux dire par là, c'est que j'insère n'importe quelle "forme" de variable dans le contenu de cette variable. Je m'excuse si cette question est confuse, je ne peux pas sembler être capable d'expliquer bien ce que c'est exactement ce que je veux.

Alternativement, et de manière beaucoup plus préférable, serait-il possible d'obtenir le nom d'utilisateur sans le demander? (Et le stocker dans une chaîne, bien sûr)

Répondre

4

Vous pouvez utiliser:

std::string usern; 
std::cin >> usern; 
std::string directory = "/home/" + usern + "/.program"; 
mkdir(directory.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 

Une meilleure alternative, l'OMI, est d'utiliser la valeur de l'environnement HOME variable.

char const* home = std::getenv("HOME"); 
if (home == nullptr) 
{ 
    // Deal with problem. 
} 
else 
{ 
    std::string directory = home + std::string("/.program"); 
    mkdir(directory.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 
} 

FWIW, vous pouvez simplifier votre code en créant une fonction make_directory dans votre espace de noms d'application dans laquelle vous pouvez ajouter les détails de vérifier si le répertoire existe, en utilisant les drapeaux à droite, etc.

namespace MyApp 
{ 
    bool directory_exists(std::string const& directory) 
    { 
     struct stat st; 

     // This is simplistic check. It will be a problem 
     // if the entry exists but is not a directory. Further 
     // refinement is needed to deal with that case. 
     return (stat(directory.c_tr(), &st) == 0);  
    } 

    int make_directory(std::string const& directory) 
    { 
     if (directory_exists(directory)) 
     { 
     return 0; 
     } 
     return mkdir(directory.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 
    } 
} 

et puis, vous pouvez simplement MyApp::make_directory dans le reste de votre code.

char const* home = std::getenv("HOME"); 
if (home == nullptr) 
{ 
    // Deal with problem. 
} 
else 
{ 
    std::string directory = home + std::string("/.program"); 
    MyApp::make_directory(directory); 
    MyApp::make_directory(directory + "/moredata"); 
} 
1

Avoir le nom d'utilisateur dans usern, vous pouvez construire la chaîne comme vous le souhaitez:

std::string dir = "/home/" + usern + "/.program/" 

mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 
mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 

Pour obtenir le nom d'utilisateur sans promting l'utilisateur, vous pouvez utiliser getlogin_r()

+0

Si seulement je pouvais marquer deux réponses comme réponses :( –

+0

@DistantGraphics La réponse de Sahu est de loin meilleure, donc pas de soucis. – Ramon