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
@ নলডোরিন এটি কোনও মস্তিষ্ক-এটি করার সর্বোত্তম উপায় হ'ল লাইব্রেরি ব্যবহার করা। এটি লজ্জার বিষয় যে সি ++ স্ট্যান্ডার্ড লাইব্রেরি এত কয়েকটি দরকারী কাজ করে।
মাস্টারসিল্লো

1
@ মাস্টারেক্সিলো এই সমস্যাটি সমাধান করার জন্য আপনি কোন লাইব্রেরির প্রস্তাব দিচ্ছেন এবং সেই লাইব্রেরিটি কীভাবে একটি (মূলত) এক-লাইন ফাংশনটির চেয়ে ভাল পছন্দ?
ব্র্যান্ডিন

33
@ ব্র্যান্ডিন কারণ এটি এমন একটি প্রাথমিক কার্যকারিতা। সি ++ আমাদের বারবার একই ক্রিয়াকলাপগুলি পুনরায় প্রোগ্রাম করতে বাধ্য করে যা অন্য যে কোনও আধুনিক কম্পিউটার ভাষায় বাইরের বাইরে সরবরাহ করা হয়। এই প্রশ্নটি সমাধান করার জন্য লোকেরা স্ট্যাকওভারফ্লোতে যেতে হবে এমন একটি পিবি রয়েছে তা দেখায়।
কনচিলেক্ল্যাটার

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
সাবধান হন যে এমএসভিসি 10 এই সমাধানটি পছন্দ করে না: std::equal(suffix.rbegin(), suffix.rend(), str.rbegin()ডিবাগ মোডে, এটি ছুঁড়ে দেয়:_DEBUG_ERROR("string iterator not decrementable");
রিমাই সিএটিএউইনু

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 স্টাড :: স্ট্রিং থেকে শুরু করে অবশেষে প্রারম্ভ_ও এবং শেষ_সমেত প্রদান করবে । মনে হচ্ছে এমন একটি সম্ভাবনা রয়েছে যে সি ++ এর সি ++ এর 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));
}

আইএমও, সি ++ স্ট্রিংগুলি স্পষ্টতই অকার্যকর এবং এগুলি বাস্তব বিশ্বের কোডে ব্যবহার করার জন্য তৈরি করা হয়নি। তবে একটি আশা আছে যে এটি কমপক্ষে আরও ভাল হয়ে উঠবে।


2
যেহেতু str.compare কোনও বুলিয়ান দেয় না, তাই "== 0" এর জন্য ("!") অপারেটরটি ব্যবহার করে পরীক্ষা করা এত স্মার্ট নয়, এটি পাঠকদের জন্য বিভ্রান্তিকর হতে পারে। স্পষ্টতার জন্য দয়া করে "... && str.compare (...) == 0" ব্যবহার করুন।
থমাস টেম্পেলম্যান

@ পাভেল স্ট্যান্ড :: স্ট্রিং :: আপনার "স্টার্টস উইথ" পদ্ধতিতে খুঁজে না পাওয়ার কি কারণ আছে?
ম্যাক্সিম ওডট

4
@ ম্যাক্সিমোউডট বন্ধ কোর্স আছে! আপনি যদি কিছু জানতে শুরু করেন যে এটি কিছু দিয়ে শুরু হয় তবে কেন আপনি পুরো স্ট্রিংটি অনুসন্ধান করতে চান? অন্য কথায়, টুকরোটি শেষে আপনি 100 মিমি দীর্ঘ স্ট্রিংটি অনুসন্ধান করতে পারেন এবং তারপরে ফলাফলটি উপেক্ষা করতে পারেন কারণ এটি স্ট্রিংয়ের শুরুতে নয়।
পাভেল পি

1
সি ++ 30 পূর্বাভাসের জন্য প্লাস "1"।
নির্দোষ বাইস্ট্যান্ডার

40

আমি প্রশ্নটি সি ++ এর জন্য জানি, তবে কারও যদি এটির জন্য কোনও ভাল অল এর ফ্যাশনযুক্ত সি ফাংশন প্রয়োজন হয়:


/*  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 টি। আমি এর আগে কখনও স্টাডি :: মেলানো () খেয়াল করিনি - আমি অবাক হয়েছি যে সেই অ্যালগরিদম শিরোলেখের ফাইলটিতে আর কী আছে যা আমি কখনও দেখিনি ...
j_random_hacker

3
আমি মনে করি এটি নিজস্ব কোনও SO প্রশ্নের পক্ষে মূল্যবান: আপনি কি কখনও স্টল ফাংশনগুলি ব্রাউজ করেছেন?
xtofl

2
মনে রাখবেন যে এর একই প্রয়োজনীয়তা রয়েছে std::equal: আপনার আগে থেকেই পরীক্ষা করে নেওয়া উচিত যে অনুমিত প্রত্যয়টি আপনি যে স্ট্রিংটি অনুসন্ধান করছেন তার চেয়ে দীর্ঘ নয় that এটি যা অপরিজ্ঞাত আচরণের দিকে পরিচালিত করে তা তদন্ত করতে অবহেলা করা।
রব কেনেডি

18

আমার মতে সবচেয়ে সহজ, সি ++ সমাধানটি হ'ল:

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

10
এই যেহেতু আপনি সমগ্র স্ট্রিং অনুসন্ধান করব বরং ধীর sশুধু এটা শেষে পরীক্ষা পরিবর্তে!
অ্যালেক্সিস উইল্ক

2
@ নোডাকাই, যদি আমার কাছে 1 এমবি স্ট্রিং থাকে তবে এটি ন্যানোসেকেন্ডের চেয়ে অনেক বেশি হবে।
অ্যালেক্সিস উইলক

আমি মনে করি না ... এটি কোনও অবস্থাতেই স্ট্রেন করা দরকার, এবং তারপরে শেষ থেকে সন্ধান করা শুরু করে।
LtWorf

2
@ এলটি ওয়ার্ফ std::string::size()একটি ধ্রুবক সময় অপারেশন; এটির দরকার নেই strlen
থমাস

2
প্রত্যয়.সাইজ () == এস.সাইজ () + ১. কেস স্নিপেট এই অনলাইন gdb.com/S1ITVqKDL দেখায় এমন ক্ষেত্রে কীভাবে এটি এমনকি বিবেচিত সমাধান হিসাবে বিবেচিত হবে । জটিলতা অপ্রাসঙ্গিক যদি এটি সমস্ত ক্ষেত্রে সঠিকভাবে কাজ না করে।
c0ntrol

10

দিন aএকটি স্ট্রিং এবং হতে bস্ট্রিং তোমার জন্য দেখুন। ব্যবহারের a.substrশেষ এন অক্ষর পেতে 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 বা উভয়ই শেষ হয়ে গেলে আমি কীভাবে সত্য ফিরে আসতে পারি ??? ধন্যবাদ!
সোমবার 11'14

@ডারিও: আপনার স্টাডি :: সমান () ব্যবহারের সমাধানটি ভাল, সাবস্ট্রাস্টার () ব্যবহার করে এমনটি এত বেশি নয় - যদি না আপনি COW স্ট্রিং ব্যবহার করেন (এবং কয়েক জনই আমি বিশ্বাস করি), সাবস্ট্রাস্ট () বোঝায় দ্বিতীয় কপি তৈরি করা স্ট্রিং এর অংশ, গতিশীল মেমরি বরাদ্দ জড়িত। এটি ব্যর্থ হতে পারে এবং যে কোনও ক্ষেত্রে অন্যান্য সমাধানের চেয়ে বেশি মেমরি ব্যবহৃত হয় (এবং এটি অন্যান্য সমাধানের চেয়ে প্রায় অবশ্যই ধীর)।
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
starts_with'স্ট্রিং :: তুলনা' কেন ব্যবহার করে? না কেন std::equal(start.begin(), start.end(), str.begin())?
Dmytro Ovdiienko

আমার প্রথম প্রয়োজনটি শুরু করার কারণেই _ শেষ_ও পরে যুক্ত করা হয়েছে।
ডডজ্যাঙ্গো

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));
}

সম্ভবত এত দক্ষ না, তবে কার্যকর করা সহজ।


সি ++ 11 বা তার বেশি বয়সী যে কারও পক্ষে এটি খুব সুবিধাজনক।
ক্লেয়ার ম্যাক্রে

সাবধান, রেগেক্সগুলি সি ++ তে অত্যন্ত ধীর হতে পারে!
mxMLnkn

এর জন্য রেজেক্স এর মতো ... আমার এটি ডাউনভোট করা দরকার। আমি করব না তবে আমার উচিত।
এমকে

2

আপনি স্ট্রিং :: আরফাইন্ড ব্যবহার করতে পারেন

মন্তব্যের ভিত্তিতে পূর্ণ উদাহরণ:

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। হ্যাঁ আপনি এটি ব্যবহার করতে পারেন, তবে স্ট্রিং সরবরাহকৃত সমাপ্তির সাথে শেষ না হওয়ার কারণে এটি অযথা ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে পড়ে থাকবে scan এছাড়াও, আপনি উল্লেখ করেন নি যে স্ট্রিংয়ের শেষের সাথে স্ট্রিংয়ের অন্যত্রের চেয়ে শেষের ম্যাচগুলি মিলছে কিনা তা নিশ্চিত করার জন্য আপনাকে পরবর্তী পরীক্ষার প্রয়োজন ।
j_random_hacker

আমি কেবল প্রয়োজনীয় ফাংশনটির লিঙ্কটি রেখেছি এবং আমি মনে করি এটি স্ট্রিং রাইফাইন্ড (কী, স্ট্রিংলেন্থ () - কী.লাইনেথ (), কী.লাইনেথ ()) থেকে ডকুমেন্টেশন থেকে এটি করা খুব সহজ;
আহমেদ বলেছেন

ঠিক আছে, এটি দক্ষ - তবে সেই ক্ষেত্রে স্ট্রিং :: ফাইন্ড () ঠিক একইভাবে কাজ করবে। এছাড়াও আপনার কেস-দৈর্ঘ্য ()> স্ট্রাইলথেন্থ () - আপনার মন্তব্যে যে কোডটি প্রস্তাব করবেন সে ক্ষেত্রে এই ক্ষেত্রে ক্রাশ হবে সেই ক্ষেত্রে আপনাকে উল্লেখ করতে হবে। আপনি যদি এই তথ্যের সাথে আপনার উত্তরটি আপডেট করেন তবে আমি আমার -1 নামিয়ে দেব।
j_random_hacker

2

স্ট্রিংয়ের প্রত্যয় রয়েছে কিনা তা নীচে ব্যবহার করে দেখুন:

/*
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

গ্রাজেগরজ বেজিয়ার সাড়া সম্পর্কে Regarding আমি এই বাস্তবায়নটি ব্যবহার করেছি, তবে আসলটির একটি বাগ রয়েছে (আমি যদি ".." সাথে ".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

অনুরূপ "স্টার্ট উইথ" -র সমস্যাটির দুর্দান্ত উত্তরটি পেয়েছে:

একটি সি ++ এসডিডি :: স্ট্রিংটি একটি নির্দিষ্ট স্ট্রিং দিয়ে শুরু হয় কিনা এবং কীভাবে আমি একটি স্ট্রিংকে একটি ইনটে রূপান্তর করতে পারি তা আমি কীভাবে চেক করব?

আপনি কেবল স্ট্রিংয়ের শেষ স্থানে অনুসন্ধানের সমাধানটি গ্রহণ করতে পারেন:

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

এইভাবে আপনি এটি সংক্ষিপ্ত, দ্রুত করতে পারবেন, স্ট্যান্ডার্ড সি ++ ব্যবহার করতে এবং এটিকে পঠনযোগ্য করে তুলতে পারেন।


0

আপনি যদি আমার মতো হন এবং সি ++ পিউরিজমে না হন তবে এখানে একটি পুরানো স্কুল হাইব্রিড। স্ট্রিংগুলি মুষ্টিমেয় অক্ষরের চেয়ে বেশি হলে কিছুটা সুবিধা রয়েছে কারণ বেশিরভাগ 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;
}

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.