带有boost directory_iterator的Max_element [英] Max_element with boost directory_iterator
问题描述
我使用boost的文件系统和std :: max_element()来查找给定目录中名字最长的文件:
I am using boost's filesystem and std::max_element() to find a file with the longest name in a given directory:
#include <iostream>
#include <iterator>
#include <algorithm>
#include <string>
#include <boost/filesystem.hpp>
using namespace std;
using namespace boost::filesystem;
bool size_comp( directory_entry de1, directory_entry de2 )
{
return de1.path().string().size() < de2.path().string().size();
}
int main(int argc, char* argv[])
{
path p (argv[1]); // p is a path to a directory
directory_iterator itr (p);
directory_iterator itr_end;
directory_iterator itr_max=::max_element(itr,itr_end,size_comp);
int max_size = itr_max->path().string().size();
cout << "Longest file name: " << itr_max->path() << " has "
<< max_size << " characters" << endl;
return 0;
}
对于带有文件cat.dat,mouse.dat,elephant的目录。 dat的输出是:
For the directory Animals with files cat.dat, mouse.dat, elephant.dat the output is:
Longest file name: Animals/mouse.dat has 17 characters
这既不是最长也不是最短的文件名。上面的代码出了什么问题?
This is neither the longest nor the shortest filename. What's wrong with the code above?
推荐答案
boost :: filesystem :: directory_iterator
share state 。实现声明实现由 boost :: shared_ptr
管理,以允许InputIterators所需的浅拷贝语义。因此,当算法(例如 std :: max_element
)迭代 [first,last)
时,结果迭代器使用第一个
的每个增量间接修改,因为迭代器将与首先共享状态
。
The boost::filesystem::directory_iterator
shares state. The implementation states the implementation is managed by boost::shared_ptr
to allow shallow-copy semantics required for InputIterators. Thus, when an algorithm, such as std::max_element
, iterates over [first,last)
, the result iterator is indirectly modified with each increment of first
, as the result iterator will share state with first
.
要解决此问题,请考虑存储 boost :: filesystem :: directory_entry
。例如,可以从 directory_iterator
范围构造 std :: vector< directory_entry>
,然后将向量传递给的std :: max_element
。或者,手动编写算法可能更容易。
To resolve this, consider storing boost::filesystem::directory_entry
throughout the overall algorithm. For example, one could construct a std::vector<directory_entry>
from a directory_iterator
range, then pass the vector to std::max_element
. Alternatively, it may be easier to write the algorithms by hand.
这是一个完整的示例,显示了在当前目录下运行的两种方法。
Here is a complete example showing both approaches, operating on the current directory.
#include <algorithm> // std::copy, std::max_element
#include <iterator> // std::back_inserter
#include <iostream> // std::cout, std::endl
#include <vector>
#include <utility> // std::make_pair
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
namespace fs = boost::filesystem;
bool size_comp(const fs::directory_entry& lhs,
const fs::directory_entry& rhs)
{
return lhs.path().string().size() < rhs.path().string().size();
}
/// @brief Finds max by copying all directory entries.
fs::directory_entry max_full_copy(
fs::directory_iterator first,
fs::directory_iterator last)
{
// Extract directory_entries from directory_iteartor.
std::vector<fs::directory_entry> entries;
std::copy(first, last, std::back_inserter(entries));
// Find max element.
return *std::max_element(entries.begin(), entries.end(), &size_comp);
}
/// @brief Finds max by only storing a copy of the max entry.
fs::directory_entry max_single_copy(
fs::directory_iterator first,
fs::directory_iterator last)
{
fs::directory_entry result;
BOOST_FOREACH(fs::directory_entry& current, std::make_pair(first, last))
{
if (size_comp(result, current))
result = current;
}
return result;
}
int main()
{
std::cout << max_full_copy(fs::directory_iterator("."),
fs::directory_iterator()) << "\n"
<< max_single_copy(fs::directory_iterator("."),
fs::directory_iterator()) << std::endl;
}
输出示例:
[tsansbury@localhost tmp]$ ls
file_four file_one file_three file_two
[tsansbury@localhost tmp]$ ../a.out
"./file_three"
"./file_three"
这篇关于带有boost directory_iterator的Max_element的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!