2011-10-07 19 views
7

मैं एक छोटा प्रोग्राम बनाने की कोशिश कर रहा हूं जो बाद में प्रोजेक्ट में उपयोग के लिए आईएनआई फाइलों को संसाधित करता है, पहले स्मृति में लोड होने के बाद अपने आकार को कम करके। इस प्रकार,स्ट्रिंग्स के वेक्टर से खाली तत्वों को हटाकर

जहां vLine एक वेक्टर फ़ाइल सामग्री

for (unsigned int i = 0; i < vLine.size(); i++) 
{ 
    if (!vLine[i].find(';', 0)) 
    { 
     vLine[i].erase(); 
    } 
} 

मुद्रण vLine पर युक्त है, मैं इस तरह के

के रूप में रिक्त स्थान है, जहां एक बार एक पंक्ति एक सेमी-कोलन के साथ शुरुआत से ही अस्तित्व में, के साथ छोड़ दिया हो जाएगा
1.  
2. property 
3. property 
4. 
5. property 

आकार का उपयोग करना() इन रिक्त हिस्सों को हटाने के बजाय सूची से अंतिम तत्व को निकालने के लिए प्रतीत होता है। वही समस्या मौजूद है जहां मैं उन रेखाओं को हटाता हूं जिनमें केवल मिटाएं() के साथ व्हाइटस्पेस होता है।

क्या vLine के आदेश को संरक्षित करते समय इन खाली तत्वों को निकालना संभव है?

(इस में iterators का उपयोग नहीं कर के लिए क्षमा याचना।)

+0

पुन:

क्या आप क्या करना चाहते करने के लिए मानक और सरल तरीका std::remove_if है? –

+0

उनके उचित उपयोग के बारे में ज्ञान की कमी। ऐसा लगता है (लग रहा था?) उनके बिना ऐसा करने के लिए संभव है। – JGrey

+1

आप स्ट्रिंग की सामग्री को मिटाने के बजाय वेक्टर से लाइनों को हटा सकते हैं (जो 'vLine [i] .erase() 'करता है, नहीं? कॉल' vLine.erase() 'क्योंकि' वेक्टर 'से मिटा देता है फिर फ़ाइल को फिर से लिखें। ऐसा करने का एक बेवकूफ तरीका सी ++ है [मिटाएं-हटाएं मुहावरे] (http://en.wikipedia.org/wiki/Erase-remove_idiom), हालांकि आप 'std :: remove_if का उपयोग करना चाहते हैं '' से सशर्त का उपयोग करने के लिए। – birryree

उत्तर

8

यह:

vLine[i].erase(); 

वेक्टर से vLine[i] मिटा नहीं है। अभिव्यक्ति vLine[i] सूचकांक i पर तत्व का संदर्भ देता है। तो यह मानते हुए कि vLinestd::vector<std::string> प्रकार है, फ़ंक्शन कॉल erase() वास्तव में तत्व पर string::erase() पर कॉल करता है, वेक्टर पर vector::erase() नहीं। आप जो भी कर रहे हैं वह उस विशेष तत्व को खाली कर रहा है।

vLine.erase(vLine.begin() + i); 

यह वास्तव में वेक्टर से तत्व निकालता है:

क्या आप शायद चाहते हैं कुछ इस तरह है। अब, यह वेक्टर को सभी मौजूदा इटरेटर्स को अमान्य कर देता है, और सूचकांक अब और सही नहीं होंगे। यह एक ऐसी स्थिति है जहां आपको वास्तव में इटरेटर का उपयोग करने की आवश्यकता होती है।

std::vector<std::string>::iterator i = vLine.begin(); 
while(i != vLine.end()) 
{ 
    if(i->find(';', 0) != std::string::npos) 
    { 
     i = vLine.erase(i); 
    } 
    else 
    { 
     ++i; 
    } 
} 

लेकिन वहाँ यह करने के लिए एक और भी आसान तरीका है: एक functor के साथ मानक एल्गोरिथ्म std::remove_if() का उपयोग तो vLine.erase() कहते हैं।

struct HasSemicolon 
{ 
    bool operator()(const std::string& s) 
    { 
     return s.find(';', 0) != std::string::npos; 
    } 
}; 

// ... 

vLine.erase(std::remove_if(vLine.begin(), vLine.end(), HasSemicolon()), vLine.end()); 

आप एक सी ++ 11 संकलक का उपयोग कर सकते हैं, तो आप भी लैम्ब्डा एक्सप्रेशन का उपयोग भी अधिक संक्षिप्त हो सकता है।

+0

सिलिको में बहुत अधिक बाध्य है। मैं इसे फिर से सीखने के लिए समय लेता हूं और तदनुसार अपना आवेदन बदलता हूं। – JGrey

+0

क्या आप सी ++ 11 लैम्बडास का उपयोग करके एक उदाहरण जोड़ सकते हैं? मैं कोशिश कर रहा हूं इसे एक घंटे के बेहतर हिस्से के लिए समझने के लिए, लेकिन मैं सी ++ डॉक्स पढ़ने में भयानक हूं। –

+0

@QPaysTaxes http://en.cppreference.com/w/cpp/algorithm/remove में लैम्ब्डा के साथ एक उदाहरण है। – arekolek

4

अधिमानतः से सी ++ 11 एक लैम्ब्डा के साथ, मिटा/निकालें-मुहावरा का प्रयोग करें:

foo.erase(std::remove_if(foo.begin(), foo.end(), 
         [](const std::string& s) 
         { return s.find(';', 0); })); 
7

समस्या तत्वों को दूर करने के लिए अपने तर्क में है। जब आप इंडेक्स i पर किसी तत्व पर आते हैं जिसे आप मिटाना चाहते हैं, तो आप इसका मान साफ़ करते हैं, लेकिन आप इसे वेक्टर से नहीं हटाते हैं। (इस में iterators का उपयोग नहीं कर के लिए क्षमा याचना।) - क्यों iterators का उपयोग नहीं:

vLine.erase(
    std::remove_if(
     vLine.begin(), 
     vLine.end(), 
     [](std::string const& s) { return s.size() != 0 && s.front() == ';'; }), 
    vLine.end()); 
संबंधित मुद्दे