查找字符串是否以C++中的另一个字符串结尾

sof*_*ofr 252 c++ string ends-with

如何在C++中查找字符串是否以另一个字符串结尾?

kdt*_*kdt 200

只需比较最后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;
}
Run Code Online (Sandbox Code Playgroud)

  • @Brandin因为它是一个这样的基本功能.C++迫使我们一次又一次地重新编程在任何其他现代计算机语言中开箱即用的相同功能.人们需要去stackoverflow来解决这个问题的事实表明有一个pb. (24认同)
  • @Noldorin我不同意.这是一个明智的选择 - 最好的方法是使用库.令人遗憾的是,C++标准库几乎没有什么用处. (13认同)
  • 我总是讨厌计算子串的索引,它非常偏向于...我宁愿从两个字符串的末尾向后迭代,试图找到不匹配. (3认同)
  • @masterxilo 您建议使用什么库来解决这个问题,以及该库如何比(基本上)单行函数更好的选择? (3认同)
  • C++ 确实应该向 Python 学习,让琐碎的事情变得更容易!做困难的事很容易,做简单的事却很难。 (2认同)

小智 166

使用此功能:

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());
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,MSVC10不喜欢这个解决方案:`std :: equal(suffix.rbegin(),suffix.rend(),str.rbegin()`在调试模式下,它抛出:`_DEBUG_ERROR("string iterator not decrementable") ;` (3认同)
  • @remi.chateuneu 我确信他们现在已经修复了大错误;-) (2认同)

And*_*ner 151

使用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));
Run Code Online (Sandbox Code Playgroud)


Pav*_*l P 65

注意,从c ++ 20 std :: string开始最终将提供starts_withends_with.似乎有可能c ++中的c ++ 30字符串可能最终变得可用,如果你不是从遥远的未来读取它,你可以使用这些startsWith/endsWith:

#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);
}
Run Code Online (Sandbox Code Playgroud)

和一些额外的帮助重载:

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));
}
Run Code Online (Sandbox Code Playgroud)

IMO,c ++字符串显然功能失调,并没有在现实世界的代码中使用.但是希望这至少会变得更好.

  • 对于 c++30 预测加“1”。 (19认同)
  • @MaximeOudot 当然有!如果您需要知道它是否以某些东西开头,为什么要搜索整个字符串?换句话说,您最终可能会搜索 100mb 长的字符串以找到末尾的片段,然后忽略该结果,因为它不在字符串的开头。 (5认同)
  • 由于 str.compare 不返回布尔值,因此使用 not ("!") 运算符测试 "==0" 并不明智,因为这可能会使读者感到困惑。为清楚起见,请使用“... &amp;&amp; str.compare(...) == 0”。 (2认同)
  • 如果您接受 C++17 `std::string_view`,它会更加通用,并且您将不再需要这些变体来提高效率。 (2认同)

Tom*_*Tom 39

我知道C++的问题,但是如果有人需要一个好的'老式C函数来做到这一点:


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

  • 如果您期望一个字符串但得到一个“NULL”,那就是一个错误。因此,我会“assert()”或崩溃,而不是默默地在损坏的状态下继续前进。 (3认同)

xto*_*ofl 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() );
Run Code Online (Sandbox Code Playgroud)

  • +1.我之前从未注意到std :: mismatch() - 我想知道那个算法头文件中还有哪些我从未看过... (3认同)
  • 我认为这是值得的一个问题:你有没有浏览过可用的stl函数? (3认同)
  • 请注意,这与`std :: equal`具有相同的要求:您需要事先检查所假设的后缀是否不长于您正在搜索它的字符串.忽略检查会导致未定义的行为. (2认同)

baz*_*rek 16

在我看来最简单的,C++解决方案是:

bool endsWith(const string& s, const string& suffix)
{
    return s.rfind(suffix) == (s.size()-suffix.size());
}
Run Code Online (Sandbox Code Playgroud)

  • 这是相当慢的,因为你将搜索整个字符串`s`而不是只测试它的结尾! (7认同)
  • @LtWorf `std::string::size()` 是一个恒定时间操作;它不需要“strlen”。 (3认同)
  • @AlexisWilke慢吗?多少纳秒? (2认同)
  • @nodakai,如果我碰巧有1Mb字符串,它将会超过纳秒. (2认同)
  • 如果它“失败”匹配,它将在放弃之前向后搜索整个字符串。它需要从候选索引开始向前搜索: `ssize_t Maybe_index = s.size()-suffix.size(); 返回 Maybe_index &gt; 0 &amp;&amp; (s.find(suffix, Maybe_index) == Maybe_index);` (2认同)

Dar*_*rio 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());
}
Run Code Online (Sandbox Code Playgroud)


Ser*_*gei 10

使用 std::equal 算法进行<algorithms>反向迭代:

\n
std::string LogExt = ".log";\nif (std::equal(LogExt.rbegin(), LogExt.rend(), filename.rbegin())) {\n   \xe2\x80\xa6\n}\n
Run Code Online (Sandbox Code Playgroud)\n

从C++20开始ends_with引入。

\n

  • 虽然此代码可以提供问题的解决方案,但最好添加有关其工作原理/原因的上下文。这可以帮助未来的用户学习并将这些知识应用到他们自己的代码中。当代码被解释时,您也可能会以点赞的形式得到用户的积极反馈。 (2认同)
  • @SomeGuy 我相信你是对的。std::equal 的 3 迭代器形式无法推断 filename.rend() 并假设 filename 的长度大于 LogExt。使用 std::equal 的 4 迭代器形式更安全(需要 c++14)。/sf/ask/1517617601/ (2认同)

Pol*_*ear 6

让我用不区分大小写的版本扩展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);
        }
    );
}
Run Code Online (Sandbox Code Playgroud)