2010-02-04 37 views
24

veo getcwd de C a través de: man 3 cwd¿Hay un C++ equivalente a getcwd?

sospecho C++ tiene una similar, que me podría devolver un std :: string.

En caso afirmativo, ¿cómo se llama y dónde puedo encontrar su documentación?

Gracias!

+4

¿Por qué no simplemente usar 'std :: string cwd = getcwd();' y dejar que el constructor haga su trabajo? – LiraNuna

+0

¿no perderá esa memoria? – anon

+4

¿Tiene memoria de pérdida getcwd() si no la libera? Si es así, debes liberarlo después de crear la cadena, en lugar de liberarla cuando ya no la necesites, y eso es más conveniente. De lo contrario, la inicialización de la cadena no perderá memoria. –

Respuesta

20

Ok, estoy respondiendo aunque ya haya aceptado una respuesta.

Una forma mejor que envolver la llamada getcwd sería usar boost::filesystem, donde obtiene un objeto path de la función current_path(). La biblioteca del sistema de archivos de Boost le permite hacer muchas otras cosas útiles que de otra manera necesitaría hacer un montón de análisis sintáctico de cadenas, como comprobar si existen archivos/directorios, obtener la ruta padre, completar las rutas, etcétera. Compruébalo, también es portátil, lo que probablemente no será mucho de lo que el código de análisis de cadenas usaría.

Actualización (2016): Filesystem se ha publicado como technical specification en 2015, basado en Boost Filesystem v3. Esto significa que ya puede estar disponible con su compilador (por ejemplo, Visual Studio 2015). Para mí también parece probable que se convierta en parte de un futuro estándar de C++ (supongo que C++ 17, pero no conozco el estado actual).

Actualización (2017): El filesystem library se ha fusionado con la norma ISO C++ en C++ 17, por

std::filesystem::current_path(); 
+1

Por supuesto, en algunas situaciones puede que no valga la pena incluir la biblioteca boost :: filesystem solo para obtener el directorio de trabajo actual. Sin embargo, si él/ella está haciendo un montón de cosas del sistema de archivos, entonces también pueden usar impulso para todo. –

+7

¿Por qué cada respuesta aumenta :: este impulso :: eso? – TheRealChx101

+0

@ chx101: No creo que Boost sea siempre la respuesta. Pero en algunos casos lo es, y usar algo que ya existe y hace que su vida sea más fácil suele ser algo bueno. Tenga en cuenta que algunas cosas que ahora están en el estándar C++ provienen de Boost y que Boost Filesystem está programado para su inclusión como una especificación técnica iirc. – villintehaspam

17

std::string 's constructor puede tomar con seguridad un char* como parámetro. Sorprendentemente también hay un windows version.

Editar: en realidad es un poco más complicado:

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

memoria no es un problema - Temp es un búfer basado en pila, y el constructor std :: string hace una copia. Probablemente podrías hacerlo de una vez, pero no creo que el estándar lo garantice.

Sobre la asignación de memoria, a través de POSIX: función

El getcwd() deberá colocar una ruta absoluta del directorio de trabajo actual en el array apuntado por buf, buf y devolver. La ruta copiada a la matriz no debe contener componentes que sean enlaces simbólicos. El argumento de tamaño es el tamaño en bytes de la matriz de caracteres apuntada por el argumento buf. Si buf es un puntero nulo, el comportamiento de getcwd() no está especificado.

+2

Tanto esta respuesta como el comentario de Liranuna usan 'getcwd' como una función sin argumentos, pero la documentación que veo muestra dos parámetros. ¿Estoy leyendo los documentos incorrectos? –

+2

es el char * liberado automáticamente? o esto me da una fuga de memoria? – anon

+0

@anon no, el char * resultante es 'malloc' ed y debería estar' libre' d ​​después de crear una cadena std :: de él. – Bill

3

Todas las funciones C también son funciones C++. Si necesita un std::string, simplemente cree uno a partir del char* que obtiene getcwd para usted.

4

Tendrá que escribir un pequeño envoltorio.

std::string getcwd_string(void) { 
    char buff[PATH_MAX]; 
    getcwd(buff, PATH_MAX); 
    std::string cwd(buff); 
    return cwd; 
} 
+0

Debe usar PATH_MAX en lugar de un número mágico. – Bill

+0

@Bill gracias, aprende algo nuevo todos los días. –

+0

Excelente, gracias! –

11

Vamos a tratar de reescribir esta simple llamada C como 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()); 
     } 
    } 
} 

El hecho es que cuando se ajusta una función de biblioteca en otra función, se debe asumir que toda la funcionalidad debe estar expuesta, porque una biblioteca no sabe cómo se llamará. Por lo tanto, debe manejar los casos de error en lugar de simplemente tragarlos o esperar que no sucedan.

Por lo general, es mejor dejar que el código de cliente llame a la función de biblioteca y solucione el error en ese momento; probablemente el código de cliente no le importa por qué se produjo el error y solo tiene que gestionar el pase/error caso, en lugar de todos los códigos de error.

+1

Hay un error tipográfico. Debería ser '! = 0' en lugar de' == 0' en la quinta línea. – Phantrast

2

que utilizan getcwd() en C de la siguiente manera:

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

El archivo de cabecera es necesaria stdio.h. Cuando uso el compilador de C, funciona perfecto.

Si puedo compilar exactamente el mismo código utilizando el compilador de C++, informa del siguiente mensaje de error:

identifier "getcwd" is undefined 

Entonces incluido unistd.h y compilado con el compilador de C++. Esta vez, todo funciona. Cuando volví al compilador de C, ¡todavía funciona!

Siempre y cuando incluya stdio.h y unistd.h, el código anterior funciona para los compiladores C y C++.

+0

+1 para verificar en ambos compiladores y volver a verificarlo después de los cambios. –

1

También utilicé boost :: filesystem como se indica en otra respuesta anterior. Solo quería agregar que, dado que la función current_path() no devuelve una cadena std ::, debe convertirla.

Esto es lo que hice:

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

Se puede crear una nueva función, que yo prefiero más ligarse a una biblioteca como impulso (a menos que ya está).

std::string getcwd() 
{ 
    char* buff;//automatically cleaned when it exits scope 
    return std::string(getcwd(buff,255)); 
} 
Cuestiones relacionadas