usar resueltos leer funciones ejercicios ejemplos declarar como caracteres cadenas cadena arreglo c++ string filenames

resueltos - Cómo obtener la extensión de archivo desde una cadena en C++



funciones de cadenas de caracteres en c++ (24)

¿Es esto demasiado simple de una solución?

#include <iostream> #include <string> int main() { std::string fn = "filename.conf"; if(fn.substr(fn.find_last_of(".") + 1) == "conf") { std::cout << "Yes..." << std::endl; } else { std::cout << "No..." << std::endl; } }

Dada una cadena "filename.conf" , ¿cómo verificar la parte de la extensión?

Necesito una solución multiplataforma.


Alguien más mencionó el impulso, pero solo quería agregar el código real para hacer esto:

#include <boost/filesystem.hpp> using std::string; string texture = foo->GetTextureFilename(); string file_extension = boost::filesystem::extension(texture); cout << "attempting load texture named " << texture << " whose extensions seems to be " << file_extension << endl; // Use JPEG or PNG loader function, or report invalid extension


Aquí hay una función que toma una ruta / nombre de archivo como una cadena y devuelve la extensión como una cadena. Es todo c ++ estándar, y debe funcionar multiplataforma para la mayoría de las plataformas.

A diferencia de otras respuestas aquí, maneja los casos extraños que maneja PathFindExtension de Windows, en función de la documentación de PathFindExtensions.

wstring get_file_extension( wstring filename ) { size_t last_dot_offset = filename.rfind(L''.''); // This assumes your directory separators are either / or / size_t last_dirsep_offset = max( filename.rfind(L''//'), filename.rfind(L''/'') ); // no dot = no extension if( last_dot_offset == wstring::npos ) return L""; // directory separator after last dot = extension of directory, not file. // for example, given C:/temp.old/file_that_has_no_extension we should return "" not "old" if( (last_dirsep_offset != wstring::npos) && (last_dirsep_offset > last_dot_offset) ) return L""; return filename.substr( last_dot_offset + 1 ); }


Asumiendo que tienes acceso a STL:

std::string filename("filename.conf"); std::string::size_type idx; idx = filename.rfind(''.''); if(idx != std::string::npos) { std::string extension = filename.substr(idx+1); } else { // No extension found }

Editar: esta es una solución multiplataforma ya que no mencionó la plataforma. Si está específicamente en Windows, querrá aprovechar las funciones específicas de Windows mencionadas por otros en el hilo.


Buenas respuestas, pero veo que la mayoría tienen algunos problemas: en primer lugar, creo que una buena respuesta debería funcionar para los nombres completos de los archivos que tienen sus encabezados de ruta, también debería funcionar para Linux o Windows o, como se mencionó, debe ser multiplataforma. Para la mayoría de las respuestas; nombres de archivos sin extensión pero una ruta con un nombre de carpeta que incluye punto, la función no devolverá la extensión correcta: ejemplos de algunos casos de prueba podrían ser los siguientes:

const char filename1 = {"C://init.d//doc"}; // => No extention const char filename2 = {"..//doc"}; //relative path name => No extention const char filename3 = {""}; //emputy file name => No extention const char filename4 = {"testing"}; //only single name => No extention const char filename5 = {"tested/k.doc"}; // normal file name => doc const char filename6 = {".."}; // parent folder => No extention const char filename7 = {"/"}; // linux root => No extention const char filename8 = {"/bin/test.d.config/lx.wize.str"}; // ordinary path! => str

La sugerencia de " brian newman " fallará para filename1 y filename4. y la mayoría de las otras respuestas que se basan en el hallazgo inverso fallarán para filename1. Sugiero incluir el siguiente método en su fuente: que es el índice que devuelve la función del primer carácter de extensión o la longitud de la cadena dada si no se encuentra.

size_t find_ext_idx(const char* fileName) { size_t len = strlen(fileName); size_t idx = len-1; for(size_t i = 0; *(fileName+i); i++) { if (*(fileName+i) == ''.'') { idx = i; } else if (*(fileName + i) == ''/'' || *(fileName + i) == ''//') { idx = len - 1; } } return idx+1; }

podría usar el código anterior en su aplicación c ++ como se muestra a continuación:

std::string get_file_ext(const char* fileName) { return std::string(fileName).substr(find_ext_idx(fileName)); }

El último punto en algunos casos la carpeta se asigna al nombre del archivo como argumento e incluye un punto en el nombre de la carpeta. La función devolverá el seguimiento del punto de la carpeta, así que es mejor que el usuario compruebe que el nombre es un nombre de archivo y no una carpeta.


Con C ++ 17 y su std::filesystem::path::extension (la biblioteca es la sucesora de boost :: filesystem) harías tu declaración más expresiva que usando, por ejemplo, std::string .

#include <iostream> #include <filesystem> // C++17 namespace fs = std::filesystem; int main() { fs::path filePath = "my/path/to/myFile.conf"; if (filePath.extension() == ".conf") // Heed the dot. { std::cout << filePath.stem() << " is a valid type."; // Output: "myFile is a valid type." } else { std::cout << filePath.filename() << " is an invalid type."; // Output: e.g. "myFile.cfg is an invalid type" } }

Ver también std::filesystem::path::stem , std::filesystem::path::filename .


Debes asegurarte de que cuides los nombres de los archivos con más de un punto. ejemplo: c:/.directoryname/file.name.with.too.many.dots.ext no sería manejado correctamente por strchr o find.

Mi favorito sería la biblioteca del sistema de archivos boost que tiene una función de extensión (ruta)


En realidad, la forma más fácil es

char* ext; ext = strrchr(filename,''.'')

Una cosa para recordar: si ''.'' no existe en nombre de archivo, ext será NULL .


Esta es una solución que se me ocurrió. Luego, noté que es similar a lo que publicó @serengeor.

Funciona con std::string y find_last_of , pero la idea básica también funcionará si se modifica para usar las matrices char y strrchr . Maneja archivos ocultos y puntos extra que representan el directorio actual. Es plataforma independiente.

string PathGetExtension( string const & path ) { string ext; // Find the last dot, if any. size_t dotIdx = path.find_last_of( "." ); if ( dotIdx != string::npos ) { // Find the last directory separator, if any. size_t dirSepIdx = path.find_last_of( "///" ); // If the dot is at the beginning of the file name, do not treat it as a file extension. // e.g., a hidden file: ".alpha". // This test also incidentally avoids a dot that is really a current directory indicator. // e.g.: "alpha/./bravo" if ( dotIdx > dirSepIdx + 1 ) { ext = path.substr( dotIdx ); } } return ext; }

Prueba de unidad:

int TestPathGetExtension( void ) { int errCount = 0; string tests[][2] = { { "/alpha/bravo.txt", ".txt" }, { "/alpha/.bravo", "" }, { ".alpha", "" }, { "./alpha.txt", ".txt" }, { "alpha/./bravo", "" }, { "alpha/./bravo.txt", ".txt" }, { "./alpha", "" }, { "c://alpha//bravo.net//charlie.txt", ".txt" }, }; int n = sizeof( tests ) / sizeof( tests[0] ); for ( int i = 0; i < n; ++i ) { string ext = PathGetExtension( tests[i][0] ); if ( ext != tests[i][1] ) { ++errCount; } } return errCount; }


Hoy he tropezado con esta pregunta, aunque ya tenía un código de trabajo, descubrí que, en algunos casos, no funcionaría.

Si bien algunas personas ya sugirieron usar algunas bibliotecas externas, prefiero escribir mi propio código para fines de aprendizaje.

Algunas respuestas incluyeron el método que estaba usando en primer lugar (buscando el último "."), Pero recordé que en Linux los archivos / carpetas ocultos comienzan con ".". Entonces, si el archivo de archivo está oculto y no tiene extensión, se tomará el nombre completo del archivo para la extensión. Para evitar eso, escribí este fragmento de código:

bool getFileExtension(const char * dir_separator, const std::string & file, std::string & ext) { std::size_t ext_pos = file.rfind("."); std::size_t dir_pos = file.rfind(dir_separator); if(ext_pos>dir_pos+1) { ext.append(file.begin()+ext_pos,file.end()); return true; } return false; }

No lo he probado completamente, pero creo que debería funcionar.


Intenta usar strstr

char* lastSlash; lastSlash = strstr(filename, ".");


Iría con boost::filesystem::extension pero si no puede usar Boost y solo tiene que verificar la extensión, una solución simple es:

bool ends_with(const std::string &filename, const std::string &ext) { return ext.length() <= filename.length() && std::equal(ext.rbegin(), ext.rend(), filename.rbegin()); } if (ends_with(filename, ".conf")) { /* ... */ }


La mejor manera es no escribir ningún código que lo haga, sino llamar a los métodos existentes. En Windows, el método PathFindExtension es probablemente el más simple.

Entonces, ¿por qué no escribirías la tuya?

Bueno, tome el ejemplo de strrchr, ¿qué sucede cuando usa ese método en la siguiente cadena "c: / program files / AppleGate.Net / readme"? ¿Es ".Net / léame" la extensión? Es fácil escribir algo que funcione para algunos ejemplos de casos, pero puede ser mucho más difícil escribir algo que funcione para todos los casos.


O puedes usar esto:

char *ExtractFileExt(char *FileName) { std::string s = FileName; int Len = s.length(); while(TRUE) { if(FileName[Len] != ''.'') Len--; else { char *Ext = new char[s.length()-Len+1]; for(int a=0; a<s.length()-Len; a++) Ext[a] = FileName[s.length()-(s.length()-Len)+a]; Ext[s.length()-Len] = ''/0''; return Ext; } } }

Este código es multiplataforma


Para cadenas tipo array de char puedes usar esto:

#include <ctype.h> #include <string.h> int main() { char filename[] = "apples.bmp"; char extension[] = ".jpeg"; if(compare_extension(filename, extension) == true) { // ..... } else { // ..... } return 0; } bool compare_extension(char *filename, char *extension) { /* Sanity checks */ if(filename == NULL || extension == NULL) return false; if(strlen(filename) == 0 || strlen(extension) == 0) return false; if(strchr(filename, ''.'') == NULL || strchr(extension, ''.'') == NULL) return false; /* Iterate backwards through respective strings and compare each char one at a time */ for(int i = 0; i < strlen(filename); i++) { if(tolower(filename[strlen(filename) - i - 1]) == tolower(extension[strlen(extension) - i - 1])) { if(i == strlen(extension) - 1) return true; } else break; } return false; }

Puede manejar rutas de archivos además de nombres de archivos. Funciona con C y C ++. Y multiplataforma.


Si considera la extensión como el último punto y los posibles caracteres posteriores, pero solo si no contienen el carácter separador de directorio, la siguiente función devuelve el índice de inicio de la extensión, o -1 si no se encuentra ninguna extensión. Cuando tenga eso, puede hacer lo que quiera, como quitar la extensión, cambiarla, verificarla, etc.

long get_extension_index(string path, char dir_separator = ''/'') { // Look from the end for the first ''.'', // but give up if finding a dir separator char first for(long i = path.length() - 1; i >= 0; --i) { if(path[i] == ''.'') { return i; } if(path[i] == dir_separator) { return -1; } } return -1; }


Si usa bibliotecas de Poco , puede hacer:

#include <Poco/Path.h> ... std::string fileExt = Poco::Path("/home/user/myFile.abc").getExtension(); // == "abc"



Una versión de NET / CLI usando System :: String

System::String^ GetFileExtension(System::String^ FileName) { int Ext=FileName->LastIndexOf(''.''); if( Ext != -1 ) return FileName->Substring(Ext+1); return ""; }


Usé la función PathFindExtension () para saber si es un archivo tif válido o no.

#include <Shlwapi.h> bool A2iAWrapperUtility::isValidImageFile(string imageFile) { char * pStrExtension = ::PathFindExtension(imageFile.c_str()); if (pStrExtension != NULL && strcmp(pStrExtension, ".tif") == 0) { return true; } return false; }


Usando find / rfind de std :: string resuelve ESTE problema, pero si trabajas mucho con rutas, entonces deberías mirar boost :: filesystem :: path, ya que hará que tu código sea mucho más limpio que jugar con índices / iteradores de cadenas sin formato.

Sugiero impulso ya que es una biblioteca de alta calidad, bien probada, (de código abierto y comercial) libre y totalmente portátil.


Utilizo estas dos funciones para obtener la extensión y el nombre de archivo sin extensión :

std::string fileExtension(std::string file){ std::size_t found = file.find_last_of("."); return file.substr(found+1); } std::string fileNameWithoutExtension(std::string file){ std::size_t found = file.find_last_of("."); return file.substr(0,found); }

Y estos enfoques regex para ciertos requisitos adicionales:

std::string fileExtension(std::string file){ std::regex re(".*[^//.]+//.([^//.]+$)"); std::smatch result; if(std::regex_match(file,result,re))return result[1]; else return ""; } std::string fileNameWithoutExtension(std::string file){ std::regex re("(.*[^//.]+)//.[^//.]+$"); std::smatch result; if(std::regex_match(file,result,re))return result[1]; else return file; }

Requisitos adicionales que cumple el método de expresión regular:

  1. Si filename es como .config o algo así, la extensión será una cadena vacía y el nombre de archivo sin extensión será .config .
  2. Si el nombre del archivo no tiene extensión, la extensión será una cadena vacía, el nombre del archivo sin extensión será el nombre del archivo sin cambios.

EDITAR:

Los requisitos adicionales también pueden cumplirse de la siguiente manera:

std::string fileExtension(const std::string& file){ std::string::size_type pos=file.find_last_of(''.''); if(pos!=std::string::npos&&pos!=0)return file.substr(pos+1); else return ""; } std::string fileNameWithoutExtension(const std::string& file){ std::string::size_type pos=file.find_last_of(''.''); if(pos!=std::string::npos&&pos!=0)return file.substr(0,pos); else return file; }

Nota:

Pase solo los nombres de los archivos (no la ruta) en las funciones anteriores.


de hecho, el STL puede hacer esto sin mucho código, le aconsejo que aprenda un poco sobre el STL porque le permite hacer algunas cosas sofisticadas, de todos modos esto es lo que uso.

std::string GetFileExtension(const std::string& FileName) { if(FileName.find_last_of(".") != std::string::npos) return FileName.substr(FileName.find_last_of(".")+1); return ""; }

esta solución siempre devolverá la extensión incluso en cadenas como "this.abcdesmp3" si no puede encontrar la extensión que devolverá "".


_splitpath, _wsplitpath, _splitpath_s, _wsplitpath_w

Creo que esto es solo Windows (Platform SDK)