Отримати ім’я файлу із шляху


85

Який найпростіший спосіб отримати ім’я файлу із шляху?

string filename = "C:\\MyDirectory\\MyFile.bat"

У цьому прикладі я повинен отримати "MyFile". без розширення.


1
Шукати ззаду, доки не вдариться до зворотного простору?
Kerrek SB

2
@KerrekSB, ви маєте на увазі зворотну косу риску ;)
Нім

у мене є std :: рядок, що містить шлях до файлу "c: \\ MyDirectory \\ Myfile.pdf", мені потрібно перейменувати цей файл у myfile_md.pdf, тому мені потрібно отримати ім'я файлу із шляху.
nidhal

1
Якщо вам потрібно багато попрацювати із шляхами до файлів, розгляньте можливість використання Boost FileSystem boost.org/doc/libs/release/libs/filesystem/v3/doc/index.htm
edA-qa mort-ora-y

2
@ Нім: Так! Я, мабуть, відступав ...
Kerrek SB

Відповіді:


29

_splitpath повинен робити те, що вам потрібно. Звичайно, ви можете зробити це вручну, але також _splitpathобробляєте всі особливі випадки.

РЕДАГУВАТИ:

Як уже згадувалося BillHoag рекомендується використовувати більш безпечну версію _splitpathпід назвою _splitpath_s якщо такі є.

Або якщо ви хочете щось портативне, ви можете просто зробити щось подібне

std::vector<std::string> splitpath(
  const std::string& str
  , const std::set<char> delimiters)
{
  std::vector<std::string> result;

  char const* pch = str.c_str();
  char const* start = pch;
  for(; *pch; ++pch)
  {
    if (delimiters.find(*pch) != delimiters.end())
    {
      if (start != pch)
      {
        std::string str(start, pch);
        result.push_back(str);
      }
      else
      {
        result.push_back("");
      }
      start = pch + 1;
    }
  }
  result.push_back(start);

  return result;
}

...
std::set<char> delims{'\\'};

std::vector<std::string> path = splitpath("C:\\MyDirectory\\MyFile.bat", delims);
cout << path.back() << endl;

2
На _splitpathмоїй машині немає жодного з компонентів.
James Kanze

9
У мене є Visual Studio, і g ++, і Sun CC. Чому я повинен використовувати щось нестандартне, коли є цілком якісні портативні рішення.
James Kanze

2
@James, на сторінці, на яку посилається, написано, що вона є <stdlib.h>. Що стосується портативності, можливо, ви можете перелічити кілька прикладів «цілком хороших портативних рішень»?
Synetech

2
@Synetech Сторінка, на яку посилається, описує розширення Microsoft, а не <stdlib.h>. І головним мотивним портативним рішенням є boost::filesystem.
James Kanze,

3
@James, ви не маєте _splitpathв stdlib.hвашій копії VS? Тоді ви можете зробити ремонтну установку VS.
Synetech

63

Можливе рішення:

string filename = "C:\\MyDirectory\\MyFile.bat";

// Remove directory if present.
// Do this before extension removal incase directory has a period character.
const size_t last_slash_idx = filename.find_last_of("\\/");
if (std::string::npos != last_slash_idx)
{
    filename.erase(0, last_slash_idx + 1);
}

// Remove extension if present.
const size_t period_idx = filename.rfind('.');
if (std::string::npos != period_idx)
{
    filename.erase(period_idx);
}

найпростіший - завжди найкращий!
Жан-Франсуа Фабр

61

Завдання досить просте, оскільки базове ім'я файлу - це лише частина рядка, що починається з останнього деліметра для папок:

std::string base_filename = path.substr(path.find_last_of("/\\") + 1)

Якщо розширення також потрібно вилучити, єдине, що потрібно зробити, це знайти останнє .і пройти substrдо цього моменту

std::string::size_type const p(base_filename.find_last_of('.'));
std::string file_without_extension = base_filename.substr(0, p);

Можливо, повинна бути перевірка для роботи з файлами, що складаються виключно з розширень (тобто .bashrc...)

Якщо ви розділите це на окремі функції, ви зможете повторно використовувати окремі завдання:

template<class T>
T base_name(T const & path, T const & delims = "/\\")
{
  return path.substr(path.find_last_of(delims) + 1);
}
template<class T>
T remove_extension(T const & filename)
{
  typename T::size_type const p(filename.find_last_of('.'));
  return p > 0 && p != T::npos ? filename.substr(0, p) : filename;
}

Код створений за шаблоном, щоб мати можливість використовувати його з різними std::basic_stringекземплярами (тобто std::string& std::wstring...)

Недоліком шаблону є вимога вказати параметр шаблону, якщо а const char *передається функціям.

Отже, ви можете:

A) Використовуйте лише std::stringзамість шаблону коду

std::string base_name(std::string const & path)
{
  return path.substr(path.find_last_of("/\\") + 1);
}

B) Забезпечити функцію обгортання з використанням std::string(як проміжних продуктів, які, швидше за все, будуть вбудовані / оптимізовані)

inline std::string string_base_name(std::string const & path)
{
  return base_name(path);
}

В) Вкажіть параметр шаблону під час виклику за допомогою const char *.

std::string base = base_name<std::string>("some/path/file.ext");

Результат

std::string filepath = "C:\\MyDirectory\\MyFile.bat";
std::cout << remove_extension(base_name(filepath)) << std::endl;

Відбитки

MyFile

У цьому випадку все в порядку (і на оригінальне запитання дано відповіді), але ваш засіб для видалення розширень не ідеальний - він не вдасться, якщо ми передамо туди щось на зразок "/home/user/my.dir/myfile"
avtomaton

@avtomaton Функцію видалення розширення слід використовувати для імені файлу, а не шляху. (Просто подайте заявку base_nameспочатку.)
Pixelchemist

Я це розумію (тому я написав, що на вихідне запитання дано відповідь, і в цьому випадку все в порядку). Просто хотів вказати на цю проблему для тих, хто спробує використовувати ці фрагменти.
автомат

Дуже приємне пояснення. Це покращує структурне розуміння проблеми. Дякую
hell_ical_vortex

38

Найпростішим рішенням є використання чогось подібного boost::filesystem. Якщо з якихось причин це не варіант ...

Щоб зробити це правильно, потрібен певний системний код: під Windows, '\\'або '/'може бути роздільником шляху; під Unix '/'працює тільки , а в інших системах, хто знає. Очевидним рішенням буде щось на зразок:

std::string
basename( std::string const& pathname )
{
    return std::string( 
        std::find_if( pathname.rbegin(), pathname.rend(),
                      MatchPathSeparator() ).base(),
        pathname.end() );
}

, MatchPathSeparatorщо визначається в залежному від системи заголовку як:

struct MatchPathSeparator
{
    bool operator()( char ch ) const
    {
        return ch == '/';
    }
};

для Unix, або:

struct MatchPathSeparator
{
    bool operator()( char ch ) const
    {
        return ch == '\\' || ch == '/';
    }
};

для Windows (або щось, що все ще відрізняється для іншої невідомої системи).

EDIT: Я пропустив той факт, що він також хотів придушити продовження. Для цього ще те саме:

std::string
removeExtension( std::string const& filename )
{
    std::string::const_reverse_iterator
                        pivot
            = std::find( filename.rbegin(), filename.rend(), '.' );
    return pivot == filename.rend()
        ? filename
        : std::string( filename.begin(), pivot.base() - 1 );
}

Код дещо складніший, оскільки в цьому випадку основа зворотного ітератора знаходиться на неправильній стороні місця, де ми хочемо вирізати. (Пам'ятайте, що основа зворотного ітератора стоїть за символом, на який вказує ітератор.) І навіть це трохи сумнівно: мені не подобається той факт, що він може повертати порожній рядок, наприклад. (Якщо єдиним '.'є перший символ імені файлу, я стверджую, що вам слід повернути повне ім'я файлу. Для цього знадобиться трохи додаткового коду, щоб зафіксувати особливий випадок.)}


9
Як щодо використання string::find_last_ofзамість маніпулювання зворотними ітераторами?
Luc Touraille

@LucTouraille Чому навчитися двом способам робити щось, коли один це робитиме? Вам потрібні зворотні ітератори для будь-якого контейнера, за винятком string, тому ви все одно повинні їх вивчити. І вивчивши їх, немає жодної причини турбуватися про вивчення всього роздутого інтерфейсу std::string.
James Kanze

Примітка: Заголовок <filesystem> постачається з Visual Studio 2015 і вище, тому вам не потрібно додавати залежність від boost, щоб використовувати його.
IIСпецифічно

17

Найпростіший спосіб у C ++ 17:

використовуйте #include <filesystem>і filename()для імені файлу з розширенням та stem()без розширення.

    #include <iostream>
    #include <filesystem>
    namespace fs = std::filesystem;

    int main()
    {
        string filename = "C:\\MyDirectory\\MyFile.bat";

    std::cout << fs::path(filename).filename() << '\n'
        << fs::path(filename).stem() << '\n'
        << fs::path("/foo/bar.txt").filename() << '\n'
        << fs::path("/foo/bar.txt").stem() << '\n'
        << fs::path("/foo/.bar").filename() << '\n'
        << fs::path("/foo/bar/").filename() << '\n'
        << fs::path("/foo/.").filename() << '\n'
        << fs::path("/foo/..").filename() << '\n'
        << fs::path(".").filename() << '\n'
        << fs::path("..").filename() << '\n'
        << fs::path("/").filename() << '\n';
    }

вихід:

MyFile.bat
MyFile
"bar.txt"
".bar"
"."
"."
".."
"."
".."
"/"

Довідково: cppreference


це вже не в "експериментальному"
Віт

15

Ви також можете використовувати оболонку Path APIs PathFindFileName, PathRemoveExtension. Можливо, гірше, ніж _splitpath для цієї конкретної проблеми, але ці API дуже корисні для всіх видів завдань синтаксичного аналізу шляхів, і вони беруть до уваги UNC-шляхи, похилі риски та інші дивні речі.

wstring filename = L"C:\\MyDirectory\\MyFile.bat";
wchar_t* filepart = PathFindFileName(filename.c_str());
PathRemoveExtension(filepart); 

http://msdn.microsoft.com/en-us/library/windows/desktop/bb773589(v=vs.85).aspx

Недоліком є ​​те, що вам потрібно зробити посилання на shlwapi.lib, але я не зовсім впевнений, чому це недолік.


Моє найкраще рішення для отримання імені файлу із шляху.
Андреас,

15

Якщо ви можете використовувати boost,

#include <boost/filesystem.hpp>
path p("C:\\MyDirectory\\MyFile.bat");
string basename = p.filename().string();
//or 
//string basename = path("C:\\MyDirectory\\MyFile.bat").filename().string();

Це все.

Я рекомендую вам використовувати бібліотеку boost. Boost дає вам багато зручностей під час роботи з C ++. Він підтримує майже всі платформи. Якщо ви використовуєте Ubuntu, ви можете встановити boost-бібліотеку лише одним рядком sudo apt-get install libboost-all-dev(див. Як встановити boost на Ubuntu? )


12

Функція:

#include <string>

std::string
basename(const std::string &filename)
{
    if (filename.empty()) {
        return {};
    }

    auto len = filename.length();
    auto index = filename.find_last_of("/\\");

    if (index == std::string::npos) {
        return filename;
    }

    if (index + 1 >= len) {

        len--;
        index = filename.substr(0, len).find_last_of("/\\");

        if (len == 0) {
            return filename;
        }

        if (index == 0) {
            return filename.substr(1, len - 1);
        }

        if (index == std::string::npos) {
            return filename.substr(0, len);
        }

        return filename.substr(index + 1, len - index - 1);
    }

    return filename.substr(index + 1, len - index);
}

Тести:

#define CATCH_CONFIG_MAIN
#include <catch/catch.hpp>

TEST_CASE("basename")
{
    CHECK(basename("") == "");
    CHECK(basename("no_path") == "no_path");
    CHECK(basename("with.ext") == "with.ext");
    CHECK(basename("/no_filename/") == "no_filename");
    CHECK(basename("no_filename/") == "no_filename");
    CHECK(basename("/no/filename/") == "filename");
    CHECK(basename("/absolute/file.ext") == "file.ext");
    CHECK(basename("../relative/file.ext") == "file.ext");
    CHECK(basename("/") == "/");
    CHECK(basename("c:\\windows\\path.ext") == "path.ext");
    CHECK(basename("c:\\windows\\no_filename\\") == "no_filename");
}

8

З документів C ++ - рядок :: find_last_of

#include <iostream>       // std::cout
#include <string>         // std::string

void SplitFilename (const std::string& str) {
  std::cout << "Splitting: " << str << '\n';
  unsigned found = str.find_last_of("/\\");
  std::cout << " path: " << str.substr(0,found) << '\n';
  std::cout << " file: " << str.substr(found+1) << '\n';
}

int main () {
  std::string str1 ("/usr/bin/man");
  std::string str2 ("c:\\windows\\winhelp.exe");

  SplitFilename (str1);
  SplitFilename (str2);

  return 0;
}

Виходи:

Splitting: /usr/bin/man
 path: /usr/bin
 file: man
Splitting: c:\windows\winhelp.exe
 path: c:\windows
 file: winhelp.exe

Не забувайте (і обробляти), що find_last_ofповертається, string::nposякщо нічого не знайдено.
congusbongus

@congusbongus Правда, але немає сенсу розділяти шлях до файлу, коли це просто ім'я файлу (без шляху) :)
jave.web

@ jave.web Це має сенс і ПОВИНЕН обробляти повернення 'string :: npos'. Реалізація функції для цього повинна мати можливість обробляти різні вхідні дані, включаючи "просто ім'я файлу". В іншому випадку це буде марно, якщо його глючить у реальній реалізації.
winux

@winux Це вважає вже дійсними ШЛЯХИ ... Якщо ви не довіряєте введенню, вам слід, звичайно, спочатку перевірити шлях.
jave.web

@winux У будь-якому випадку перевірку на наявність string::nposне потрібно робити через спосіб, як це і string::substrреалізовано. а) string::npos передається як "length" => substrмає задокументовану поведінку читання всіх до кінця. б) substrдається « string::npos + 1» і не довжина: string::nposне документована мати значення -1, так що має значення 0=> початок рядка і значення по замовчуванням довжини для substrє в npos=> працює на "просто ім'я файлу" теж cplusplus.com/reference / string / string / substr cplusplus.com/reference/string/string/npos
jave.web

5

Варіант С ++ 11 (натхненний версією Джеймса Канце) з рівномірною ініціалізацією та анонімною вбудованою лямбда-ланкою.

std::string basename(const std::string& pathname)
{
    return {std::find_if(pathname.rbegin(), pathname.rend(),
                         [](char c) { return c == '/'; }).base(),
            pathname.end()};
}

Однак це не видаляє розширення файлу.


Короткий і солодкий, хоча він працює лише із шляхами, які не є Windows.
Воломіке

Ви завжди можете змінити повернення return c == '/' || c == '\\';
лямбди,

Щоб обробляти такі шляхи, як "", "///" та "dir1 / dir2 /", додайте наступний код перед оператором return (див. Базове ім'я POSIX ()): if (pathname.size() == 0) return "."; auto iter = pathname.rbegin(); auto rend = pathname.rend(); while (iter != rend && *iter == '/') ++iter; if (iter == rend) /* pathname has only path separators */ return "/"; pathname = std::string(pathname.begin(), iter.base());
Gidfiddle

5

boost filesystemБібліотека також доступна в якості experimental/filesystemбібліотеки і об'єднані в ISO C ++ для C ++ 17. Ви можете використовувати його так:

#include <iostream>
#include <experimental/filesystem>

namespace fs = std::experimental::filesystem;

int main () {
    std::cout << fs::path("/foo/bar.txt").filename() << '\n'
}

Вихід:

"bar.txt"

Він також працює для std::stringоб'єктів.


4

це єдине, що насправді нарешті спрацювало у мене:

#include "Shlwapi.h"

CString some_string = "c:\\path\\hello.txt";
LPCSTR file_path = some_string.GetString();
LPCSTR filepart_c = PathFindFileName(file_path);
LPSTR filepart = LPSTR(filepart_c);
PathRemoveExtension(filepart);

майже те, що запропонував Скримслі, але не працює з wchar_t *, VS Enterprise 2015

_splitpath також працював, але мені не подобається вгадувати, скільки символів [[]] мені знадобиться; певно, деяким людям потрібен цей контроль.

CString c_model_name = "c:\\path\\hello.txt";
char drive[200];
char dir[200];
char name[200];
char ext[200];
_splitpath(c_model_name, drive, dir, name, ext);

Я не вірю, що для _splitpath потрібні були будь-які включення. Жодні зовнішні бібліотеки (наприклад, підсилення) не потрібні для жодного з цих рішень.


4
std::string getfilename(std::string path)
{
    path = path.substr(path.find_last_of("/\\") + 1);
    size_t dot_i = path.find_last_of('.');
    return path.substr(0, dot_i);
}

3

Я б зробив це ...

Шукайте назад від кінця рядка, поки не знайдете першу косу риску / косу риску.

Потім виконайте пошук назад з кінця рядка, поки не знайдете першу крапку (.)

Потім у вас є початок і кінець імені файлу.

Прості ...


Що не працює для жодної системи, яку я знаю. (Єдина система, яка приймає '\\'як роздільник шляхів, також використовує '/', тому вам потрібно збігатися з ними.) І я не впевнений, чого б ви з нетерпінням чекали.
James Kanze

Гаразд, так модифікуйте його відповідно до будь-якого, не біггі. І з нетерпінням чекаю першої точки (.)
TomP89

Вам ще доведеться знайти останню крапку, а не першу. (Зворотні ітератори - ваш друг!)
Джеймс Канце,

Ах так, хороший момент. Отже, для file.ext.ext тоді ви хочете витягти file.ext, чи не так. :)
TomP89

Імовірно. Це звичайна умова, в будь-якому випадку: my.source.cppкомпілюється my.source.obj, наприклад (із .cppзаміненим розширенням на .obj).
James Kanze

2
m_szFilePath.MakeLower();
CFileFind finder;
DWORD buffSize = MAX_PATH;
char longPath[MAX_PATH];
DWORD result = GetLongPathName(m_szFilePath, longPath, MAX_PATH );

if( result == 0)
{
    m_bExists = FALSE;
    return;
}
m_szFilePath = CString(longPath);
m_szFilePath.Replace("/","\\");
m_szFilePath.Trim();
//check if it does not ends in \ => remove it
int length = m_szFilePath.GetLength();
if( length > 0 && m_szFilePath[length - 1] == '\\' )
{
    m_szFilePath.Truncate( length - 1 );
}
BOOL bWorking = finder.FindFile(this->m_szFilePath);
if(bWorking){
    bWorking = finder.FindNextFile();
    finder.GetCreationTime(this->m_CreationTime);
    m_szFilePath = finder.GetFilePath();
    m_szFileName = finder.GetFileName();

    this->m_szFileExtension = this->GetExtension( m_szFileName );

    m_szFileTitle = finder.GetFileTitle();
    m_szFileURL = finder.GetFileURL();
    finder.GetLastAccessTime(this->m_LastAccesTime);
    finder.GetLastWriteTime(this->m_LastWriteTime);
    m_ulFileSize = static_cast<unsigned long>(finder.GetLength());
    m_szRootDirectory = finder.GetRoot();
    m_bIsArchive = finder.IsArchived();
    m_bIsCompressed = finder.IsCompressed();
    m_bIsDirectory = finder.IsDirectory();
    m_bIsHidden = finder.IsHidden();
    m_bIsNormal = finder.IsNormal();
    m_bIsReadOnly = finder.IsReadOnly();
    m_bIsSystem = finder.IsSystem();
    m_bIsTemporary = finder.IsTemporary();
    m_bExists = TRUE;
    finder.Close();
}else{
    m_bExists = FALSE;
}

Змінна m_szFileName містить fileName.


3
вау - це багато коду для "отримати ім'я файлу" із шляху ... :)
Нім

4
@Nim Моє враження також. У моєму власному коді, я використовую один вкладиш: boost::filesystem::path( path ).filename().
James Kanze

У мене є клас CFileInfo, який має цей код. Я просто скинув код сюди, тому що він протестований, і я не хотів нічим ризикувати ... Ви можете просто використати близько 5 рядків коду з цього прикладу.
Lucian

2

Не використовуйте _splitpath()та _wsplitpath(). Вони не в безпеці, і вони застаріли!

Натомість використовуйте їх безпечні версії, а саме _splitpath_s()та_wsplitpath_s()


2

Це теж повинно працювати:

// strPath = "C:\\Dir\\File.bat" for example
std::string getFileName(const std::string& strPath)
{
    size_t iLastSeparator = 0;
    return strPath.substr((iLastSeparator = strPath.find_last_of("\\")) != std::string::npos ? iLastSeparator + 1 : 0, strPath.size() - strPath.find_last_of("."));
}

Якщо ви можете використовувати його, Qt надає QString (з розділенням, обрізанням тощо), QFile, QPath, QFileInfo тощо для маніпулювання файлами, іменами файлів та каталогів. І, звичайно, це також поперечний плафторм.


4
Задля майбутніх читачів вашого коду, будь ласка, використовуйте тимчасові змінні зі значущими іменами, замість того, щоб набивати все в один рядок коду (і поки ви це робите, будь-ласка, інкапсулюйте все це у функцію getFilenameчи щось подібне).
Luc Touraille

відредаговано. Але суть полягала в тому, щоб зробити це коротким, оскільки вже було дано кілька робочих відповідей.
typedef

1
Я думаю, це НЕПРАВИЛЬНО. Чи не слід замінити останню частину: "strPath.size () - strPath.find_last_of (". ")" На "strPath.find_last_of (". ") - iLastSeparator"
taktak004

@ taktak004 ви маєте рацію, це має бути `return strPath.substr ((iLastSeparator = strPath.find_last_of (" / "))! = std :: string :: npos? iLastSeparator + 1: 0, strPath.find_last_of (". " ) - iLastSeparator); `
phenmod

2

Ви можете використовувати файлову систему std ::, щоб зробити це досить добре:

#include <filesystem>
namespace fs = std::experimental::filesystem;

fs::path myFilePath("C:\\MyDirectory\\MyFile.bat");
fs::path filename = myFilePath.stem();

0

Довгий час я шукав функцію, здатну правильно розкласти шлях до файлу. Для мене цей код чудово працює як для Linux, так і для Windows.

void decomposePath(const char *filePath, char *fileDir, char *fileName, char *fileExt)
{
    #if defined _WIN32
        const char *lastSeparator = strrchr(filePath, '\\');
    #else
        const char *lastSeparator = strrchr(filePath, '/');
    #endif

    const char *lastDot = strrchr(filePath, '.');
    const char *endOfPath = filePath + strlen(filePath);
    const char *startOfName = lastSeparator ? lastSeparator + 1 : filePath;
    const char *startOfExt = lastDot > startOfName ? lastDot : endOfPath;

    if(fileDir)
        _snprintf(fileDir, MAX_PATH, "%.*s", startOfName - filePath, filePath);

    if(fileName)
        _snprintf(fileName, MAX_PATH, "%.*s", startOfExt - startOfName, startOfName);

    if(fileExt)
        _snprintf(fileExt, MAX_PATH, "%s", startOfExt);
}

Приклади результатів:

[]
  fileDir:  ''
  fileName: ''
  fileExt:  ''

[.htaccess]
  fileDir:  ''
  fileName: '.htaccess'
  fileExt:  ''

[a.exe]
  fileDir:  ''
  fileName: 'a'
  fileExt:  '.exe'

[a\b.c]
  fileDir:  'a\'
  fileName: 'b'
  fileExt:  '.c'

[git-archive]
  fileDir:  ''
  fileName: 'git-archive'
  fileExt:  ''

[git-archive.exe]
  fileDir:  ''
  fileName: 'git-archive'
  fileExt:  '.exe'

[D:\Git\mingw64\libexec\git-core\.htaccess]
  fileDir:  'D:\Git\mingw64\libexec\git-core\'
  fileName: '.htaccess'
  fileExt:  ''

[D:\Git\mingw64\libexec\git-core\a.exe]
  fileDir:  'D:\Git\mingw64\libexec\git-core\'
  fileName: 'a'
  fileExt:  '.exe'

[D:\Git\mingw64\libexec\git-core\git-archive.exe]
  fileDir:  'D:\Git\mingw64\libexec\git-core\'
  fileName: 'git-archive'
  fileExt:  '.exe'

[D:\Git\mingw64\libexec\git.core\git-archive.exe]
  fileDir:  'D:\Git\mingw64\libexec\git.core\'
  fileName: 'git-archive'
  fileExt:  '.exe'

[D:\Git\mingw64\libexec\git-core\git-archiveexe]
  fileDir:  'D:\Git\mingw64\libexec\git-core\'
  fileName: 'git-archiveexe'
  fileExt:  ''

[D:\Git\mingw64\libexec\git.core\git-archiveexe]
  fileDir:  'D:\Git\mingw64\libexec\git.core\'
  fileName: 'git-archiveexe'
  fileExt:  ''

Сподіваюся, це вам також допоможе :)


0

shlwapi.lib/dllвикористовує HKCUвулик реєстру внутрішньо.

Краще не посилатись, shlwapi.libякщо ви створюєте бібліотеку або продукт не має інтерфейсу користувача. Якщо ви пишете lib, ваш код можна використовувати в будь-якому проекті, включаючи ті, які не мають інтерфейсів.

Якщо ви пишете код, який запускається, коли користувач не входить в систему (наприклад, служба [чи інша], встановлена ​​для запуску під час завантаження або запуску), тоді немає HKCU. Нарешті, шлвапі - це функції поселення; і, як наслідок, високо в списку для припинення в пізніших версіях Windows.


0

Повільне, але пряме рішення регулярного виразу:

    std::string file = std::regex_replace(path, std::regex("(.*\\/)|(\\..*)"), "");

0

Я реалізував функцію, яка може відповідати вашим потребам. Він базується на функції cons_prpr string_view find_last_of (починаючи з c ++ 17), яку можна обчислити під час компіляції

constexpr const char* base_filename(const char* p) {
    const size_t i = std::string_view(p).find_last_of('/');
    return std::string_view::npos == i ? p : p + i + 1 ;
}

//in the file you used this function
base_filename(__FILE__);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.