Как получить основание имени файла из пути? - PullRequest
3 голосов
/ 02 апреля 2011

Я хочу извлечь имя файла const char * из пути к файлу const char *.Я пытался с регулярным выражением, но не смог:

const char* currentLoadedFile = "D:\files\file.lua";
char fileName[256];
if (sscanf(currentLoadedFile, "%*[^\\]\\%[^.].lua", fileName)) {
return (const char*)fileName; // WILL RETURN "D:\files\file!!
}

Проблема в том, что будет возвращено "D: \ files \ file", а не нужный файл "(примечание: без" .lua ")

Ответы [ 8 ]

15 голосов
/ 02 апреля 2011

А как насчет использования std :: string?например,

  std::string path("d:\\dir\\subdir\\file.ext");
  std::string filename;

  size_t pos = path.find_last_of("\\");
  if(pos != std::string::npos)
    filename.assign(path.begin() + pos + 1, path.end());
  else
    filename = path;
15 голосов
/ 02 апреля 2011

Просто используйте boost::filesystem.

#include <boost/filesystem.hpp>

std::string filename_noext;
filename_noext = boost::filesystem::path("D:\\files\\file.lua").stem().string().
const char* result_as_const_char = filename_noext.c_str();

или, альтернативно, если вы хотите сами вносить ошибки:

// have fun defining that to the separator of the target OS.
#define PLATFORM_DIRECTORY_SEPARATOR '\\'

// the following code is guaranteed to have bugs.
std::string input = "D:\\files\\file.lua";
std::string::size_type filename_begin = input.find_last_of(PLATFORM_DIRECTORY_SEPERATOR);
if (filename_begin == std::string::npos)
    filename_begin = 0;
else
    filename_begin++;
std::string::size_type filename_length = input.find_last_of('.');
if (filename_length != std::string::npos)
    filename_length = filename_length - filename_begin;

std::string result = input.substr(filename_begin, filename_length);

const char* bugy_result_as_const_char = result.c_str();
1 голос
/ 23 декабря 2016

Вы можете сделать это легко и просто, используя новую библиотеку файловой системы на C ++ 17.

#include <cstdint>
#include <cstdio>
#include <filesystem>

int main()
{
    std::filesystem::path my_path("D:/files/file.lua");
    std::printf("filename: %s\n", my_path.filename().u8string().c_str());
    std::printf("stem: %s\n", my_path.stem().u8string().c_str());
    std::printf("extension: %s\n", my_path.extension().u8string().c_str());
}

Вывод:

filename: file.lua
stem: file
extension: .lua

Обратите внимание, что на данный момент вы можетенеобходимо использовать #include <experimental/fileystem> вместе с std::experimental::filesystem, пока стандартные библиотеки не будут полностью соответствовать.

Для получения дополнительной документации по std::filesystem ознакомьтесь с справочником библиотеки файловой системы .

1 голос
/ 24 ноября 2011

Вы можете легко извлечь файл:

int main()
{
    char pscL_Dir[]="/home/srfuser/kush/folder/kushvendra.txt";
    char pscL_FileName[50];
    char pscL_FilePath[100];
    char *pscL;
    pscL=strrchr(pscL_Dir,'/');
    if(pscL==NULL)
        printf("\n ERROR :INvalid DIr");
    else
    {
        strncpy(pscL_FilePath,pscL_Dir,(pscL-pscL_Dir));
        strcpy(pscL_FileName,pscL+1);
        printf("LENTH [%d}\n pscL_FilePath[%s]\n pscL_FileName[%s]",(pscL-pscL_Dir),pscL_FilePath,pscL_FileName);
    }
    return 0;
}


output: 
LENTH [25}
 pscL_FilePath[/home/srfuser/kush/folder]
 pscL_FileName[kushvendra.txt
0 голосов
/ 13 февраля 2017

Если вы собираетесь отобразить имя файла для пользователя в Windows, вы должны соблюдать его настройки оболочки (показать / скрыть расширение и т. Д.).

Вы можете получить имя файла в правильномформатировать, вызывая SHGetFileInfo с флагом SHGFI_DISPLAYNAME.

0 голосов
/ 02 декабря 2015

Вы можете использовать функцию _splitpath_s для разбиения имени пути на его компоненты . Я не знаю, является ли это стандартным C или специфичным для Windows. В любом случае это функция:

#include <stdlib.h>
#include <string>

using std::string;

bool splitPath(string const &path, string &drive, string &directory, string &filename, string &extension) {
    // validate path
    drive.resize(_MAX_DRIVE);
    directory.resize(_MAX_DIR);
    filename.resize(_MAX_FNAME);
    extension.resize(_MAX_EXT);

    errno_t result;
    result = _splitpath_s(path.c_str(), &drive[0], drive.size(), &directory[0], directory.size(), &filename[0], filename.size(), &extension[0], extension.size()); 
    //_splitpath(path.c_str(), &drive[0], &directory[0], &filename[0], &extension[0]); //WindowsXp compatibility
    _get_errno(&result);
    if (result != 0) {
        return false;
    } else {
        //delete the blank spaces at the end
        drive = drive.c_str();
        directory = directory.c_str();
        filename = filename.c_str();
        extension = extension.c_str();
        return true;
    }
}

Намного проще и безопаснее использовать std::string, но вы можете изменить это, чтобы использовать TCHAR* (wchar, char) ...

Для вашего конкретного случая:

int main(int argc, char *argv[]) {
    string path = argv[0];
    string drive, directory, filename, extension;
    splitPath(path, drive, directory, filename, extension);
    printf("FILE = %s%s", filename.c_str(), extension.c_str());
    return 0;
}
0 голосов
/ 15 сентября 2013
// Set short name:
char *Filename;
Filename = strrchr(svFilename, '\\');
if ( Filename == NULL )
    Filename = svFilename;

if ( Filename[0] == '\\')
    ++Filename;
if ( !lstrlen(Filename) )
{
    Filename = svFilename;
}
fprintf( m_FileOutput, ";\n; %s\n;\n", Filename );
0 голосов
/ 02 апреля 2011

Здесь вы можете найти пример. Я не говорю, что это лучшее, и я уверен, что вы могли бы улучшить это, но он использует только стандартный C ++ (во всяком случае, по крайней мере то, что сейчас считается стандартом). Конечно, у вас не будет функций boost :: filesystem (эти функции в примере воспроизводятся с простыми строками и не гарантируют / не проверяют, действительно ли вы работаете с реальным путем к файловой системе).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...