2008-10-30 37 views
8

我試圖代碼相反的動作這樣的:如何使用std :: copy讀取任意數量的值?

std::ostream outs; // properly initialized of course 
std::set<int> my_set; // ditto 

outs << my_set.size(); 
std::copy(my_set.begin(), my_set.end(), std::ostream_iterator<int>(outs)); 

它應該是這樣的:

std::istream ins; 

std::set<int>::size_type size; 
ins >> size; 

std::copy(std::istream_iterator<int>(ins), std::istream_iterator<int>(ins) ???, std::inserter(my_set, my_set.end())); 

但我堅持的「結束」迭代器 - 輸入interators能不使用std :: advance,也不能使用兩個源碼相同的流...

有沒有什麼優雅的方法來解決這個問題?當然,我可以使用循環,但也許有一些更好:)

回答

3

您可以從istream_iterator <T>中派生出來。
雖然使用Daemin generator method是另一種選擇,但我會直接生成集合而不是使用中間向量。

#include <set> 
#include <iterator> 
#include <algorithm> 
#include <iostream> 


template<typename T> 
struct CountIter: public std::istream_iterator<T> 
{ 
    CountIter(size_t c) 
     :std::istream_iterator<T>() 
     ,count(c) 
    {} 
    CountIter(std::istream& str) 
     :std::istream_iterator<T>(str) 
     ,count(0) 
    {} 

    bool operator!=(CountIter const& rhs) const 
    { 
     return (count != rhs.count) && (dynamic_cast<std::istream_iterator<T> const&>(*this) != rhs); 
    } 
    T operator*() 
    { 
     ++count; 
     return std::istream_iterator<T>::operator*(); 
    } 

    private: 
     size_t count; 
}; 

int main() 
{ 
    std::set<int>  x; 

    //std::copy(std::istream_iterator<int>(std::cin),std::istream_iterator<int>(),std::inserter(x,x.end())); 
    std::copy(
       CountIter<int>(std::cin), 
       CountIter<int>(5), 
       std::inserter(x,x.end()) 
      ); 
} 
0

(編輯:我應該讀的問題接近...)

雖然有點懷疑,你可以有大約得到正確的行爲該文件中的一個條目將使第一個循環「失敗」,然後清除流上的故障位並開始讀取更多。

數據,沒有一個明確的大小,但這樣

 
1 1 2 3 5 8 Fibb 

美聯儲將下面的代碼似乎做了我的意思,至少在與STLPort的VS2005。

 
typedef std::istream_iterator < int, char, std::char_traits ,ptrdiff_t> is_iter; 
std::copy(is_iter(cin), is_iter(), inserter(my_set,my_set.end())); 
cin.clear(); 
std::cin >> instr; 
+0

呵呵,你說得對,它是一種懷疑和最重要的 - 它不會在二進制流:) – 2008-10-30 14:01:10

0

是sdg,但是當我想在該文件/流中使用其他數據結構?我應該明確地寫在這裏,我想在這個集合之後存儲另一個東西,這也是我存儲大小的原因。

2

錯誤... copy_n()算法?

+0

「這個功能是一個SGI擴展;它不是C++標準的一部分。「 這是非常真實的,它至少在VS2008中缺少。但很好,我幾乎想責怪自己怎麼可能忽略它;) – 2008-10-30 14:00:02

+1

C++ 0x是 – 2008-12-11 20:07:32

2

看着這一點,我不認爲直接讀入一個集合會起作用,因爲你需要調用插入來實際添加元素(我可能會誤解,這是在凌晨這裏) 。雖然看着VS2005的STL文件簡要我認爲使用generate_n功能應該工作的東西,比如:

std::istream ins; 
std::set<int> my_set; 
std::vector<int> my_vec; 

struct read_functor 
{ 
    read_functor(std::istream& stream) : 
     m_stream(stream) 
    { 
    } 

    int operator() 
    { 
     int temp; 
     m_stream >> temp; 
     return temp; 
    } 
private: 
    std::istream& m_stream; 
}; 

std::set<int>::size_type size; 
ins >> size; 
my_vec.reserve(size); 

std::generate_n(my_vec.begin(), size, read_functor(ins)); 
my_set.insert(my_vec.begin(), my_vec.end()); 

希望這要麼解決你的問題,或使你確信環路是不是在隆重的那麼糟糕事物的計劃。

+1

爲什麼使用向量作爲中間函數?只需使用生成器插入集合(使用std :: inserter)。 – 2008-10-30 15:41:27

+0

當我編寫答案時已經很晚了,當時它並沒有想到。我想你會使用插件,但它仍然需要創建一個完整的其他類,所以對於我來說,循環會更簡單,可能看起來更好。 – Daemin 2008-10-30 22:27:06

1

如何使用備用迭代器進行遍歷,然後使用函數對象(或lambda)來填充容器?

istream ins; 
set<int>::size_type size; 
set<int> new_set; 
ins >> size; 
ostream_iterator<int> ins_iter(ins); 

for_each(counting_iterator<int>(0), counting_iterator<int>(size), 
    [&new_set, &ins_iter](int n) { new_set.insert(*ins_iter++); } 
); 

當然,這裏假定你有一個C++ 0x兼容的編譯器。

順便說一句,'counting_iterator <>'是Boost.Iterator的一部分。

0

感謝您的想法傢伙。即使這些事情看起來很酷,我當然不會爲創建新類/迭代器,它;-)我更好地理解爲什麼SGI決定將現在的「copy_n」算法:)

3

用途:

std::copy(std::istream_iterator<int>(ins), 
      std::istream_iterator<int>(), 
      std::inserter(my_set, my_set.end()) 
     ); 

注意空參數:

std::istream_iterator<int>(); 
1

或者你可以這樣做:

my_set.insert(std::istream_iterator<int>(ins), std::istream_iterator<int>()); 
相關問題