पता लगाएँ कि क्या स्ट्रिंग C ++ में एक और स्ट्रिंग के साथ समाप्त होती है


270

मैं कैसे पता लगा सकता हूं कि एक स्ट्रिंग C ++ में दूसरे स्ट्रिंग के साथ समाप्त होती है?

जवाबों:


211

बस अंतिम n वर्णों की तुलना करें std::string::compare:

#include <iostream>

bool hasEnding (std::string const &fullString, std::string const &ending) {
    if (fullString.length() >= ending.length()) {
        return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
    } else {
        return false;
    }
}

int main () {
    std::string test1 = "binary";
    std::string test2 = "unary";
    std::string test3 = "tertiary";
    std::string test4 = "ry";
    std::string ending = "nary";

    std::cout << hasEnding (test1, ending) << std::endl;
    std::cout << hasEnding (test2, ending) << std::endl;
    std::cout << hasEnding (test3, ending) << std::endl;
    std::cout << hasEnding (test4, ending) << std::endl;

    return 0;
}

हाँ, यह बिना शक के करने का सबसे अच्छा तरीका है।
नोल्डोरिन

3
मैं हमेशा सब्सट्रिंग के सूचकांकों की गणना करने से नफरत करता हूं, यह बहुत ही बंद-से-प्रवण है ... मैं दोनों स्ट्रिंग्स के अंत से पीछे की ओर पुनरावृति करता हूं, बेमेल खोजने की कोशिश कर रहा हूं।
xtofl

17
@ नोल्डोरिन मैं सहमत नहीं हूँ। यह एक नो-ब्रेनर है - इसे करने का सबसे अच्छा तरीका एक पुस्तकालय का उपयोग करना है। यह शर्म की बात है कि C ++ मानक पुस्तकालय इतनी उपयोगी चीजें करता है।
मास्टरएक्सिलो

1
@masterxilo इस समस्या को हल करने के लिए आप किस लाइब्रेरी का प्रस्ताव रखते हैं और वह लाइब्रेरी एक (मूल रूप से) एक-लाइन फ़ंक्शन से बेहतर विकल्प कैसे है?
ब्रेंडिन

33
@ ब्रैंडिन क्योंकि यह एक ऐसी बुनियादी कार्यक्षमता है। C ++ हमें बार-बार वही कार्यशीलता के लिए उकसाने के लिए मजबूर करता है जो किसी अन्य आधुनिक कंप्यूटर भाषा में आउट-ऑफ-द-बॉक्स प्रदान किए जाते हैं। तथ्य यह है कि इस सवाल को हल करने के लिए लोगों को स्टैकओवरफ़्लो में जाने की ज़रूरत है, यह दर्शाता है कि एक पीबी है।
कंसीकल्चर

175

इस फ़ंक्शन का उपयोग करें:

inline bool ends_with(std::string const & value, std::string const & ending)
{
    if (ending.size() > value.size()) return false;
    return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
}

3
सावधान रहें कि MSVC10 इस समाधान को पसंद नहीं करता है: std::equal(suffix.rbegin(), suffix.rend(), str.rbegin()डीबग मोड में, यह फेंकता है:_DEBUG_ERROR("string iterator not decrementable");
remi.chateauneu

154

उपयोग करें boost::algorithm::ends_with(उदाहरण के लिए देखें http://www.boost.org/doc/libs/1_34_0/doc/html/boost/algorithm/ends_with.html ):

#include <boost/algorithm/string/predicate.hpp>

// works with const char* 
assert(boost::algorithm::ends_with("mystring", "ing"));

// also works with std::string
std::string haystack("mystring");
std::string needle("ing");
assert(boost::algorithm::ends_with(haystack, needle));

std::string haystack2("ng");
assert(! boost::algorithm::ends_with(haystack2, needle));

83

ध्यान दें, कि c ++ 20 std :: string से शुरू होकर अंत में start_with और end_with प्रदान करेगा । ऐसा लगता है कि एक मौका है कि c ++ में c ++ के 30 तार अंत में प्रयोग करने योग्य हो सकते हैं, यदि आप इसे दूर के भविष्य से नहीं पढ़ रहे हैं, तो आप इन का उपयोग कर सकते हैं।

#include <string>

static bool endsWith(const std::string& str, const std::string& suffix)
{
    return str.size() >= suffix.size() && 0 == str.compare(str.size()-suffix.size(), suffix.size(), suffix);
}

static bool startsWith(const std::string& str, const std::string& prefix)
{
    return str.size() >= prefix.size() && 0 == str.compare(0, prefix.size(), prefix);
}

और कुछ अतिरिक्त सहायक अधिभार:

static bool endsWith(const std::string& str, const char* suffix, unsigned suffixLen)
{
    return str.size() >= suffixLen && 0 == str.compare(str.size()-suffixLen, suffixLen, suffix, suffixLen);
}

static bool endsWith(const std::string& str, const char* suffix)
{
    return endsWith(str, suffix, std::string::traits_type::length(suffix));
}

static bool startsWith(const std::string& str, const char* prefix, unsigned prefixLen)
{
    return str.size() >= prefixLen && 0 == str.compare(0, prefixLen, prefix, prefixLen);
}

static bool startsWith(const std::string& str, const char* prefix)
{
    return startsWith(str, prefix, std::string::traits_type::length(prefix));
}

IMO, c ++ स्ट्रिंग्स स्पष्ट रूप से बेकार हैं, और वास्तविक विश्व कोड में उपयोग करने के लिए नहीं बनाए गए थे। लेकिन एक उम्मीद है कि यह कम से कम बेहतर हो जाएगा।


2
चूंकि str.compare एक बूलियन वापस नहीं करता है, इसलिए "== 0" के लिए नहीं ("!") ऑपरेटर का उपयोग करके परीक्षण करना इतना स्मार्ट नहीं है, क्योंकि यह पाठकों को भ्रमित कर सकता है। कृपया स्पष्टता के लिए "... && str.compare (...) == 0" का उपयोग करें।
थॉमस टेम्पेलमैन

@ पावेल वहाँ एक कारण नहीं है std :: string :: का प्रयोग अपने "start" तरीके से करें?
मैक्सिमे ऊदोत

4
@MaximeOudot बेशक वहाँ है! यदि आप किसी चीज से शुरू करना चाहते हैं, तो आपको पूरे स्ट्रिंग को क्यों खोजना होगा? दूसरे शब्दों में, आप अंत में टुकड़े को खोजने के लिए 100mb लंबी स्ट्रिंग खोज सकते हैं और फिर उस परिणाम को अनदेखा कर सकते हैं क्योंकि यह स्ट्रिंग की शुरुआत में नहीं है।
पावेल पी

1
C ++ 30 की भविष्यवाणी के लिए प्लस "1"।
मासूम बिस्टैंडर

40

मैं C ++ के लिए प्रश्न जानता हूं, लेकिन अगर किसी को ऐसा करने के लिए एक अच्छे ol 'फ़ैशन सी फ़ंक्शन की आवश्यकता है:


/*  returns 1 iff str ends with suffix  */
int str_ends_with(const char * str, const char * suffix) {

  if( str == NULL || suffix == NULL )
    return 0;

  size_t str_len = strlen(str);
  size_t suffix_len = strlen(suffix);

  if(suffix_len > str_len)
    return 0;

  return 0 == strncmp( str + str_len - suffix_len, suffix, suffix_len );
}


25

यह std::mismatchविधि इस उद्देश्य की पूर्ति कर सकती है जब दोनों तारों के अंत से पीछे की ओर प्रयोग किया जाता है:

const string sNoFruit = "ThisOneEndsOnNothingMuchFruitLike";
const string sOrange = "ThisOneEndsOnOrange";

const string sPattern = "Orange";

assert( mismatch( sPattern.rbegin(), sPattern.rend(), sNoFruit.rbegin() )
          .first != sPattern.rend() );

assert( mismatch( sPattern.rbegin(), sPattern.rend(), sOrange.rbegin() )
          .first == sPattern.rend() );

3
+1। मैंने कभी भी std पर ध्यान नहीं दिया: बेमेल () से पहले - मुझे आश्चर्य है कि उस एल्गोरिदम हेडर फ़ाइल में और क्या है जो मैंने कभी नहीं देखा है ...
j_random_hacker

3
मुझे लगता है कि यह अपने आप में एक एसओ प्रश्न के लायक है: क्या आपने कभी एसटीएल कार्यों के माध्यम से उपलब्ध कराया है?
xtofl

2
ध्यान दें कि इसकी समान आवश्यकता है std::equal: आपको पहले से जांचने की आवश्यकता है कि माना गया प्रत्यय उस स्ट्रिंग से अधिक लंबा नहीं है जिसे आप इसके लिए खोज रहे हैं। यह जांचने के लिए उपेक्षा करना कि अपरिभाषित व्यवहार की ओर जाता है।
रोब कैनेडी

18

मेरी राय में सबसे सरल, C ++ समाधान है:

bool endsWith(const string& s, const string& suffix)
{
    return s.rfind(suffix) == std::abs(s.size()-suffix.size());
}

10
यह केवल धीमा है क्योंकि आप sइसके अंत के परीक्षण के बजाय पूरे स्ट्रिंग को खोज लेंगे !
एलेक्सिस विल्के

2
@nodakai, अगर मुझे 1Mb स्ट्रिंग होती है, तो यह नैनोसेकंड से बहुत अधिक है।
एलेक्सिस विल्के

मुझे ऐसा नहीं लगता ... इसे किसी भी मामले में स्ट्रगल करने की जरूरत है, और फिर अंत से देखना शुरू कर देता है।
लेटॉर्फ

2
@LtWorf std::string::size()एक निरंतर-समय ऑपरेशन है; इसकी जरूरत नहीं है strlen
थॉमस

2
जब यह प्रत्यय के मामले में विफल हो जाता है तो इसे कैसे भी माना जा सकता है। जब आप इसे ऑनलाइनgdb.com/S1ITVqKDL दिखाते हुए कोड को प्रत्यय देते हैं । यदि यह सभी मामलों के लिए ठीक से काम नहीं करता है, तो जटिलता अप्रासंगिक है।
c0ntrol

10

चलो a देना एक स्ट्रिंग और bस्ट्रिंग आप के लिए देखो। a.substrके अंतिम n अक्षर प्राप्त करने के लिए उपयोग करें aऔर उनकी तुलना b से करें (जहाँ n की लंबाई है b)

या उपयोग std::equal(शामिल <algorithm>)

उदाहरण के लिए:

bool EndsWith(const string& a, const string& b) {
    if (b.size() > a.size()) return false;
    return std::equal(a.begin() + a.size() - b.size(), a.end(), b.begin());
}

अगर मैं अपनी स्ट्रिंग को \ r या \ n या दोनों के बाद समाप्त करता हूं तो मैं कैसे सच लौटा सकता हूं ??? धन्यवाद!
सोफ्र

@ डारियो: एसटीडी का उपयोग करके आपका समाधान :: बराबर () अच्छा है, एक का उपयोग कर पदार्थ () इतना नहीं है - जब तक आप गाय का उपयोग नहीं कर रहे हैं (और कुछ लोगों का मानना ​​है कि), पदार्थ () का अर्थ है एक दूसरी प्रति बनाना। स्ट्रिंग का हिस्सा, गतिशील मेमोरी आवंटन को शामिल करना शामिल है। यह विफल हो सकता है, और किसी भी मामले में इसका मतलब है कि अन्य समाधानों की तुलना में अधिक मेमोरी का उपयोग किया जाता है (और यह निश्चित रूप से अन्य समाधानों की तुलना में धीमा है)।
j_random_hacker

4

केस असंवेदनशील संस्करण ( ऑनलाइन डेमो ) के साथ मुझे यूसुफ के समाधान का विस्तार करने दें

static bool EndsWithCaseInsensitive(const std::string& value, const std::string& ending) {
    if (ending.size() > value.size()) {
        return false;
    }
    return std::equal(ending.rbegin(), ending.rend(), value.rbegin(),
        [](const char a, const char b) {
            return tolower(a) == tolower(b);
        }
    );
}

3

ऊपर के रूप में ही, यहाँ मेरा समाधान है

 template<typename TString>
  inline bool starts_with(const TString& str, const TString& start) {
    if (start.size() > str.size()) return false;
    return str.compare(0, start.size(), start) == 0;
  }
  template<typename TString>
  inline bool ends_with(const TString& str, const TString& end) {
    if (end.size() > str.size()) return false;
    return std::equal(end.rbegin(), end.rend(), str.rbegin());
  }

1
Use starts_withस्ट्रिंग :: तुलना ’का उपयोग क्यों करता है? क्यों नहीं std::equal(start.begin(), start.end(), str.begin())?
Dmytro Ovdiienko

सिर्फ इसलिए कि start_with मुझे पहले चाहिए था End_with को बाद में जोड़ा गया था।
डोडजैंगो

3

एक और विकल्प रेगेक्स का उपयोग करना है। निम्न कोड ऊपरी / निचले मामले में खोज को असंवेदनशील बनाता है:

bool endsWithIgnoreCase(const std::string& str, const std::string& suffix) {
  return std::regex_search(str,
     std::regex(std::string(suffix) + "$", std::regex_constants::icase));
}

शायद इतना कुशल नहीं है, लेकिन इसे लागू करना आसान है।


C ++ 11 या इसके बाद के संस्करण वाले किसी के लिए, यह बहुत सुविधाजनक है।
क्लेयर मैक्रॉन

खबरदार, Regexes C ++ में पागलपन की तरह धीमा हो सकता है!
mxmlnkn

इस के लिए regex ऐसा है ... मुझे इसे नीचा दिखाना होगा। मैं नहीं करूँगा, लेकिन मुझे चाहिए।
एम.के.

2

आप स्ट्रिंग का उपयोग कर सकते हैं :: rfind

टिप्पणियों पर आधारित पूर्ण उदाहरण:

bool EndsWith(string &str, string& key)
{
size_t keylen = key.length();
size_t strlen = str.length();

if(keylen =< strlen)
    return string::npos != str.rfind(key,strlen - keylen, keylen);
else return false;
}

3
-1। हां, आप इसका उपयोग कर सकते हैं, लेकिन यह इस घटना में अनावश्यक रूप से धीमा है कि स्ट्रिंग आपूर्ति की समाप्ति के साथ समाप्त नहीं होती है - स्कैनिंग स्ट्रिंग की शुरुआत में सभी तरह से वापस आ जाएगी। इसके अलावा, आप यह उल्लेख नहीं करते हैं कि आपको यह सुनिश्चित करने के लिए बाद के परीक्षण की आवश्यकता है कि स्ट्रिंग के अंत में, स्ट्रिंग में कहीं और के बजाय मैच समाप्त हो रहे हैं ।
j_random_hacker

मैं सिर्फ आवश्यक फ़ंक्शन का लिंक डाल देता हूं और मुझे लगता है कि यह प्रलेखन str.rfind (कुंजी, str.length () - key.length (), key.length ()) से करना बहुत आसान है;
अहमद ने

ठीक है, यह कुशल है - लेकिन उस स्थिति में स्ट्रिंग :: ढूंढें () बस के रूप में अच्छी तरह से काम करेगा। साथ ही आपको उस मामले का उल्लेख करना होगा जहां key.length ()> str.length () - आपकी टिप्पणी में आपके द्वारा सुझाया गया कोड इस मामले में क्रैश हो जाएगा। यदि आप अपना उत्तर इस जानकारी के साथ अपडेट करते हैं तो मैं अपना -1 छोड़ दूंगा।
j_random_hacker 16

2

पता लगाएं कि str है प्रत्यय , नीचे का उपयोग कर:

/*
Check string is end with extension/suffix
*/
int strEndWith(char* str, const char* suffix)
{
  size_t strLen = strlen(str);
  size_t suffixLen = strlen(suffix);
  if (suffixLen <= strLen) {
    return strncmp(str + strLen - suffixLen, suffix, suffixLen) == 0;
  }
  return 0;
}

2

एसटीडी का उपयोग करें <algorithms>: रिवर्स इटर्शन से समान एल्गोरिथ्म :

std::string LogExt = ".log";
if (std::equal(LogExt.rbegin(), LogExt.rend(), filename.rbegin())) {
   
}

2
हालांकि यह कोड प्रश्न का हल प्रदान कर सकता है, इसलिए संदर्भ जोड़ना बेहतर है कि यह क्यों / कैसे काम करता है। यह भविष्य के उपयोगकर्ताओं को सीखने में मदद कर सकता है, और उस ज्ञान को अपने कोड में लागू कर सकता है। जब कोड समझाया जाता है, तो आपको उपयोगकर्ताओं से upvotes के रूप में सकारात्मक प्रतिक्रिया मिलने की संभावना होती है।
बोरवम

@borchvm, कुछ स्पष्टीकरण जोड़ा, आशा है कि यह समझने में मदद करता है
सर्गेई

1

ग्रेज़गोरज़ बाज़ीर की प्रतिक्रिया के बारे में। मैंने इस कार्यान्वयन का उपयोग किया, लेकिन मूल में बग है (यदि मैं ".." के साथ ".so") की तुलना में सही है (तो सही है)। मैं संशोधित कार्य प्रस्तावित करता हूं:

bool endsWith(const string& s, const string& suffix)
{
    return s.size() >= suffix.size() && s.rfind(suffix) == (s.size()-suffix.size());
}

1

मैंने सोचा कि यह एक कच्चे समाधान पोस्ट करने के लिए समझ में आता है जो किसी भी पुस्तकालय कार्यों का उपयोग नहीं करता है ...

// Checks whether `str' ends with `suffix'
bool endsWith(const std::string& str, const std::string& suffix) {
    if (&suffix == &str) return true; // str and suffix are the same string
    if (suffix.length() > str.length()) return false;
    size_t delta = str.length() - suffix.length();
    for (size_t i = 0; i < suffix.length(); ++i) {
        if (suffix[i] != str[delta + i]) return false;
    }
    return true;
}

एक साधारण जोड़ना std::tolowerहम इस मामले को असंवेदनशील बना सकते हैं

// Checks whether `str' ends with `suffix' ignoring case
bool endsWithIgnoreCase(const std::string& str, const std::string& suffix) {
    if (&suffix == &str) return true; // str and suffix are the same string
    if (suffix.length() > str.length()) return false;
    size_t delta = str.length() - suffix.length();
    for (size_t i = 0; i < suffix.length(); ++i) {
        if (std::tolower(suffix[i]) != std::tolower(str[delta + i])) return false;
    }
    return true;
}

इसे जोड़ने के लिए धन्यवाद। प्रकाश समाधान हमेशा महान होते हैं
ईकिस

1

इस तरह के "startWith" के लिए यह अच्छा जवाब मिला -प्रोफ़ाइल:

अगर C ++ std :: string एक निश्चित स्ट्रिंग से शुरू होती है, और एक स्ट्रिंग को एक int में परिवर्तित करती है, तो मैं कैसे जांचूं?

आप स्ट्रिंग में अंतिम स्थान पर केवल खोज करने के लिए समाधान को अपना सकते हैं:

bool endsWith(const std::string& stack, const std::string& needle) {
    return stack.find(needle, stack.size() - needle.size()) != std::string::npos;
}

इस तरह से आप इसे छोटा, तेज, मानक c ++ का उपयोग कर सकते हैं और इसे पठनीय बना सकते हैं।


0

यदि आप मेरे जैसे हैं और C ++ शुद्धतावाद में नहीं हैं, तो यहां एक पुराना स्कुल हाइब्रिड है। कुछ फायदे हैं जब तार कुछ मुट्ठी भर पात्रों से अधिक होते हैं, क्योंकि अधिकांश memcmpकार्यान्वयन मशीन शब्दों की तुलना जब संभव हो तो करते हैं।

आपको चरित्र सेट के नियंत्रण में होना चाहिए। उदाहरण के लिए, यदि इस दृष्टिकोण का उपयोग utf-8 या wchar प्रकार के साथ किया जाता है, तो कुछ नुकसान है क्योंकि यह वर्ण मैपिंग का समर्थन नहीं करेगा - उदाहरण के लिए, जब दो या दो से अधिक अक्षर तार्किक रूप से समान होते हैं

bool starts_with(std::string const & value, std::string const & prefix)
{
    size_t valueSize = value.size();
    size_t prefixSize = prefix.size();

    if (prefixSize > valueSize)
    {
        return false;
    }

    return memcmp(value.data(), prefix.data(), prefixSize) == 0;
}


bool ends_with(std::string const & value, std::string const & suffix)
{
    size_t valueSize = value.size();
    size_t suffixSize = suffix.size();

    if (suffixSize > valueSize)
    {
        return false;
    }

    const char * valuePtr = value.data() + valueSize - suffixSize;

    return memcmp(valuePtr, suffix.data(), suffixSize) == 0;
}

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