2011-12-04 9 views
7

मैं एसटीएल एल्गोरिदम का उपयोग करके यह कैसे करूं?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 बाइट्स से कम होने पर इससे बहुत सारे कचरे हो सकते हैं।

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<> उपयोग कर सकते हैं:

किसी भी मामले में, अगर आप चाहते मज़बूती से कॉपी करने के लिएn आइटम तक, आप अपने खुद के समारोह लिखने के लिए की आवश्यकता होगी इटरेटर के समान दूरी प्रकार को मजबूर करें।

+0

+1 जेनेरिक इटरेटर एल्गोरिदम और 'std :: iterator_traits' का उल्लेख करने के लिए। –

+0

'आउट' शायद एक अलग टेम्पलेट तर्क होना चाहिए। – pmr

+0

@pmr: वास्तव में। इसके बिना, यह प्रश्न में पोस्ट किए गए उपयोग के मामले के लिए काम नहीं करेगा (उदाहरण के लिए 'std :: back_inserter()') का उपयोग करना। मैं कोड संपादित करूंगा। –

0

आप एक विशेष back_insert_iterator का उपयोग कर सकते हैं जो एक अनुमान के आधार पर संचालन को त्याग देता है।

यह कोड stdlib और अनुकूलित किए गए के जीसीसी कार्यान्वयन से लापरवाही से लिया गया है। एक सी ++ 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

इसे व्यक्तिगत रूप से न लें, लेकिन, ओह। –

+0

@ बेंजामिन लिंडली नाह, कभी नहीं। मैं एल्गोरिदम को संशोधित करने के विपरीत दृष्टिकोण की तलाश करने के लायक हूं। नतीजा यह भी सामान्य उद्देश्य नहीं है क्योंकि यह कंटेनर पर काम करता है। मैं वास्तव में 'शायद' मान के आधार पर 'जेनरेट' का संस्करण रखना चाहता हूं। इससे यह वास्तव में आसान हो जाएगा। – pmr

+0

यह भविष्यवाणी का बिल्कुल उपयोग नहीं करता है। अगर भविष्य में स्ट्रीमर को पॉइंटर संग्रहीत किया जाता है तो यह काम कर सकता है, ताकि वह ईओफ़ की जांच कर सके। मूल्य तर्क अधिक जानकारी नहीं देगा। – UncleBens

संबंधित मुद्दे