Find out if string ends with another string in C++
Asked Answered
S

22

365

How can I find out if a string ends with another string in C++?

Schoenfelder answered 17/5, 2009 at 8:19 Comment(0)
S
257

Simply compare the last n characters using 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;
}
Snowblind answered 17/5, 2009 at 8:34 Comment(13)
Yeah, this is the best way to do it, without doubt.Gloat
I tried but somehow it didn't work I need my code also to handle if after the ending it has \r or \n etc. thanks for the helpSchoenfelder
I always hate calculating indices of substrings, it's very off-by-one prone... I'ld rather iterate backwards from the end of both strings, trying to find a mismatch.Froze
@sofr: Sounds like you should be stripping \r and \n from the end of your strings first (either just fullString or both it and ending). The following function does this in-place: void trimCrLf(string& s) { string::size_type n = s.size(); if (n && s[n - 1] == '\n') --n; if (n && s[n - 1] == '\r') --n; s.erase(n); }Lapith
Just wanted to point out for the the usecase of ending = "" this will return true. (Which is expected behavior IMO, and also what Java does).Seraphic
@Gloat I don't agree. This is a no-brainer -- the best way to do it is to use a library. It's a shame the C++ Standard library does so few useful things.Aeriell
@Aeriell What library do you propose to solve this problem and how is that library a better choice than a (basically) one-line function?Feltonfelts
@Feltonfelts Because it's a such basic functionality. C++ forces us to reprogram again and again the same functionalities which are provided out-of-the-box in any other modern computer language. The fact that people need to go to stackoverflow to solve this question shows there is a pb.Sawfish
@Sawfish Wrong. You could have looked at the compare function or browsed the std::string member functions in any C++ documentation source. For example, look at the second if statement in the example here: cplusplus.com/reference/string/string/compare It is precisely the solution used in this answer.Feltonfelts
C++ should really look at Python to make trivial things easier! It does difficult stuff easily but easy stuff difficult.Centralize
@Brandin: I have NO idea what point you're trying to make. Javascript: String.prototype.endsWith(). Python: Python String endswith() Method, C#: String.EndsWith. Clojure: str/ends-with. Dart: endsWith. Go: hasSuffix (lolz). Haskel: isSuffixOf. Java: endsWith. Pascal: AnsiEndsStr (don't ask). Ruby: end_with. Rust: ends_with. Scala: endsWith. C++: An ugly patch of unreadableness which invariably generates 822 compiler errors. I've been programming professionally in C++ for as long as there was C++; and it's just gets worse without ever getting better.Fiddlestick
@RobinDavies Apparently the C++ committee listened to this -- As of C++20 it is in the language: en.cppreference.com/w/cpp/string/basic_string/ends_with On second look, the functionality is a bit counter intuitive. It is clearly there in compare, but not easy to use correctly for this case. The standard version is equivalent to return size() >= x.size() && compare(size() - x.size(), npos, x) == 0 which is basically what is written in this answer, but the standard formulation is more compact and is a member function of the same class.Feltonfelts
Anyway, the fact that it was not provided for so long in C++ was clearly to me a design choice of conservatism. Don't include things that are not clearly needed. Yet, in the end, std::ends_with seems like a useful addition. I would personally prefer to use the standard version, if I'm programming in C++20. If I'm programming for an older compiler, though, my preference is still to make my own function like this if needed, and not to get a third party library like Boost just to have a few things like this. The original commentor never actually answered which library she would have preferred.Feltonfelts
R
219

Use this function:

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());
}
Raveaux answered 15/1, 2010 at 15:59 Comment(2)
Beware that MSVC10 does not like this solution: std::equal(suffix.rbegin(), suffix.rend(), str.rbegin() In debug mode, it throws: _DEBUG_ERROR("string iterator not decrementable");Lauree
@Lauree I'm sure they fixed their big bug by now ;-)Ragged
M
178

Use boost::algorithm::ends_with (see e.g. 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));
Mcclees answered 12/6, 2011 at 21:36 Comment(1)
Since C++23, we can use the Standard Library function std::ranges::ends_with() instead.Cranny
S
178

Note, that starting from C++20, std::string provides starts_with and ends_with. Seems like there is a chance that by C++30 strings in C++ might finally become usable.

If you are stuck with an ancient environment, you can use these starts_with/ends_with with C++17:

#if __cplusplus >= 201703L // C++17 and later 
#include <string_view>

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

static bool starts_with(std::string_view str, std::string_view prefix)
{
    return str.size() >= prefix.size() && str.compare(0, prefix.size(), prefix) == 0;
}
#endif // C++17

If your environment is nearer prehistoric, you may use these:

#if __cplusplus < 201703L // pre C++17
#include <string>

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

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

// some extra helper overloads:

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

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

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

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

IMO, C++ strings are clearly dysfunctional, and weren't made to be used in real world code. But there is a hope that this will get better at least.

Scat answered 16/3, 2017 at 20:57 Comment(13)
Since str.compare does not return a boolean, it's not so smart to test for "==0" by using the not ("!") operator, as that may be confusing to readers. Please use "... && str.compare(...) == 0" for clarity.Calvincalvina
@Pavel Is there a reason to not use std::string::find in your "startsWith" methods?Radium
@MaximeOudot Off course there is! Why would you want to search entire string if you need to know if it starts with something? In other words, you may end up searching 100mb long string to find the piece at the end and then ignoring that result because it's not at the beginning of the string.Scat
Plus "1" for c++30 prediction.Antimere
+1 though you should not blindly and unnecessarily write the equality comparison backwards. It's never been a good idea, and most particularly in situations where you'd naturally get a syntax error if accidentally missing an =.Taynatayra
If you accept C++17 std::string_views instead, it is more versatile and you won't need those variants anymore for efficiency.Ragged
@Ragged Added string_view based versions. IMO if code that wanted to use these functions already had std::string args, then it's better to use std::string versions directlyScat
Creating std::string_view from a std::string is likely zero overhead, so no benefit to the std::string version at all.Cranny
I completely disagree with the opinion in this answer. In fact, I'd suggest that std::string has far too many member functions that merely duplicate what standard range algorithms provide (e.g. ends_with() member that just returns the same as std::ranges::ends_with(*this, other)).Cranny
What opinion are you referring to? Well, if you look into generated asm you'll see that using std::string refs directly is similar to raw pointers with no code generated. Converting to std::string_view is, as you say, likely, but it is not zero overhead. Depending on the use, that "likely" part may be the reason not to use std::strings at all. Also using std::string_view conversion generates code at call sites, this has impact on binary size for no reason.Scat
The opinion that C++ strings are "clearly dysfunctional". If you expect all relevant string functions to be members of std::string, then I could see why you might think that. But the string interface is much more than that, since it's a standard Range, and so fits perfectly with <algorithm>.Cranny
Seriously, any good compiler generates identical object code for string and string_view functions. That's what I mean by zero overhead.Cranny
it all depends. It's easy to craft a sample that proves otherwise: godbolt.org/z/enqWhzjerScat
L
49

I know the question's for C++, but if anyone needs a good ol' fashioned C function to do this:


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

  /*  note - it would be better to abort or return an error code here; see the comments  */
  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 );
}

Liederkranz answered 10/10, 2011 at 20:22 Comment(1)
If you expect a string but get a NULL, that's an error. Thus, I would assert() or crash, instead of silently plodding on with corrupt state.Ragged
F
27

The std::mismatch method can serve this purpose when used to backwards iterate from the end of both strings:

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() );
Froze answered 18/5, 2009 at 8:12 Comment(4)
+1. I'd never noticed std::mismatch() before -- I wonder what else is in that algorithms header file that I've never looked at...Lapith
I think that's worth a SO question on it's own: have you ever browsed through the stl functions available?Froze
Note that this has the same requirement as std::equal: you need to check in advance that the supposed suffix isn't longer than the string you're searching for it in. Neglecting to check that leads to undefined behavior.Heptode
@RobKennedy That could be remedied by using the 4-pronged std::mismatch().Ragged
L
17

In my opinion simplest, C++ solution is:

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

Warning: If the match fails, this will search the entire string backwards before giving up, and thus potentially waste a lot of cycles.

Leoleod answered 8/9, 2013 at 6:59 Comment(5)
This is rather slow since you'll search the entire string s instead of just testing the end of it!Cannae
@nodakai, if I happen to have a 1Mb string, it's going to be a lot more than nanoseconds.Cannae
I don't think so… it needs to do strlen in any case, and then starts looking from the end.Saltwort
And if it fails to match, it will search the entire string backwards before giving up. It needs to be a forward search starting from the candidate index: ssize_t maybe_index = s.size()-suffix.size(); return maybe_index > 0 && (s.find(suffix, maybe_index) == maybe_index);Maltose
@Saltwort std::string::size() is a constant-time operation; it doesn't need strlen.Adnopoz
E
12

Let a be a string and b the string you look for. Use a.substr to get the last n characters of a and compare them to b (where n is the length of b)

Or use std::equal (include <algorithm>)

Ex:

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());
}
Enfeeble answered 17/5, 2009 at 8:27 Comment(2)
How can i return true also if it ends after my string with \r or \n or both??? thanks!Schoenfelder
@Dario: Your solution using std::equal() is good, the one using substr() not so much -- unless you're using COW strings (and few people are I believe), substr() implies creating a second copy of part of the string, implying dynamic memory allocation is involved. This can may fail, and in any case means more memory is used than other solutions (and it's almost certainly slower than other solutions).Lapith
H
10

Use std::equal algorithm from <algorithms> with reverse iteration:

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

Starting from C++20 ends_with introduced.

Hg answered 7/5, 2020 at 14:46 Comment(5)
While this code may provide a solution to the question, it's better to add context as to why/how it works. This can help future users learn, and apply that knowledge to their own code. You are also likely to have positive feedback from users in the form of upvotes, when the code is explained.Evanescent
@borchvm, added some explaination, hope it helps to comprehendHg
What if LogExt.length() is greater than filename.length()? This will read past the beginning of filename, possibly segfaulting. Seems like a bug.Freeboard
It is ok if LogExt.length() is greater than filename.length(), std::equal returns false this way en.cppreference.com/w/cpp/algorithm/equalHg
@SomeGuy I believe you are right. The 3-iterator form of std::equal cannot infer filename.rend() and assumes that the length of filename is greater than LogExt. Safer to use 4-iterators form of std::equal (requires c++14). #21680751Evie
T
8

Let me extend Joseph's solution with the case insensitive version (online demo)

#include <string>
#include <cctype>

static bool EndsWithCaseInsensitive(const std::string& value, const std::string& ending) {
    if (ending.size() > value.size()) {
        return false;
    }
    return std::equal(ending.crbegin(), ending.crend(), value.crbegin(),
        [](const unsigned char a, const unsigned char b) {
            return std::tolower(a) == std::tolower(b);
        }
    );
}
Tonisha answered 3/1, 2018 at 22:27 Comment(4)
Unless you include tolower() using <ctype.h> instead of <cctype> (or use using), that might fail to compile. Also, plain char might be signed, making this UB.Ragged
@Deduplicator, thank you for your remarks. I have fixed my answer. But I don't understand your point about UB, could you please elaborate?Tonisha
Just see some docs. In short, you have to cast to unsigned char before passing it to tolower(). Easiest way is changing the lambdas argument types to unsigned char.Ragged
@Deduplicator, insane, thank you for pointing it out. I have fixed itTonisha
T
4

you can use string::rfind

The full Example based on comments:

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;
}
Tenebrous answered 17/5, 2009 at 8:38 Comment(3)
-1. Yes you could use it, but it's unnecessarily slow in the event that the string does not end with the supplied ending -- scanning will continue all the way back to the start of the string. Also, you don't mention that you need a subsequent test to make sure that the ending matches at the end of the string, rather than elsewhere in the string.Lapith
I just put the link of the needed function and I think it is very easy to do it from the documentation str.rfind(key,str.length()-key.length(),key.length());Tenebrous
OK, that's efficient -- but in that case string::find() would work just as well. Also you need to mention the case where key.length() > str.length() -- the code you suggest in your comment will crash in this case. If you update your answer with this info I'll drop my -1.Lapith
C
3

the very same as above, here is my solution

 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());
  }
Charissecharita answered 1/3, 2016 at 22:46 Comment(2)
Why starts_with does use 'string::compare'? Why not std::equal(start.begin(), start.end(), str.begin())?Garment
Just because starts_with was the first one I needed. ends_with was added later.Charissecharita
C
3

Check if str has suffix, using below:

/*
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;
}
Calycle answered 2/12, 2016 at 8:41 Comment(0)
E
3

If, like me, you need endsWith to check a file extension, you can use the std::filesystem library:

std::filesystem::path("/foo/bar.txt").extension() == ".txt"
Elviraelvis answered 25/3, 2021 at 17:1 Comment(0)
R
2

I thought it makes sense to post a raw solution that doesn't use any library functions...

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

Adding a simple std::tolower we can make this case insensitive

// 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;
}
Rigel answered 8/12, 2016 at 14:10 Comment(1)
thanks for adding this. light solutions are always greatSavill
N
1

Regarding Grzegorz Bazior response. I used this implementation, but original one has bug (returns true if I compare ".." with ".so"). I propose modified function:

bool endsWith(const string& s, const string& suffix)
{
    return s.size() >= suffix.size() && s.rfind(suffix) == (s.size()-suffix.size());
}
Nerves answered 5/12, 2014 at 8:47 Comment(0)
P
1

another option is to use regex. The following code makes the search insensitive to upper/lower case:

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

probably not so efficient, but easy to implement.

Proceeding answered 30/1, 2019 at 22:52 Comment(4)
For anyone with C++11 or above, this is very convenient.Cooker
Beware, regexes can be insanely slow in C++!Maduro
regex for this is like... I need to downvote this. I won't but I should.Tacheometer
what if suffix contains special characters? unfortunately this isn't reliableRotherham
N
0

If you're like me and no so into C++ purism, here's an old skool hybrid. There's some advantage when strings are more than a handful of characters, as most memcmp implementations compare machine words when possible.

You need to be in control of the character set. For example, if this approach is used with utf-8 or wchar type, there's some disadvantage as it won't support character mapping - e.g., when two or more characters are logically identical.

#include <cstdlib>
#include <string>

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

    if (prefixSize > valueSize)
    {
        return false;
    }

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


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

    if (suffixSize > valueSize)
    {
        return false;
    }

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

    return std::memcmp(valuePtr, suffix.data(), suffixSize) == 0;
}
Nina answered 25/11, 2017 at 17:37 Comment(0)
A
0

Found this nice answer to the similar "startWith"-problem:

How do I check if a C++ std::string starts with a certain string, and convert a substring to an int?

You can adopt the solution to only search at the last place in the string:

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

This way you can make it short, fast (it does not search the whole string like rfind does in this example), use standard c++ and make it readable.

Edit: Updated with empty-check.

Albertalberta answered 9/6, 2020 at 10:19 Comment(6)
This is missing the test for needle.size() > stack.size(). You only get away with it because the overflowing subtraction results in invalid pos argument to find() for reasonable-length strings. And I recommend accepting std::string_view arguments rather than requiring std::string to be constructed.Cranny
You don't need to. If the size of the needle is larger than the stack the starting position will wrap around and the function will return false. If you have problems with a solution I would recommend you to at least test run it first.Marmalade
I think it's possible to prove that stack.size() - needle.size() is always greater than stack.size() in that case, but it's certainly worth an explanatory comment. Otherwise it looks like a bug to the next coder editing it!Cranny
Well now we have your comment at least. For it to be a problem you need to have a size of needle that is larger than at least half of the memory's total ram, because size_t is large it can index all elements of any theoretical array on your system.Marmalade
Not necessarily half the total RAM - a conforming implementation may have more (virtual) memory than a single array can address. There's no requirement to be able to create an object as large as the address space (e.g. segmented x86 implementations may have a std::size_t that's smaller than their pointer types, I've heard). So the needle only needs to be larger than half the maximum object size - but the subtraction should still be safe.Cranny
Thats a interesting distinction I did not catch when I red about it. So like you say. It should be safe for most system if you plan to search with strings that is much smaller than the maximum object size, which should true for most cases.Marmalade
U
0
bool endswith(const std::string &str, const std::string &suffix)
{
    string::size_type totalSize = str.size();
    string::size_type suffixSize = suffix.size();

    if(totalSize < suffixSize) {
        return false;
    }

    return str.compare(totalSize - suffixSize, suffixSize, suffix) == 0;
}
Universal answered 10/9, 2020 at 8:2 Comment(0)
G
0

Based on Lasersköld's answer.

Code - Test on Godbolt.org

#include <iostream>
#include <string>

bool EndsWith(const std::string& data, const std::string& suffix)
{
    if(data.empty() or suffix.empty() or (data.length() < suffix.length()))
    {
        return false;
    }
    if(data ==  suffix)
    {
        return true;
    }
    return data.find(suffix, data.size() - suffix.size()) != std::string::npos;
}

int main()
{
   std::cout << std::boolalpha;
   std::cout << "Test 1 = " <<EndsWith("hello!😎", "😎") << std::endl; 
   std::cout << "Test 2 = " << EndsWith("😎hello!", "😎") << std::endl; 
   std::cout << "Test 3 = " << EndsWith("hello!😎 ", "😎") << std::endl; 
   std::cout << "Test 4 = " << EndsWith("hello!😎 ", " ") << std::endl; 
   std::cout << "Test 5 = " << EndsWith("", "😎") << std::endl; 
   std::cout << "Test 6 = " << EndsWith("hello!😎", "") << std::endl; 
   std::cout << "Test 7 = " << EndsWith("", "") << std::endl; 
   std::cout << "Test 8 = " << EndsWith("hello!😎", "hello!😎😎") << std::endl; 
   std::cout << "Test 9 = " << EndsWith("hello!😎", "hello!😎") << std::endl; 
   return 0;
}

Output

Test 1 = true
Test 2 = false
Test 3 = false
Test 4 = true
Test 5 = false
Test 6 = false
Test 7 = false
Test 8 = false
Test 9 = true
Gospodin answered 5/10, 2020 at 5:51 Comment(3)
Though we thank you for your answer, it would be better if it provided additional value on top of the other answers. In this case, your answer does not provide additional value, since another user already posted that solution. If a previous answer was helpful to you, you should vote it up instead of repeating the same information.Cranny
I checked the answers, and my answer is equal/similar to Lasersköld's answer. I apologize for not checking the other answers. I improved my answer and added credit to Lasersköld.Gospodin
I saw this now. I would much rather just get a comment for what test-cases that does not work and I could have fixed my answer. Also, there is only one of all of those checks you need to do no clear all your test cases (se my answer).Marmalade
O
-1

My two cents:

bool endsWith(std::string str, std::string suffix)
{
   return str.find(suffix, str.size() - suffix.size()) != string::npos;
}
Ornis answered 16/6, 2020 at 18:42 Comment(1)
This appears to be a copy of Lasersköld's answer, except it passes the strings by value, causing both to be copied unnecessarily.Cranny

© 2022 - 2024 — McMap. All rights reserved.