que - ¿Hay un equivalente de C++ para getcwd?
lenguaje c++ pdf (8)
El constructor de std::string
puede tomar un char*
como parámetro de forma segura. Sorprendentemente también hay una versión para windows .
Edit: 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("") );
}
La 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 sola vez, pero no creo que el estándar lo garantice.
Sobre la asignación de memoria, a través de POSIX:
La función getcwd () colocará una ruta de acceso absoluta del directorio de trabajo actual en la matriz a la que apunta buf, y devolverá buf. La ruta de acceso copiada a la matriz no contendrá 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.
Veo el getcwd de C a través de: man 3 cwd
Sospecho que C ++ tiene uno similar, que me podría devolver una cadena std :: string.
Si es así, ¿cómo se llama y dónde puedo encontrar su documentación?
¡Gracias!
Intentemos y reescribamos esta simple llamada de 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());
}
}
}
La cuestión es que, al ajustar una función de biblioteca en otra función, debe asumir que toda la funcionalidad debería estar expuesta, porque una biblioteca no sabe cómo se llamará. Así que tienes que manejar los casos de error en lugar de simplemente tragarlos o esperar que no ocurran.
Por lo general, es mejor dejar que el código del cliente simplemente llame a la función de la biblioteca, y lidiar con el error en ese punto; al código del cliente probablemente no le importa por qué ocurrió el error, y solo tiene que manejar el caso de aprobación / falla, en lugar de Todos los códigos de error.
Ok, estoy respondiendo a pesar de que ya ha aceptado una respuesta.
Una forma aún mejor que envolver la llamada getcwd sería usar boost::filesystem , donde se obtiene un objeto de path
de la función current_path()
. La biblioteca del sistema de archivos Boost te permite hacer muchas otras cosas útiles que de lo contrario necesitarías hacer un montón de análisis de cadenas para hacer, como verificar si existen archivos / directorios, obtener la ruta principal, completar rutas, etc. Compruébelo, también es portátil, lo que probablemente no será la mayoría del código de análisis de cadenas que de otro modo se usaría.
Actualización (2016): el sistema de archivos se ha publicado como una especificación técnica en 2015, basado en Boost Filesystem v3. Esto significa que puede estar disponible ya 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 ++ (asumiría C ++ 17, pero no estoy al tanto del estado actual).
Actualización (2017): la biblioteca del sistema de archivos se ha fusionado con ISO C ++ en C ++ 17, para
std::filesystem::current_path();
Podrías crear una nueva función, que preferiría más que enlazar a una biblioteca como boost (a menos que ya lo estés).
std::string getcwd()
{
char* buff;//automatically cleaned when it exits scope
return std::string(getcwd(buff,255));
}
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.
Aquí esta lo que hice:
std::string cwd = boost::filesystem::current_path().generic_string();
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;
}
Todas las funciones de C son también funciones de C ++. Si necesita un std::string
, simplemente cree uno del char*
que getcwd obtenga para usted.
getcwd()
en C de la siguiente manera:
char * cwd;
cwd = (char*) malloc( FILENAME_MAX * sizeof(char) );
getcwd(cwd,FILENAME_MAX);
El archivo de encabezado necesario es stdio.h
. Cuando uso el compilador de C, funciona perfectamente.
Si compilo exactamente el mismo código usando el compilador de C ++, se muestra el siguiente mensaje de error:
identifier "getcwd" is undefined
Luego unistd.h
compilado con el compilador de C ++. Esta vez, todo funciona. Cuando volví al compilador de C, ¡todavía funciona!
Siempre que incluya tanto stdio.h
como unistd.h
, el código anterior funciona para los compiladores C y C ++.