2010-09-30 24 views
6

मैं एक वेक्टर के लिए एक फ़ाइल की सामग्री की प्रतिलिपि चाहते हैं, मैं ऐसा कर सकते हैं:किसी फ़ाइल से एसटीएल-वेक्टर में एक निश्चित संख्या में वर्णों की प्रतिलिपि कैसे कॉपी करें?

std::ifstream file("path_to_file"); 
std::vector<char> buffer(std::istream_iterator<char>(file), 
         std::istream_iterator<char>()); 

मेरा प्रश्न है, मैं ऐसा करने के तरीके अगर मैं केवल पहले n वर्ण की प्रतिलिपि बनाना चाहते हैं?

संपादित करें मैं अपना खुद का संस्करण copy लिख सकता हूं, लेकिन क्या मौजूदा घटक का उपयोग करके ऐसा करने का कोई तरीका है?

+0

सुंदर नहीं है लेकिन repl_copy_if का उपयोग कर सकता है, यह जांचने के लिए पूर्वानुमान का उपयोग करें कि आपने एन वर्णों की प्रतिलिपि बनाई है या नहीं !! – DumbCoder

उत्तर

6

रूप Steve द्वारा नोट किया गया था, इस copy_n() है, जो, एक निरीक्षण के कारण, वर्तमान मानक पुस्तकालय में नहीं है की आवश्यकता होगी, लेकिन सी ++ 1x में होगा। आप एक अपने आप को आसानी से लागू कर सकते हैं, यहाँ एक मैं सही होने के लिए विश्वास है कि है:

template<class InIt, class OutIt> 
OutIt copy_n(InIt src, OutIt dest, size_t n) 
{ 
    if (!n) return dest; 
    *dest = *src; 
    while (--n) 
    *++dest = *++src; 
    return ++dest; 
} 

ध्यान दें कि std::copy_n() इनपुट इटरेटर मान लिया जाता है n वस्तुओं वितरित करने के लिए सक्षम होने के लिए। फ़ाइल से पढ़ते समय, यह समस्याग्रस्त हो सकता है।


std::copy_n() के अनुपस्थित, आप std::generate_n इस्तेमाल कर सकते हैं।

template< typename InIt > 
struct input_generator { 
    typedef std::iterator_traits<InIt>::value_type value_type; 

    input_generator(InIt begin, InIt end) begin_(begin), end_(end) {} 

    value_type operator()() 
    { 
    assert(it_ != end); 
    return *it_++; 
    } 

    Init begin_; 
    Init end_; 
}; 


std::vector<char> buffer; 
buffer.reserve(42); 

std::generate_n(std::back_inserter(buffer) 
       , 42 
       , input_generator(std::istream_iterator<char>(file)) 
       , input_generator(std::istream_iterator<char>())); 

हालांकि, मैं avakar showed के रूप में फ़ाइल से सीधे पढ़ने से अधिक लाभ के रूप में देखते नहीं है।

+0

एसबीआई का कार्यान्वयन स्ट्रीम इटरेटर्स के लिए सही नहीं था, जो दोनों वृद्धि और प्रारंभिकरण पर धारा से पढ़ा गया था। मैंने ठीक कर दिया। –

+0

@ डॉन: धन्यवाद। यही कारण है कि यहां तक ​​कि इस तरह के सरल एल्गोरिदम एसडीडी प्रयोगशाला में होना चाहिए - सूक्ष्म बग को सबसे सरल लोगों में भी छोड़ना आसान है। – sbi

0
char *buffer = new char[n]; 
file.read(buffer,n); 
std::vector<char> myVector 
for (int i=0;i<n;i++) myVector.push_back(buffer[i]); 
delete [] buffer; 

// myVector now holds the first n bytes of file. 

यह सुंदर या तेज तरीका नहीं हो सकता है, लेकिन यह मैं इसे कैसे करना होगा है।

+0

एक छोटा सा सिर्फ 'std :: vector myVector (buffer, n); ' – Default

+3

होना चाहिए जो' std :: vector myVector (बफर, बफर + एन) होना चाहिए;' (और फ़ोरलोप छोड़ें) – Default

+1

सीधे (पर्याप्त आकार में) वेक्टर में पढ़ने के साथ क्या गलत है? – sbi

1

"एसटीएल रास्ता" copy_n का उपयोग करना है, जो एसटीएल में है लेकिन सी ++ मानक नहीं है।

+0

उचित लगता है, लेकिन पोर्टेबिलिटी चिंता का विषय है तो सलाह नहीं दी जाती है। साथ ही, क्या यह सी ++ x0 में मानक में जोड़ा गया है? –

+0

हां, यह सी ++ 0x में है। यदि पोर्टेबिलिटी चिंता का विषय है, तो एसटीएल तरीके से चीजें न करें, उन्हें सी ++ मानक तरीका करें ;-) इस मामले में शायद इसका मतलब है कि आप अपने नामस्थान में कॉपी_एन को लागू कर सकते हैं, शायद कहीं और से कार्यान्वयन करके। –

8

सिकंदर बताते हैं के रूप में, सबसे तेज़ तरीका होगा

std::vector<char> buffer(n); 
file.read(&buffer[0], n); 

C++ 0x में, आप &buffer[0] के बजाय buffer.data() उपयोग कर सकते हैं; उत्तरार्द्ध ने n == 0 पर व्यवहार को अपरिभाषित किया है।

0

@ एसबीआई के कारण क्रेडिट, मैं लगभग generate_n भूल गया।

streambuffile अंदर एक समारोह snextc जो अगले वर्ण देता है, एक जनरेटर समारोह के रूप में यह योग्यता, एक बार अपने निहित this तर्क ही है है।

generate_n(back_inserter(buffer), 42, 
      tr1::bind(tr1::mem_fn(&streambuf::snextc), file.rdbuf())); 

vector के लिए, बस सीधे पढ़ें। यह deque या जो भी हो, के लिए अच्छा है।

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

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