Bir yoldan bir dosya adı alın


85

Bir yoldan dosya adını almanın en basit yolu nedir?

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

Bu örnekte "MyFile" almalıyım. uzatma olmadan.


1
Bir geri tuşuna basana kadar arkadan aramak?
Kerrek SB

2
@KerrekSB, ters eğik çizgiyi kastediyorsunuz ;)
Nim

"c: \\ MyDirectory \\ Myfile.pdf" adlı bir dosyanın yolunu içeren bir std :: string var. Bu dosyayı myfile_md.pdf olarak yeniden adlandırmam gerekiyor, bu yüzden dosya adını yoldan almam gerekiyor.
nidhal

1
Dosya yollarıyla çok fazla iş yapmanız gerekiyorsa, Boost FileSystem boost.org/doc/libs/release/libs/filesystem/v3/doc/index.htm
edA-qa mort-ora-y

2
@Nim: Evet!
Aralıklı olmalıyım

Yanıtlar:


29

_splitpath ihtiyacınız olanı yapmalıdır. Elbette manuel olarak da yapabilirsiniz, ancak _splitpathtüm özel durumları da ele alır.

DÜZENLE:

BillHoag'ın belirttiği gibi, mevcut olduğunda _splitpath_s_splitpath adlı daha güvenli sürümün kullanılması önerilir .

Veya taşınabilir bir şey istiyorsanız, bunun gibi bir şey yapabilirsiniz

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
Makinemde bulunanların hiçbirinde yok _splitpath.
James Kanze

9
Visual Studio, sahip ve g ++ ve Güneş CC. Mükemmel derecede iyi taşınabilir çözümler varken neden standart olmayan bir şey kullanmalıyım?
James Kanze

2
@James, bağlantılı sayfa içinde olduğunu söylüyor <stdlib.h>. Taşınabilirliğe gelince, belki “mükemmel derecede iyi taşınabilir çözüm” lerden bazı örnekleri listeleyebilirsiniz?
Synetech

2
@Synetech Bağlantı verilen sayfa bir Microsoft uzantısını açıklıyor, değil <stdlib.h>. Ve en belirgin taşınabilir çözüm şudur boost::filesystem.
James Kanze

3
@James, sen yok _splitpathiçinde stdlib.hVS Kopyanızın? O zaman VS'nin onarım kurulumunu yapmak isteyebilirsiniz.
Synetech

63

Olası bir çözüm:

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);
}

en basit olan her zaman en iyisidir!
Jean-François Fabre

61

Temel dosya adı dizenin klasörler için son sınırlamadan başlayan kısmı olduğundan, görev oldukça basittir:

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

Uzantı da kaldırılacaksa, yapılacak tek şey sonuncuyu bulmak .ve substrbu noktaya gitmek.

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

Belki de yalnızca uzantılardan oluşan dosyalarla başa çıkmak için bir kontrol yapılmalıdır (ör .bashrc.

Bunu ayrı işlevlere ayırırsanız, tek görevleri yeniden kullanma esnekliğine sahip olursunuz:

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;
}

Kod, farklı std::basic_stringörneklerle (yani std::string& std::wstring...) kullanabilmek için şablon haline getirilmiştir.

Şablonun dezavantajı const char *, işlevlere bir geçilirse şablon parametresini belirtme gereksinimidir .

Yani şunlardan birini yapabilirsiniz:

A) std::stringKodu şablonlamak yerine yalnızca kullanın

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

B) kullanarak sarma işlevi sağlayın std::string(muhtemelen satır içi / optimize edilecek ara ürünler olarak)

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

C) ile çağırırken şablon parametresini belirtin const char *.

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

Sonuç

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

Baskılar

MyFile

Bu kullanım durumunda her şey yolunda (ve orijinal soru cevaplandı), ancak uzantı kaldırıcınız mükemmel değil - "/home/user/my.dir/myfile" gibi bir şey
iletirsek

@avtomaton Uzantı kaldırma işlevi, bir yol yerine dosya adı üzerinde kullanılmalıdır. ( base_nameÖnce uygulayın .)
Pixelchemist

Anlıyorum (bu yüzden orijinal sorunun yanıtlandığını ve bu kullanım durumunda her şeyin yolunda olduğunu yazdım). Bu parçacıkları kullanmaya çalışacak biri için bu konuya dikkat çekmek istedim.
avtomaton

Çok güzel bir açıklama. Sorunun yapısal anlayışını geliştirir. Teşekkürler
hell_ical_vortex

38

En basit çözüm, gibi bir şey kullanmaktır boost::filesystem. Herhangi bir nedenle bu bir seçenek değilse ...

Bunu doğru bir şekilde yapmak, sisteme bağlı bazı kodlar gerektirecektir: Windows altında, bir yol ayırıcı ya '\\'da '/'olabilir; Unix altında, yalnızca '/'çalışır ve diğer sistemlerde kim bilir. Bariz çözüm şunun gibi bir şey olacaktır:

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

, MatchPathSeparatorsisteme bağlı bir başlıkta şu şekilde tanımlanır:

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

Unix için veya:

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

Windows için (veya başka bir bilinmeyen sistem için hala farklı bir şey).

DÜZENLEME: Uzantıyı da bastırmak istediği gerçeğini kaçırdım. Bunun için aynı şeylerden daha fazlası:

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 );
}

Kod biraz daha karmaşıktır, çünkü bu durumda ters yineleyicinin tabanı kesmek istediğimiz yerin yanlış tarafındadır. (Bir ters yineleyicinin tabanının yineleyicinin işaret ettiği karakterin arkasında olduğunu unutmayın.) Ve bu bile biraz şüpheli: Örneğin boş bir dizge döndürebilmesi gerçeğinden hoşlanmıyorum. (Eğer '.'dosya adının ilk karakteri tek ise, tam dosya adını döndürmeniz gerektiğini savunurum. Bu, özel durumu yakalamak için biraz fazladan kod gerektirir.)}


9
string::find_last_ofTers yineleyicileri kullanmak yerine kullanmaya ne dersiniz ?
Luc Touraille

@LucTouraille Biri yapacakken bir şeyi yapmanın iki yolunu neden öğrenelim? Hariç herhangi bir kapsayıcı için ters yineleyicilere ihtiyacınız olacak string, bu yüzden onları yine de öğrenmelisiniz. Ve onları öğrendikten sonra, tüm şişirilmiş arayüzü öğrenmeye zahmet etmenize gerek yok std::string.
James Kanze

Not: <filesystem> üstbilgisi, Visual Studio 2015 ve üzeri ile birlikte gelir, bu nedenle onu kullanmak için artırmaya bağımlılık eklemeniz gerekmez.
2017

16

C ++ 17'nin en basit yolu şudur:

uzantısı ile ve uzantısız dosya adı için #include <filesystem>ve kullanın .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';
    }

çıktı:

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

Referans: cppreference


artık "deneysel" değil
Vit

15

PathFindFileName, PathRemoveExtension kabuk Yol API'lerini de kullanabilirsiniz. Muhtemelen bu özel sorun için _splitpath'den daha kötüdür, ancak bu API'ler her türlü yol ayrıştırma işi için çok kullanışlıdır ve UNC yollarını, eğik çizgileri ve diğer garip şeyleri hesaba katarlar.

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

Dezavantajı, shlwapi.lib'e bağlanmanız gerekmesidir, ancak bunun neden bir dezavantaj olduğundan emin değilim.


Bir yoldan dosya adı almak için tercih ettiğim çözüm.
Andreas

15

Boost kullanabiliyorsanız,

#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();

Hepsi bu.

Yükseltme kitaplığını kullanmanızı tavsiye ederim. Boost, C ++ ile çalışırken size birçok kolaylık sağlar. Hemen hemen tüm platformları destekler. Ubuntu kullanıyorsanız, artırma kitaplığını yalnızca bir satırla yükleyebilirsiniz sudo apt-get install libboost-all-dev(ref. Ubuntu'ya yükseltme nasıl kurulur ? )


12

İşlev:

#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);
}

Testler:

#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 ++ Belgelerinden - string :: 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;
}

Çıktılar:

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

Hiçbir şey bulunmazsa find_last_ofdöneceğini unutmayın (ve halletmeyi) string::npos.
congusbongus

@congusbongus Doğru, ancak dosya yolunu yalnızca bir dosya adı olduğunda (yol olmadan)
bölmenin bir anlamı yoktur

@ jave.web Mantıklıdır ve 'string :: npos' dönüşlerini işlemesi ZORUNLUDUR. Bunun için bir işlev uygulamak, "sadece dosya adı" dahil olmak üzere farklı girdileri işleyebilmelidir. Aksi takdirde, gerçek uygulamada buggy olması faydasız olacaktır.
winux

@winux Bu zaten düşünmektedir geçerli Yollarını sen girdi güvenmiyorsanız, sen, elbette, ilk yolunu doğrulamak gerekir ....
jave.web

@winux Her neyse , string::nposbunun nasıl string::substruygulandığı ve uygulandığı için kontrolün yapılması gerekmiyor . a) string::npos "uzunluk" olarak geçmiştir => substrsonuna kadar tümünü okuma davranışını belgelemiştir. b) substr"verilir string::npos + 1:" ve uzunluk string::nposbir değere sahip belgelenmiştir -1için değerlendirir böylece, 0için => dize başlar ve uzunlukları varsayılan değer substrolan nposçok sadece dosya adı 'konulu => eserler' cplusplus.com/reference / string / string / substr cplusplus.com/reference/string/string/npos
jave.web

5

Tek tip başlatma ve anonim satır içi lambda ile C ++ 11 varyantı (James Kanze'nin sürümünden esinlenmiştir).

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

Ancak dosya uzantısını kaldırmaz.


Kısa ve tatlıdır, ancak yalnızca Windows olmayan yollarla çalışır.
Volomike

lambda dönüşünü return c == '/' || c == '\\';pencerelerde çalışması için her zaman değiştirebilirsiniz
ziomq1991

"", "///" ve "dir1 / dir2 /" gibi yolları işlemek için, yukarıdaki dönüş ifadesinden önce aşağıdaki kodu ekleyin (cf. POSIX basename ()): 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 filesystemKütüphane olarak da kullanılabilir experimental/filesystemkütüphane ve C ++ 17 ++ için ISO C içine birleştirilmiştir. Bunu şu şekilde kullanabilirsiniz:

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

namespace fs = std::experimental::filesystem;

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

Çıktı:

"bar.txt"

Aynı zamanda std::stringnesneler için de işe yarar.


4

nihayet benim için işe yarayan tek şey bu:

#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);

Skrymsli'nin önerdiği ancak wchar_t *, VS Enterprise 2015 ile çalışmadığı gibi

_splitpath de çalıştı, ancak kaç tane karakter [?] karaktere ihtiyacım olacağını tahmin etmekten hoşlanmıyorum; Bazı insanların muhtemelen bu kontrole ihtiyacı var, sanırım.

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 için eklemeye gerek olduğuna inanmıyorum. Bu çözümlerden herhangi biri için harici kitaplıklara (yükseltme gibi) gerek yoktu.


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

Ben yapardım ...

İlk ters eğik çizgiyi / eğik çizgiyi bulana kadar dizenin sonundan geriye doğru arama yapın.

Ardından, ilk noktayı (.) Bulana kadar dizenin sonundan geriye doğru tekrar arama yapın.

Daha sonra dosya adının başlangıcına ve sonuna sahip olursunuz.

Basit ...


Bu bildiğim hiçbir sistem için çalışmıyor. ( '\\'Yol ayırıcı olarak kabul eden tek sistem de kullanır '/', bu yüzden ikisini de eşleştirmeniz gerekir.) Ve neyi dört gözle beklediğinizden emin değilim.
James Kanze

Tamam öyleyse ikisiyle de eşleşecek şekilde değiştirin, önemli değil. Ve ilk noktayı (.)
Dört

Yine de ilk noktayı değil son noktayı bulmanız gerekiyor. (Ters yineleyiciler arkadaşınızdır!)
James Kanze

Ah evet, iyi nokta. Yani bir file.ext.ext için o zaman file.ext'i çıkarmak istersiniz, değil mi? :)
TomP89

Muhtemelen. Her durumda olağan kural budur: örneğin my.source.cppderlenir my.source.obj(uzantısı ile .cppdeğiştirilir .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 değişkeni fileName'i içerir.


3
vay - bu yoldan "dosya adı al" için çok fazla kod var ... :)
Nim

4
@Nim Benim izlenimim de. Kendi kodunda, ben tek astar kullanın: boost::filesystem::path( path ).filename().
James Kanze

Bu koda sahip bir CFileInfo sınıfım var. Kodu buraya attım çünkü test edildi ve hiçbir şeyi riske atmak istemedim ... Bu örnekten yaklaşık 5 satır kod kullanabilirsiniz.
Lucian


2

Bu da işe yaramalı:

// 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("."));
}

Kullanabiliyorsanız, Qt, dosyaları, dosya adlarını ve dizinleri işlemek için QString (split, trim vb. İle), QFile, QPath, QFileInfo vb. Sağlar. Ve tabii ki aynı zamanda çapraz fırtına.


4
Kodunuzun gelecekteki okuyucularının iyiliği için, lütfen her şeyi tek bir kod satırına doldurmak yerine anlamlı adlara sahip geçici değişkenler kullanın (ve bunu yaparken lütfen tüm bunları bir işlev getFilenameveya buna benzer bir şey içine alın ).
Luc Touraille

düzenlendi. Ancak, halihazırda birkaç çalışma cevabı verildiği için, mesele konuyu kısaltmaktı.
typedef

1
YANLIŞ olduğunu düşünüyorum. Son bölümü değiştirmemelisiniz: "strPath.size () - strPath.find_last_of (". ")" "StrPath.find_last_of (". ") - iLastSeparator"
taktak004

@ taktak004 haklısınız, "return strPath.substr ((iLastSeparator = strPath.find_last_of (" / "))! = std :: string :: npos? iLastSeparator + 1: 0, strPath.find_last_of (". " ) - iLastSeparator); `
phenmod

2

Bunu oldukça güzel yapmak için std :: dosya sistemini kullanabilirsiniz:

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

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

0

Uzun zamandır dosya yolunu düzgün şekilde ayrıştırabilen bir işlev arıyordum. Benim için bu kod hem Linux hem de Windows için mükemmel çalışıyor.

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);
}

Örnek sonuçlar:

[]
  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:  ''

Umarım bu size de yardımcı olur :)


0

shlwapi.lib/dllHKCUkayıt defteri kovanını dahili olarak kullanır .

shlwapi.libBir kitaplık oluşturuyorsanız veya ürünün bir kullanıcı arayüzü yoksa, bağlantı vermemek en iyisidir . Bir kitaplık yazıyorsanız, kodunuz kullanıcı arabirimi olmayanlar da dahil olmak üzere herhangi bir projede kullanılabilir.

Bir kullanıcı oturum açmadığında çalışan bir kod yazıyorsanız (örneğin, hizmet [veya diğer] önyükleme veya başlangıçta başlayacak şekilde ayarlanmışsa), o zaman yok HKCU. Son olarak, shlwapi yerleşim işlevleridir; ve sonuç olarak, Windows'un sonraki sürümlerinde kullanımdan kaldırılacak listede üst sıralarda.


0

Yavaş ama anlaşılır bir normal ifade çözümü:

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

0

İhtiyaçlarınızı karşılayabilecek bir işlev uyguladım. String_view'un compile zamanında hesaplanabilen find_last_of (c ++ 17'den beri) constexpr işlevine dayanmaktadır.

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__);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.