How to find if string endswith another string c++
+2
A:
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());
}
Dario
2009-05-17 08:27:09
How can i return true also if it ends after my string with \r or \n or both???thanks!
sofr
2009-05-17 11:14:46
@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).
j_random_hacker
2009-05-18 09:37:03
+16
A:
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;
}
kdt
2009-05-17 08:34:04
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 help
sofr
2009-05-17 14:14:15
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.
xtofl
2009-05-18 08:15:25
@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 if (n if (n s.erase(n); }
j_random_hacker
2009-05-18 09:30:32
I believe the comparison operator ought to be >= rather than simply >.
Skinniest Man
2010-02-16 20:28:49
A:
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;
}
Ahmed Said
2009-05-17 08:38:51
-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.
j_random_hacker
2009-05-17 09:56:30
I just put the link of the needed function and I think it is very easy to do it from the documentationstr.rfind(key,str.length()-key.length(),key.length());
Ahmed Said
2009-05-17 10:13:49
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.
j_random_hacker
2009-05-17 16:04:03
+4
A:
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() );
xtofl
2009-05-18 08:12:09
+1. I'd never noticed std::mismatch() before -- I wonder what else is in that algorithms header file that I've never looked at...
j_random_hacker
2009-05-18 09:20:47
I think that's worth a SO question on it's own: have you ever browsed through the stl functions available?
xtofl
2009-05-18 09:27:42
A:
If you want to ignore '\n' and '\r' at the end of the string, you could modify jcs' solution as follows:
#include <iostream>
bool hasEnding (std::string const &fullString, std::string const &ending)
{
unsigned int lastMatchPos = fullString.rfind(ending); // Find the last occurrence of ending
bool isEnding = lastMatchPos != std::string::npos; // Make sure it's found at least once
// If the string was found, make sure that any characters that follow it are the ones we're trying to ignore
for( int i = lastMatchPos + ending.length(); (i < fullString.length()) && isEnding; i++)
{
if( (fullString[i] != '\n') &&
(fullString[i] != '\r') )
{
isEnding = false;
}
}
return isEnding;
}
int _tmain(int argc, _TCHAR* argv[])
{
std::string test1 = "binary";
std::string test2 = "unary\n\r";
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;
getchar();
return 0;
}
Jon Cage
2009-05-18 08:52:22
rfind could spend a lot of time scanning the string looking for a match that isn't at the end, only to throw that work away later. kdt's answer is better and can be easily modified to start the comparison earlier in fullString--just subtract the number of skippable characters appearing at the end of fullString.
Ken Fox
2010-01-15 16:13:17
+1
A:
what about:
if (std::equal(suffix.rbegin(), suffix.rend(), str.rbegin())
{
//ends with....
}
else
{
//does not end with...
}
Joseph
2010-01-15 15:59:34