2011-12-04 57 views
7

我會如何使用STL算法做到這一點?copy_n或直到eof?

std::ifstream file(filename); 

std::vector<unsigned char> buf; 
for(auto file_it = std::istreambuf_iterator<char>(file); file_it != std::istreambuf_iterator<char>() && buf.size() < 2048; ++file_it) 
    buf.push_back(*file_it); 

注意buf.size() < 2048

例如如果我做了以下事情會發生什麼,並且文件小於2048字節?

std::copy_n(std::istreambuf_iterator<char>(file), 2048, std::back_inserter(buf)); 
+0

如果文件較大,會發生什麼情況?其餘的部分是否被丟棄,或者是否需要迭代器到仍然需要讀取的部分的開頭? – pmr

+0

一旦讀取了所需數量的字節,就會丟棄ifstream。 – ronag

+0

這樣就可以有一個單獨的迭代器而不是算法。 – pmr

回答

1

文檔一樣說,std::copy_n()將複製正是n項目。它將繼續讀取迭代器所指序列的末尾。不過,我不確定標準對istreambuf_iterator<>的評價。這可能是未定義的行爲,但流可能會在末尾產生大量eof()的副本。這可能會導致大量的垃圾,當有少於2048字節可用。

在任何情況下,如果要複製可靠高達n項目,你需要編寫自己的功能:

template<typename I1, typename I2, typename size_type> 
I copy_upto_n (I1 begin, I1 end, size_type n, I2 out) 
{ 
    for (size_type i=0; (i < n) && (begin != end); ++i) 
    { 
     *out++ = *begin++; 
    } 
    return out; 
} 

有些人可能會使用std::iterator_traits<>,而不是額外的模板參數強制迭代器的距離類型相同。

+0

+1對於泛型迭代器算法和提及'std :: iterator_traits'。 –

+0

'out'應該可能是一個單獨的模板參數。 – pmr

+0

@pmr:確實。沒有這一點,它不適用於問題中發佈的用例(例如使用'std :: back_inserter()')。我將編輯代碼。 –

0

您可以使用丟棄基於謂詞的操作的特殊back_insert_iterator

這段代碼已經無恥地從stdlib的 的GCC實現中進行了修改。 C++ 03版本在分配中只需要一個 Container::const_reference

template<typename Container, typename Predicate> 
class discarding_back_inserter 
    : public iterator<output_iterator_tag, void, void, void, void> 
{ 
    Container* container; 
    Predicate p; 
public: 
    typedef Container   container_type; 

    explicit 
    back_insert_iterator(Container& x, Predicate p) : container(&__x), p(p) { } 

    back_insert_iterator& 
    operator=(const typename Container::value_type& value) 
    { 
     if(*container) 
     container->push_back(__value); 
     return *this; 
    } 

    back_insert_iterator& 
    operator=(typename _Container::value_type&& value) 
    { 
     if(*container) 
     container->push_back(std::move(__value)); 
     return *this; 
    } 

    back_insert_iterator& 
    operator*() 
    { return *this; } 

    back_insert_iterator& 
    operator++() 
    { return *this; } 

    back_insert_iterator 
    operator++(int) 
    { return *this; } 
}; 
+1

不要拿這個人,但是,eww。 –

+0

@BenjaminLindley Nah,從來沒有。我只是認爲尋找相反的方法來修改算法是值得的。因爲它在容器上工作,所以結果甚至不是很通用。我真的很想擁有一個基於'Maybe'值的'generate'版本。這會讓這很容易。 – pmr

+0

這根本不使用謂詞。如果謂詞存儲一個指向流的指針,它可以工作,以便它可以檢查eof。價值觀念不會提供太多信息。 – UncleBens