2010-04-23 23 views
9

मैं std :: सूची में संग्रहीत डेटा तत्वों का उपयोग करके एक स्ट्रिंग बनाने की कोशिश कर रहा हूं, जहां मैं केवल तत्वों के बीच अल्पविराम रखना चाहता हूं (यानी, यदि तत्व {ए, बी हैं , सी, डी} सूची में, परिणाम स्ट्रिंग "ए, बी, सी, डी" होना चाहिएstd :: सूची इटरेटर: अगला तत्व

इस कोड काम नहीं करता है:।

typedef std::list< shared_ptr<EventDataItem> > DataItemList; 
// ... 
std::string Compose(DataItemList& dilList) 
{ 
    std::stringstream ssDataSegment; 
    for(iterItems = dilList.begin(); 
     iterItems != dilList.end(); 
     iterItems++) 
    { 
     // Lookahead in list to see if next element is end 
     if((iterItems + 1) == dilList.end()) 
     { 
      ssDataSegment << (*iterItems)->ToString(); 
     } 
     else 
     { 
      ssDataSegment << (*iterItems)->ToString() << ","; 
     } 
    } 
    return ssDataSegment.str(); 
} 

मैं कैसे मिलता है "पर-अगली आइटम "एक std :: सूची में एक iterator का उपयोग कर? मैं उम्मीद करता हूं कि यह एक लिंक की गई सूची है, मैं अगले आइटम पर क्यों नहीं मिल सकता?

+1

आपको अपने 'फॉर लूप' में भी एक त्रुटि है: 'iterItems = dilList.end();' 'iterItems होना चाहिए! = DilList.end();'। –

+0

@Fred - True। यह बात बताने के लिए धन्यवाद। –

+0

संभावित डुप्लिकेट: http://stackoverflow.com/questions/3673684/peek-the-next-element-in-stl-container –

उत्तर

15

आप it + N नहीं कर सकते क्योंकि आपके पास सूची इटरेटर के लिए कोई यादृच्छिक पहुंच नहीं है। आप सूची इटरेटर्स के साथ एक समय में केवल एक ही कदम उठा सकते हैं (ये बिडरेक्शनल इटरेटर्स हैं)।

आप boost::next और boost::prior

// Lookahead in list to see if next element is end 
if(boost::next(iterItems) == dilList.end()) 
{ 

उपयोग कर सकते हैं या आप पहले अल्पविराम मुद्रित कर सकते हैं:

std::string Compose(DataItemList& dilList) 
{ 
    std::stringstream ssDataSegment; 
    for(iterItems = dilList.begin(); 
     iterItems != dilList.end(); 
     ++iterItems) 
    { 
     if(iterItems != diList.begin()) 
      ssDataSegment << ","; 
     ssDataSegment << (*iterItems)->ToString(); 
    } 
    return ssDataSegment.str(); 
} 
+1

नोट: अगला() और पिछला() boost/utility.hpp में हैं। जब तक वे कहीं और नहीं जाते। –

+0

बढ़ावा :: अगला() समाधान सुरुचिपूर्ण है। बहुत धन्यवाद। –

+0

तकनीकी रूप से, यह बढ़ावा है :: पहले()। –

12

मुझे विश्वास है कि एक सूची इटरेटर द्विदिश है, लेकिन नहीं रैंडम एक्सेस। इसका मतलब है कि आप ++ और - कर सकते हैं लेकिन इसमें जोड़ या घटा नहीं सकते हैं।

अगला पुनरावर्तक प्राप्त करने के लिए, एक प्रति बनाएं और इसे बढ़ाएं।

2

आप का उपयोग करके पूरी तरह इस समस्या से बचने कर सकते हैं:

std::string Compose(DataItemList& dilList) 
{ 
    std::stringstream ssDataSegment; 
    for(iterItems = dilList.begin(); iterItems != dilList.end(); iterItems++) 
    { 
     ssDataSegment << (*iterItems)->ToString() << ","; // always write "," 
    } 
    std::string result = ssDataSegment.str(); 
    return result.substr(0, result.length()-1); // skip the last "," 
} 

आप सबसे पहला लिख ​​"," सभी तत्वों के लिए (यहां तक ​​कि पिछले एक के लिए)। बाद में, आप अवांछित अंतिम "," substr का उपयोग कर हटा दें। इसके अतिरिक्त स्पष्ट कोड में परिणाम मिलता है।

+2

हमेशा क्लीनर समाधान के लिए +1। ;-) – DevSolar

+2

मैं असहमत हूं कि यह स्पष्ट कोड है। यह बाहरी परिचालन करने के लिए कभी भी स्पष्ट नहीं है और फिर बाद में उन्हें पूर्ववत करें। इसके अलावा, यह गैर-मूर्खतापूर्ण है, क्योंकि बेवकूफ तरीका पहले पुनरावृत्ति को विशेष रूप से मानना ​​है। -1 – rmeador

+0

यह अन्य समाधानों की आधा लंबाई है और यह अभी भी दक्षता के संबंध में एक ही क्रम पर है।मैं, व्यक्तिगत रूप से, "क्लीनर" पर विचार करता हूं। इसके अलावा, अगर हम संचालन के शुद्ध लाभ के बारे में बात कर रहे हैं, तो अन्य समाधानों में उच्च शुद्ध लाभ होता है। – Adam

6

एक अन्य समाधान के बजाय अंतिम प्रविष्टि की, पहली प्रविष्टि विशेष मामला हो है:

std::string Compose(DataItemList& dilList) 
{ 
    std::stringstream ssDataSegment; 
    for(iterItems = dilList.begin(); 
     iterItems != dilList.end(); 
     ++iterItems) 
    { 
     // See if current element is the first 
     if(iterItems == dilList.begin()) 
     { 
      ssDataSegment << (*iterItems)->ToString(); 
     } 
     else 
     { 
      ssDataSegment << "," << (*iterItems)->ToString(); 
     } 
    } 
    return ssDataSegment.str(); 
} 
+0

वैकल्पिक दृष्टिकोण यह सुनिश्चित करता है कि कंटेनर खाली न हो, पहले आइटम प्रिंट करें, इटेटरेटर बढ़ाएं, और लूप के पास सिर्फ "अन्य" प्रिंट है और यदि आवश्यक नहीं है। –

+0

@ मार्क बी: हाँ, मैंने देखा कि जोहान्स ने बिल्कुल यही किया था (जब मैंने अपना पोस्ट पोस्ट किया था तो मैंने उसे जवाब में नहीं देखा था)। यह थोड़ा सा है। –

1

फिर भी एक और संभावना:

#include "infix_iterator.h" 
#include <sstream> 

typedef std::list<shared_ptr<EventDataItem> > DataItemList; 

std::string Compose(DataItemList const &diList) { 
    std::ostringstream ret; 
    infix_ostream_iterator out(ret, ","); 

    for (item = diList.begin(); item != diList.end(); ++item) 
     *out++ = (*item)->ToString(); 
    return ret.str(); 
} 

आप Google की यूज़नेट संग्रह से infix_iterator.h प्राप्त कर सकते हैं (या विभिन्न वेबसाइट्स)।

1

नोट: चूंकि सी ++ 11 आप std :: अगले और एसटीडी उपयोग कर सकते हैं :: पिछला

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