`Std :: string :: find ()` विफलताओं पर अंतिम पुनरावृत्ति वापस क्यों नहीं करता है?


29

मुझे std::string::findमानक C ++ कंटेनरों के साथ असंगत होने का व्यवहार लगता है ।

उदाहरण के लिए

std::map<int, int> myMap = {{1, 2}};
auto it = myMap.find(10);  // it == myMap.end()

लेकिन एक तार के लिए,

std::string myStr = "hello";
auto it = myStr.find('!');  // it == std::string::npos

इसके बजाय असफल myStr.find('!')वापसी क्यों नहीं होनी चाहिए ?myStr.end()std::string::npos

चूंकि std::stringअन्य कंटेनरों के साथ तुलना में कुछ हद तक विशेष है, मैं सोच रहा हूं कि क्या इसके पीछे कोई वास्तविक कारण है। (हैरानी की बात है, मैं किसी को भी इस पर सवाल नहीं उठा पाया)।


5
मुझे लगता है कि केवल उचित जवाब सवाल के जवाब के करीब है: 'क्यों हॉटडॉग 4 में पैक किए जाते हैं और 6 में हॉटडॉग बन्स?' खैर, यह दुनिया को
खुश


IMHO, इस व्यवहार का एक कारण यह होगा कि std::stringआंतरिक रूप से ऐसे अक्षर होते हैं जो सस्ती तत्व होते हैं (स्मृति के संबंध में)। और, इसके अलावा, चरित्र ही एकमात्र प्रकार std::stringहो सकता है। दूसरी ओर, std::mapअधिक जटिल तत्व होते हैं। इसके अलावा, विनिर्देश का std::map::findकहना है कि यह एक तत्व खोजने के लिए माना जाता है, और विनिर्देश का std::string::findकहना है कि यह काम करने के लिए स्थिति है।
नटक्रैकर

मानचित्र के लिए, आपके पास एक npos itter नहीं हो सकता है, इसलिए अंतिम पुनरावृत्त का उपयोग किया जाता है। स्ट्रिंग के लिए, हम npos का उपयोग कर सकते हैं, इसलिए क्यों नहीं :)
LF

जवाबों:


28

शुरू करने के लिए, std::stringइंटरफ़ेस अच्छी तरह से फूला हुआ और असंगत होने के लिए जाना जाता है, इस विषय पर हर्ब सटर के गॉटवॉव देखें । लेकिन फिर भी, std::string::findएक सूचकांक वापस करने के पीछे एक तर्क है std::string::substr:। यह सुविधा सदस्य फ़ंक्शन सूचकांकों पर संचालित होता है, जैसे

const std::string src = "abcdefghijk";

std::cout << src.substr(2, 5) << "\n";

आप substrइसे ऐसे कार्यान्वित कर सकते हैं कि यह पुनरावृत्तियों को स्ट्रिंग में स्वीकार करता है, लेकिन फिर हमें अनुपलब्ध शिकायतों के लिए लंबे समय तक प्रतीक्षा करने की आवश्यकता नहीं है जो std::stringअनुपयोगी और प्रतिवादात्मक हैं। तो यह देखते हुए कि std::string::substrसूचकांक स्वीकार करता है, आप 'd'इस सबस्ट्रिंग से शुरू होने वाली सभी चीजों का प्रिंट आउट लेने के लिए उपरोक्त इनपुट स्ट्रिंग में पहली घटना का सूचकांक कैसे पाएंगे ?

const auto it = src.find('d'); // imagine this returns an iterator

std::cout << src.substr(std::distance(src.cbegin(), it));

यह भी नहीं हो सकता है कि आप क्या चाहते हैं। इसलिए हम std::string::findएक इंडेक्स लौटा सकते हैं , और यहाँ हम हैं:

const std::string extracted = src.substr(src.find('d'));

यदि आप पुनरावृत्तियों के साथ काम करना चाहते हैं, तो उपयोग करें <algorithm>। वे आपको उपरोक्त के लिए अनुमति देते हैं

auto it = std::find(src.cbegin(), src.cend(), 'd');

std::copy(it, src.cend(), std::ostream_iterator<char>(std::cout));

4
अच्छी बात। हालांकि, एक पुनरावृति std::string::findलौटने size()के बजाय npos, substrकई अतिरिक्त शाखाओं से बचने के साथ , संगतता बनाए रखने के बजाय, अभी भी वापस आ सकता है ।
एरॉनॉन

1
@erenon हो सकता है, लेकिन std::string::substrपहले से ही दूसरे सूचकांक ( npos) के लिए डिफ़ॉल्ट पैरामीटर के साथ "अंत तक यहां शुरू करें" मामले को कवर करता है । मुझे लगता है कि वापसी size()भी भ्रामक होगी और शाब्दिक प्रहरी की तरह nposबेहतर विकल्प हो सकता है ?!
lubgr

@lubgr लेकिन अगर std::string::findएक पुनरावृति देता है, std::string::substrतो शायद यह भी शुरू की स्थिति के लिए एक पुनरावृत्ति स्वीकार करेगा। आपके उदाहरण के साथ इस वैकल्पिक दुनिया में दोनों मामलों में समान दिखेंगे।
मटियास वालिन

@MattiasWallin अच्छी बात है। लेकिन std::string::substrएक पुनरावृत्ति तर्क के साथ एक और यूबी मामले के लिए दरवाजा खुलता है (अतीत के अंत के परिदृश्य के अलावा जो समान रूप से सूचकांकों या पुनरावृत्तियों के साथ हो सकता है): एक पुनरावृत्ति पास करना जो एक और स्ट्रिंग को संदर्भित करता है।
lubgr

3

ऐसा इसलिए है क्योंकि std::stringदो इंटरफेस हैं:

  • सभी कंटेनरों पर पाया जाने वाला सामान्य पुनरावृत्ति आधारित इंटरफ़ेस
  • std::stringविशिष्ट सूचकांक आधारित इंटरफेस

std::string::findसूचकांक आधारित इंटरफेस का हिस्सा है , और इसलिए सूचकांक लौटाता है।

std::findसामान्य पुनरावृत्त आधारित इंटरफ़ेस का उपयोग करने के लिए उपयोग करें।

std::vector<char>यदि आप अनुक्रमणिका आधारित इंटरफ़ेस (ऐसा नहीं करते) नहीं चाहते हैं तो उपयोग करें ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.