请帮忙。 我有一个名字的文件:
X_ab_LOTA123.png
然后我有了这段代码,我可以从文件名中提取数字123。一切正常。
#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/lexical_cast.hpp>
namespace bfs = boost::filesystem;
namespace ba = boost::adaptors;
using std::string;
using namespace std;
void find(const bfs::path& imageDirPath, const boost::regex& filter)
{
boost::smatch result;
for (auto& entry : boost::make_iterator_range(bfs::directory_iterator(imageDirPath), {})
| ba::filtered(static_cast<bool (*)(const bfs::path &)>(&bfs::is_regular_file))
| ba::filtered([&](const bfs::path &path){ return boost::regex_match(path.filename().string(), result, filter); })
)
{
int32_t num = boost::lexical_cast<int32_t>(result[1]);
cout << "found : " << num << " = " << entry.path().string() << endl;
}
}
int main()
{
const boost::regex defaultFilter( "X_ab_LOTA(\\d{3}).png" );
const bfs::path path(".");
find(path, defaultFilter);
}
结果是:
发现:123 =。\ X_ab_LOTA123.png
但是,如果我将文件重命名为:
X_a_LOTA123.png
即。我删除'b'字母,我也相应地更改过滤器:
const boost::regex defaultFilter( "X_a_LOTA(\\d{3}).png" );
然后程序崩溃了!
我得到了bad_cast异常!
我在这里做错了什么?代码很简单。但它仅适用于某些情况,对于其他名称和匹配模式,它会崩溃。
请帮忙。
答案 0 :(得分:1)
你有未定义的行为。您的范围过滤器有副作用,但在检查结果之前,副作用可能已被另一个范围输入覆盖。
因此,当result[1]
可能无效(存在不匹配)或甚至可能引用其他路径时,您正在使用path const&
。更糟糕的是,在这种情况下,第二个过滤器表达式所引用的entry
引用已经过时(它当时是从path.filename().string()
循环变量派生的!)。
最糟糕的是:一旦你编写void find(const bfs::path& imageDirPath, const boost::regex& filter)
{
for (auto entry : bfs::directory_iterator(imageDirPath)) {
if (!is_regular_file(entry))
continue;
auto fname = entry.path().filename().string(); // keep alive longer than result!
boost::smatch result;
if (boost::regex_match(fname, result, filter)) {
int32_t num = boost::lexical_cast<int32_t>(result[1]);
cout << "found : " << num << " = " << entry.path().string() << endl;
}
}
}
,你的代码就注定了,因为它返回一个临时的,并且在封闭的完整表达式的末尾被破坏了。
使用调试迭代器或地址清理程序运行代码可能会提醒您这些问题
简化:
[1]
实际上,您可以添加匹配组const
有效并且在使用之前已成功匹配的检查,因为您的函数不能控制使用的正则表达式。