2013-07-30 93 views
1

我使用升壓轉換器的文件系統和std :: max_element()來查找最長名的文件在指定目錄:Max_element與升壓directory_iterator

#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,鼠標.DAT,elephant.dat輸出爲:

Longest file name: Animals/mouse.dat has 17 characters 

這既不是最長的,也不是最短的文件名。上面的代碼有什麼問題?

回答

3

boost::filesystem::directory_iterator共享狀態。實現狀態由boost::shared_ptr進行管理,以允許InputIterator所需的淺拷貝語義。因此,當一個算法(如std::max_element)迭代到[first,last)時,結果迭代器將間接修改,每增量爲first,結果迭代器將與first共享狀態。

要解決此問題,請考慮在整個算法中存儲boost::filesystem::directory_entry。例如,可以從directory_iterator範圍構造std::vector<directory_entry>,然後將該向量傳遞給std::max_element。或者,手動編寫算法可能會更容易。

這是一個完整的示例,顯示了在當前目錄下進行操作的兩種方法。

[[email protected] tmp]$ ls 
file_four file_one file_three file_two 
[[email protected] tmp]$ ../a.out 
"./file_three" 
"./file_three"

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

和示例與輸出運行