2012-05-09 13 views
5

मेरे पास एक ऐसा फ़ंक्शन है जो ऑब्जेक्ट मिलने पर एक इटरेटर लौटाता है।लौटने वाले सी ++ इटरेटर

अब मुझे कोई समस्या है। मैं उस ऑब्जेक्ट को सूचित करने की समस्या को कैसे ठीक करूं जिसे इस फ़ंक्शन कहा जाता है कि ऑब्जेक्ट नहीं मिला था?

vector<obj>::iterator Find(int id, int test) 
{ 
     vector<obj>::iterator it; 
      aClass class; 

      for(it = class.vecCont.begin(); it != class.vecCont.end(); ++it) 
      { 
       if(found object) //currently in psuedo code 
       return it; 
      } 

      return ???? // <<< if not found what to insert here? 

} 

क्या मुझे इसके बजाय अपनी डेटा संरचना बदलने की ज़रूरत है?

अग्रिम धन्यवाद! :)

+2

यदि आपके पास स्वयं का उपयोग करने का कोई विशेष कारण नहीं है, तो 'std :: find' पर विचार करें। जिस तरह से इसे लागू किया गया है, यह है कि यह 'अंत() 'वापस करेगा। – chris

+2

यह सिर्फ एक डिजाइन दोष की तरह लगता है। एक प्रतिलिपि, एक सूचक, एक बूल को मिला जो स्थिति को इंगित करता है और संदर्भ के माध्यम से एक इनपुट आवृत्ति संशोधित करता है, लेकिन एक छिपे हुए कंटेनर में एक इटरेटर वापस न करें! –

+0

जटिलता ढूंढें ओ (एन) है। मैं वास्तव में खोज करने के लिए एक बैक एंड बाइनरी खोज का उपयोग कर रहा हूँ। यह बहुत महत्वपूर्ण है क्योंकि मैं एक बहुत ही विशाल वितरित प्रणाली को कार्यान्वित करता हूं। – mister

उत्तर

0

एक छिपे हुए कंटेनर पर एक इटरेटर वापस न करें। केवल वही लौटें जो आप चाहते हैं, अर्थात् यदि किसी वस्तु का अस्तित्व है तो इसका उपयोग करने का साधन। इस उदाहरण में, मैं ऑब्जेक्ट को कंटेनर में पॉइंटर के माध्यम से स्टोर करता हूं।यदि आपकी वस्तुएं केवल अस्थायी रूप से मौजूद हैं, तो नया एक ऊपर और वस्तु को कॉपी करें!

class AClass; 

//...some time later 
std::vector<AClass*> vecCont; //notice, store pointers in this example! 

//..some time later 
AClass * findAClass(int id, int test) 
{ 
    vector<AClass*>::iterator it; 

    for(it = class.vecCont.begin(); it != class.vecCont.end(); ++it) 
    { 
    if(found object) //currently in psuedo code 
    return it; 
    } 

    return NULL; 
} 

//later still.. 

AClass *foundVal = findAClass(1, 0); 
if(foundVal) 
{ 
    //we found it! 
} 
else 
{ 
    //we didn't find it 
} 

संपादित करें: करने के लिए बुद्धिमान बात अपने वर्ग के लिए एक तुलनित्र लिखने और एसटीडी एल्गोरिदम प्रकार का उपयोग करें और उन्हें आप के लिए खोजने के लिए है। हालांकि, जो भी आप चाहते हैं करो।

+0

यदि आप साझा पॉइंटर्स का उपयोग करके अनुशंसा करते हैं तो मुझे यह पसंद आएगा। यहाँ कच्चे पॉइंटर्स का परिचय मेरी भावनाओं को दर्द देता है। –

+0

साझा/स्मार्ट पॉइंटर्स के साथ मेरा अनुभव सामान्य रूप से अच्छा नहीं रहा है। यह आपके स्वयं के वर्गों के अंदर अलग कोड के लिए मिलता है, लेकिन मेरे साथ क्या होता है (कम से कम मेरी परियोजनाओं पर) यह है कि जब मैं कोड इंटरफेस को एक दूसरे के साथ संवाद करने की आवश्यकता होती है और कच्चे सूचक की आवश्यकता होती है तो मैं समस्याओं में भाग लेता हूं। साथ ही, आप वस्तुएं मांगना चाहते हैं कि वे असंगत राज्यों में या उससे अधिक समय तक जीवित रहें क्योंकि विनाश आदेश नियंत्रण में आसान नहीं है। मुझे पॉइंटर्स को बसने के लिए आसान लगता है और इसे "यह मेरा है। आप केवल इसे उधार ले रहे हैं। इसे स्टोर न करें। इसे इस्तेमाल करने से पहले मुझे अनुमति दें।" –

+0

उन पर मत छोड़ो! आपका उदाहरण [std :: weak_ptr] (http://en.cppreference.com/w/cpp/memory/weak_ptr) के लिए नौकरी की तरह लगता है। मेरी राय में, किसी भी प्रकार के स्मार्ट पॉइंटर्स का उपयोग करना लगभग हमेशा रास्ता है - एक के लिए अपवाद सुरक्षा ([RAII] (http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization) सोचें। मैं मानता हूं कि इंटरफेस से निपटने पर आपको हो सकता है, खासकर यदि इंटरफेस किसी अन्य उत्पाद/एपीआई के पास हैं और आपके पास कोई नियंत्रण नहीं है। लेकिन यह अभी भी मेरे लिए लायक है। –

5

आप इसे इंगित करने के लिए एक इटरेटर को वापस कर सकते हैं, यानी return class.vecCont.end()

7

वापसी vector::end(), एक अपवाद फेंक, या वापसी अलावा कुछ एक सादे इटरेटर

की तुलना में बेहतर अभी तक, अपने स्वयं के Find समारोह को लागू नहीं करते। <algorithm> लाइब्रेरी के लिए यही है। आपके psudocode के आधार पर, आप शायद std::find या std::find_if का उपयोग कर सकते हैं। find_if उन मामलों में विशेष रूप से उपयोगी है जहां समानता का मतलब operator== नहीं है। उन मामलों में, आप एक [सी ++ 11] लैम्ब्डा का उपयोग कर सकते हैं या यदि सी ++ 11 आपके लिए उपलब्ध नहीं है, तो एक मजेदार वर्ग।

के बाद से functor सबसे कम आम विभाजक है, मैं उस के साथ शुरू करेंगे:

#include <cstdlib> 
#include <string> 
#include <algorithm> 
#include <vector> 
#include <functional> 
using namespace std; 

class Person 
{ 
public: 
    Person(const string& name, unsigned age) : name_(name), age_(age) {}; 

    string name_; 
    unsigned age_; 
}; 

class match_name : public unary_function <bool, string> 
{ 
public: 
    match_name(const string& rhs) : name_(rhs) {}; 
    bool operator()(const Person& rhs) const 
    { 
    return rhs.name_ == name_; 
    } 
private: 
    string name_; 
}; 

#include <iostream> 

int main() 
{ 
    vector<Person> people; 
    people.push_back(Person("Hellen Keller", 99)); 
    people.push_back(Person("John Doe", 42)); 

    /** C++03 **/ 
    vector<Person>::const_iterator found_person = std::find_if(people.begin(), people.end(), match_name("John Doe")); 

    if(found_person == people.end()) 
     cout << "Not FOund"; 
    else 
     cout << found_person->name_ << " is " << found_person->age_; 
} 

found_person अब व्यक्ति जिसका नाम "जॉन डो" है की ओर इशारा करता है, या यदि उस व्यक्ति नहीं दिया किसी और people_.end() को इंगित करता है नहीं मिला

ए सी ++ 11 लैम्ब्डा नई भाषा वाक्यविन्यास है जो एक मज़ेदार घोषित करने/परिभाषित करने की प्रक्रिया को बनाता है और कई मामलों के लिए उपयोग करना कुछ आसान है। यह इस तरह से किया जाता है:

string target = "John Doe"; 
vector<Person>::const_iterator found_person = std::find_if(people.begin(), people.end(), [&target](const Person& test) { return it->name_ == target; }); 
+0

मुझे लगता है कि अगर एक इटरेटर संभव नहीं है तो एक अपवाद वास्तव में सही विकल्प है। (उदाहरण के लिए क्योंकि कॉलर को यह नहीं पता है कि इसे अंत() से तुलना करना चाहिए या यदि यह कॉलर को बस दिखाई नहीं दे रहा है।) – TaZ

1

आप class.vecCont.end() लौटना चाहिए अगर वस्तु नहीं मिला था। लेकिन @ क्रिसिस सही है - यह वास्तव में std::find है।

2

केवल अंत पुनरावर्तक को वापस करने के बारे में कैसे?

आपका कोड हो जाता है: -

vector<obj>::iterator Find(int id, int test) 
{ 
    vector<obj>::iterator it; 
    aClass class; 

    for(it = class.vecCont.begin(); it != class.vecCont.end(); ++it) 
    { 
    if(found object) //currently in psuedo code 
     break; 
    } 

    return it; 
} 

या सिर्फ std::find का उपयोग करें। इस

std::vector<obj>::iterator pos; 
pos = find(coll.begin(),coll.end(), val); 

तरह

0

में या अपने तत्व की उपस्थिति नहीं के लिए इन जांच करने के लिए भूल जाते हैं कभी नहीं एक वर्ग के अंदर std::algorithm कार्यों का अनुकरण नहीं है। वे एक कारण के लिए नि: शुल्क कार्य हैं। यह आमतौर पर begin और end सदस्य फ़ंक्शन का खुलासा करने के लिए पर्याप्त है जो दाएं इटरेटर्स (और संभवतः boost::iterator_range) लौटाता है। यदि आपको एक मजेदार के साथ एक फैंसी खोजने की ज़रूरत है, तो मज़ेदार को भी बेनकाब करें।