如何在C++中判断一个字符串是否以另一个字符串结尾?
使用std::string::compare
比较最后n个字符即可:
#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;
}
使用这个函数:
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());
}
std::equal(suffix.rbegin(), suffix.rend(), str.rbegin()
在调试模式下,它会抛出错误:“_DEBUG_ERROR("string iterator not decrementable");”请小心使用。 - remi.chateauneu使用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));
请注意,从c++20开始,std::string
最终将提供starts_with
和ends_with
。如果您不是从遥远的未来阅读此信息,那么您可以在C++17中使用这些startsWith
/endsWith
函数。似乎有机会在c++30中,c++中的字符串可能最终变得更加易用。
#if __cplusplus >= 201703L // C++17 and later
#include <string_view>
static bool endsWith(std::string_view str, std::string_view suffix)
{
return str.size() >= suffix.size() && 0 == str.compare(str.size()-suffix.size(), suffix.size(), suffix);
}
static bool startsWith(std::string_view str, std::string_view prefix)
{
return str.size() >= prefix.size() && 0 == str.compare(0, prefix.size(), prefix);
}
#endif // C++17
如果你被困在使用较旧的C++,可以使用以下内容:
#if __cplusplus < 201703L // pre C++17
#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));
}
#endif
在我看来,C++ 字符串显然是有缺陷的,并且并不适合在实际的代码中使用。但至少还有希望会变得更好。
std::string_view
,它更加通用,而且您将不再需要那些变量来提高效率。 - Deduplicatorstring_view
的版本。在我看来,如果想要使用这些函数的代码已经有了 std::string
参数,那么最好直接使用 std::string
版本。 - Pavel P我知道问题是关于C++的,但如果有人需要一个好老式的C函数来做这个:
/* 当且仅当str以suffix结尾时返回1 */
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 );
}
NULL
,那就是一个错误。因此,我会使用 assert()
或者崩溃来处理,而不是默默地在损坏状态下继续执行。 - Deduplicator当需要从两个字符串的末尾开始迭代时,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() );
std::equal
具有相同的要求:您需要事先检查所假定的后缀是否不比您正在搜索它的字符串更长。忽略该检查将导致未定义的行为。 - Rob Kennedy依我之见,最简单的 C++ 解法如下:
bool endsWith(const std::string& s, const std::string& suffix)
{
return s.rfind(suffix) == std::abs(s.size()-suffix.size());
}
警告:如果匹配失败,这将在放弃之前向后搜索整个字符串,因此可能会浪费大量的循环。
s
而不是仅测试其结尾! - Alexis Wilkessize_t maybe_index = s.size()-suffix.size(); return maybe_index > 0 && (s.find(suffix, maybe_index) == maybe_index);
- ncoghlanstd::string::size()
是一个常数时间的操作,它不需要 strlen
。 - Thomas假设字符串a和你要查找的字符串b,使用a.substr获取a的最后n个字符并将其与b进行比较(其中n是b的长度)
或者使用std :: equal(包括)
例如:
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());
}
使用来自<algorithms>
的std::equal算法进行反向迭代:
std::string LogExt = ".log";
if (std::equal(LogExt.rbegin(), LogExt.rend(), filename.rbegin())) {
…
}
从C++20开始引入了ends_with
函数。
让我用不区分大小写的版本扩展Joseph的解决方案(在线演示)。
#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);
}
);
}
<ctype.h>
而不是<cctype>
(或使用using),并包含tolower()
,否则可能无法编译。此外,普通的char
可能是有符号的,从而导致未定义行为。 - Deduplicatortolower()
之前,您必须将其转换为“unsigned char”。最简单的方法是将lambda表达式的参数类型更改为“unsigned char”。 - Deduplicator