更新 2 正如帕斯卡曾经说过的:
“我把这封信写得比平时长了,因为我没时间把它写短”
我终于找到时间缩短它了!现在,它不再需要提升:
3。使用std::string::find_last_of
您可以非常直接地使用它。这里本质上是一个单行线——除了需要以与字符类型无关的方式指定分隔符集。
在本例中,我选择使用 boost::string_ref 来返回对输入字符串子范围的用户友好的 const 引用。
请注意,使用boost::string_ref 是可选的,不需要链接依赖项。如果您愿意,可以将其更改为 std::pair<iterator, iterator>:
Live On Coliru
#include <string>
#include <boost/utility/string_ref.hpp>
template <typename StringT, typename C = typename StringT::value_type>
boost::basic_string_ref<C> GetFilename(StringT const& path) {
static const C separators[4] = { '\\', '/', ':', 0 };
return boost::basic_string_ref<C>(path).substr(path.find_last_of(separators) + 1);
}
#include <iostream>
int main() {
for (std::string fname : {
"/tmp/somedir/../other//./beautiful filenames.txt.0",
"simple.txt",
"",
})
{
std::cout << "'" << fname << "' -> '" << GetFilename(fname) << "'\n";
}
for (std::wstring fname : {
L"D:\\Program Files (64)\\Something Else Entirely\\but works.just-the-same.exe",
L"\\UNCNAME\\Something Else Entirely\\network.dat",
L"D://testing/test123",
L"http://user:password@hostname:port/test123/resource?query=parameter#yo"
L"E:beautiful filenames.txt.0",
L"simple.txt",
L"",
})
{
std::wcout << "'" << fname << "' -> '" << GetFilename(fname) << "'\n";
}
}
打印
'/tmp/somedir/../other//./beautiful filenames.txt.0' -> 'beautiful filenames.txt.0'
'simple.txt' -> 'simple.txt'
'' -> ''
'D:\Program Files (64)\Something Else Entirely\but works.just-the-same.exe' -> 'but works.just-the-same.exe'
'\UNCNAME\Something Else Entirely\network.dat' -> 'network.dat'
'D://testing/test123' -> 'test123'
'http://user:password@hostname:port/test123/resource?query=parameter#yo' -> 'resource?query=parameter#yo'
'E:beautiful filenames.txt.0' -> 'beautiful filenames.txt.0'
'simple.txt' -> 'simple.txt'
'' -> ''
更新由于您希望无复制行为,这里有一个使用 Boost Regex 的版本
2。使用 Boost 正则表达式
此解决方案也返回适当字符类型的string_ref。
事实证明,这种方法比要求的要重得多,但您可能仍然希望看到/使用它来完成不那么琐碎的任务。
Live On Coliru
#include <boost/regex.hpp>
#include <boost/utility/string_ref.hpp>
template <typename StringT, typename C = typename StringT::value_type>
boost::basic_string_ref<C> GetFilename(StringT const& path) {
// it's quite tricky to initialze the pattern generically:
static auto re = [] {
char const pattern[] = "[^\\\\/:]*$";
std::basic_string<C> spattern(pattern, pattern + sizeof(pattern)-1);
return boost::basic_regex<C>(spattern, boost::regex_constants::optimize);
}();
// the rest is plain sailing:
boost::match_results<typename StringT::const_iterator> mr;
if (boost::regex_search(path.begin(), path.end(), mr, re) && mr[0].matched)
return { &*(mr[0].first), size_t(mr[0].length()) };
return path;
}
#include <iostream>
int main() {
std::string fname = "/tmp/somedir/../other//./beautiful filenames.txt.0";
std::cout << GetFilename(fname) << "\n";
std::wstring wname = L"D:\\Program Files (64)\\Something Else Entirely\\but works.just-the-same.exe";
std::wcout << GetFilename(wname) << "\n";
}
打印:
beautiful filenames.txt.0
but works.just-the-same.exe
1。使用 Boost 文件系统
旧答案是:这似乎是 Boost Filesystem 的工作。
Live On Coliru
#include <boost/filesystem.hpp>
#include <iostream>
namespace fs = boost::filesystem;
template <typename StringT>
StringT GetFilename(StringT const& path) {
return fs::path(path).filename().string<StringT>();
}
int main() {
#ifndef _WIN32
std::string fname = "/tmp/somedir/../other//./beautiful filenames.txt.0";
std::cout << GetFilename(fname) << "\n";
#else
std::wstring wname = L"D:\\Program Files (64)\\Something Else Entirely\\but works.just-the-same.exe";
std::wcout << GetFilename(wname) << "\n";
#endif
}
这应该打印出来
beautiful filenames.txt.0
或
but works.just-the-same.exe
取决于您的平台