【问题标题】:Get a file name from a path从路径中获取文件名
【发布时间】:2012-01-21 04:14:24
【问题描述】:

从路径中获取文件名的最简单方法是什么?

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

在这个例子中,我应该得到“MyFile”。没有扩展名。

【问题讨论】:

  • 从后面搜索直到您按下退格键?
  • @KerrekSB,你的意思是 反斜杠 ;)
  • 我有一个包含文件路径的 std::string "c:\\MyDirectory\\Myfile.pdf" 我需要将此文件重命名为 myfile_md.pdf 所以我需要获取路径中的文件名。
  • 如果您需要对文件路径进行大量工作,请考虑使用 Boost FileSystem boost.org/doc/libs/release/libs/filesystem/v3/doc/index.htm
  • @Nim:是的!我一定是在疏远...

标签: c++ visual-c++


【解决方案1】:

任务相当简单,因为基本文件名只是从文件夹的最后一个分隔符开始的字符串的一部分:

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

C) 使用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/”之类的内容,它将失败我的文件”
  • @avtomaton 扩展名删除功能应该用于文件名而不是路径。 (请先申请base_name。)
  • 我明白了(这就是为什么我写了原始问题得到了回答,并且在这个用例中一切正常)。只是想为尝试使用这些 sn-ps 的人指出这个问题。
  • 很好的解释。它增强了对问题的结构性理解。谢谢
【解决方案2】:

一个可能的解决方案:

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

【讨论】:

  • 最简单的永远是最好的!
【解决方案3】:

C++17 中最简单的方法是:

使用#include &lt;filesystem&gt;filename() 作为带扩展名的文件名,使用stem() 不带扩展名。

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

int main()
{
  std::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';
}

可以用g++ -std=c++17 main.cpp -lstdc++fs编译,输出:

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

参考:cppreference

【讨论】:

  • 它不再处于“实验”状态
【解决方案4】:

最简单的解决方案是使用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(或者对于其他未知的东西仍然不同 系统)。

编辑:我错过了他也想压制扩展的事实。 为此,更多相同:

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

代码有点复杂,因为在这种情况下, 反向迭代器位于我们要剪切的位置的错误一侧。 (请记住,反向迭代器的基数在 迭代器指向的字符。)甚至这有点可疑:我 例如,不喜欢它可以返回空字符串的事实。 (如果唯一的 '.' 是文件名的第一个字符,我会争辩 你应该返回完整的文件名。这需要一点 一些额外的代码来捕捉特殊情况。) }

【讨论】:

  • 使用string::find_last_of而不是操作反向迭代器怎么样?
  • @LucTouraille 为什么要学习两种做事方式,而一个人会做?除了string 之外,任何容器都需要反向迭代器,所以无论如何你都必须学习它们。学习了它们之后,没有理由费心去学习std::string 的所有臃肿界面。
  • 注意:<filesystem> 标头随 Visual Studio 2015 及更高版本提供,因此您无需添加对 boost 的依赖即可使用它。
【解决方案5】:

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

【讨论】:

  • 我的机器上的任何包含中都没有_splitpath
  • 我有 Visual Studio、 g++ 和 Sun CC。既然有完美的便携式解决方案,我为什么要使用非标准的东西。
  • @James,链接到的页面显示它位于&lt;stdlib.h&gt;。至于便携性,或许你可以列举一些“非常好的便携解决方案”的例子?
  • @Synetech 链接到的页面描述的是 Microsoft 扩展,而不是 &lt;stdlib.h&gt;。最明显的便携式解决方案是boost::filesystem
  • @James,你的 VS 副本的 stdlib.h 中没有 _splitpath 吗?然后你可能想要对 VS 进行修复安装。
【解决方案6】:

您还可以使用外壳路径 API 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,但我不确定为什么这是一个缺点。

【讨论】:

  • 我从路径获取文件名的首选解决方案。
【解决方案7】:

如果你可以使用 boost,

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

就这些了。

我推荐你使用 boost 库。当您使用 C++ 时,Boost 为您提供了很多便利。它支持几乎所有平台。 如果你使用 Ubuntu,你只需一行 sudo apt-get install libboost-all-dev (ref. How to install Boost on Ubuntu) 就可以安装 boost 库

【讨论】:

    【解决方案8】:

    功能:

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

    【讨论】:

    • 非常好!谢谢!
    【解决方案9】:

    来自 C++ 文档 - 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;
    }
    

    输出:

    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 没错,但是当只是一个文件名(没有路径)的时候没有分割文件路径的意义:)
    • @jave.web 这确实有意义并且必须处理返回'string::npos'。为此实现一个函数应该能够处理不同的输入,包括“只是文件名”。否则,如果它在实际实现中出现错误,它将毫无用处。
    • @winux 这认为已经 valid PATHS... 如果您不信任输入,您当然应该验证路径首先。
    • @winux 无论如何 不需要检查string::npos,因为它和string::substr 的实现方式。 a) string::npos 作为“长度”传递 => substr 记录了读取所有内容直到结束的行为。 b) substr 被赋予“string::npos + 1”并且没有长度:string::npos 被记录为具有 -1 的值,因此计算结果为 0 => 字符串的开头和长度的默认值 @ 987654337@ 是npos => 也适用于“仅文件名”cplusplus.com/reference/string/string/substr cplusplus.com/reference/string/string/npos
    【解决方案10】:

    具有统一初始化和匿名内联 lambda 的 C++11 变体(受 James Kanze 版本的启发)。

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

    但它不会删除文件扩展名。

    【讨论】:

    • 短小精悍,虽然它只适用于非 Windows 路径。
    • 您可以随时将 lambda return 更改为 return c == '/' || c == '\\'; 以使其在 Windows 上运行
    • 要处理“”、“///”和“dir1/dir2/”等路径,在上面的return语句之前添加以下代码(参见POSIX basename()):@987654323 @
    【解决方案11】:

    boost filesystem 库也可用作 experimental/filesystem 库,并已合并到 C++17 的 ISO C++ 中。你可以这样使用它:

    #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 对象。

    【讨论】:

      【解决方案12】:

      这是唯一真正最终对我有用的东西:

      #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 建议的,但不适用于 wchar_t*, VS 企业 2015

      _splitpath 也可以,但我不喜欢猜测我需要多少 char[?] 字符;我猜有些人可能需要这种控制。

      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 不需要任何包含。这两种解决方案都不需要外部库(如 boost)。

      【讨论】:

        【解决方案13】:
        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);
        }
        

        【讨论】:

          【解决方案14】:

          我会...

          从字符串末尾向后搜索,直到找到第一个反斜杠/正斜杠。

          然后从字符串末尾再次向后搜索,直到找到第一个点(.)

          然后您就有了文件名的开头和结尾。

          简单...

          【讨论】:

          • 这不适用于我知道的任何系统。 (接受'\\' 作为路径分隔符的一个系统使用'/',所以你需要匹配任何一个。)我不确定你会期待什么。
          • 好的,所以修改它以匹配任何一个,没什么大不了的。并期待第一个点 (.)
          • 你仍然需要找到最后一个点,而不是第一个。 (反向迭代器是你的朋友!)
          • 啊,是的,好点子。所以对于 file.ext.ext 那么你会想要提取 file.ext 不是吗。 :)
          • 大概。这是通常的约定,无论如何:my.source.cpp 被编译为 my.source.obj,例如(将扩展名 .cpp 替换为 .obj)。
          【解决方案15】:

          你可以使用 std::filesystem 做得很好:

          #include <filesystem>
          namespace fs = std::experimental::filesystem;
          
          fs::path myFilePath("C:\\MyDirectory\\MyFile.bat");
          fs::path filename = myFilePath.stem();
          

          【讨论】:

            【解决方案16】:
            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 包含文件名。

            【讨论】:

            • 哇 - 从路径中“获取文件名”的代码很多...... :)
            • @Nim 我的印象也是如此。在我自己的代码中,我使用单行代码:boost::filesystem::path( path ).filename()
            • 我有一个包含该代码的 CFileInfo 类。我只是在这里转储了代码,因为它已经过测试,我不想冒任何风险......你可以使用这个示例中的大约 5 行代码。
            【解决方案17】:

            不要使用_splitpath()_wsplitpath()。它们不安全,而且已经过时了!

            改为使用他们的安全版本,即_splitpath_s()_wsplitpath_s()

            【讨论】:

              【解决方案18】:

              这也应该有效:

              // 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(带有 split、trim 等)、QFile、QPath、QFileInfo 等来操作文件、文件名和目录。当然,它也是跨平台的。

              【讨论】:

              • 为了您的代码的未来读者,请使用具有有意义名称的临时变量,而不是将所有内容都塞进一行代码中(当您使用它时,请将所有这些封装到一个函数getFilename 或类似的东西)。
              • 已编辑。但关键是要简短,因为已经给出了几个可行的答案。
              • 我认为这是错误的。你不应该用“strPath.find_last_of(".") - iLastSeparator”替换最后一部分:“strPath.size() - strPath.find_last_of(".")”
              • @taktak004 你是对的,应该是` return strPath.substr( (iLastSeparator = strPath.find_last_of("/")) != std::string::npos ? iLastSeparator + 1 : 0 , strPath.find_last_of(".") - iLastSeparator );`
              【解决方案19】:

              一个非常简单而简短的函数,它返回我创建的不使用依赖项的文件名+路径:

              const char* GetFileNameFromPath(const char* _buffer)
              {
                  char c;
                  int  i;
                  for (i = 0; ;++i) {
                      c = *((char*)_buffer+i);
                      if (c == '\\' || c == '/')
                          return GetFileNameFromPath((char*)_buffer + i + 1);
                      if (c == '\0')
                          return _buffer;
                  }
                  return "";
              }
              

              要仅获取文件名不带扩展名,您可以将c == '\0' 更改为c == '.'

              【讨论】:

                【解决方案20】:

                长期以来,我一直在寻找能够正确分解文件路径的函数。对我来说,这段代码在 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:  ''
                

                我希望这对你也有帮助:)

                【讨论】:

                  【解决方案21】:

                  shlwapi.lib/dll 在内部使用HKCU 注册表配置单元。

                  如果您正在创建库或产品没有 UI,最好不要链接到 shlwapi.lib。如果您正在编写一个库,那么您的代码可以在任何项目中使用,包括那些没有 UI 的项目。

                  如果您正在编写在用户未登录时运行的代码(例如,服务 [或其他] 设置为在启动或启动时启动),则没有 HKCU。最后,shlwapi 是结算函数;并因此在更高版本的 Windows 中被弃用。

                  【讨论】:

                    【解决方案22】:

                    一个缓慢但直接的正则表达式解决方案:

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

                    【讨论】:

                      【解决方案23】:

                      我实现了一个可能满足您需求的功能。 它基于 string_view 的 constexpr 函数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__);
                      

                      【讨论】:

                        猜你喜欢
                        • 2011-11-16
                        • 2012-10-25
                        • 2023-03-26
                        • 1970-01-01
                        • 2015-04-22
                        • 2014-07-24
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多