问答中心分类: C++找出字符串是否以 C++ 中的另一个字符串结尾
0
匿名用户 提问 12分钟 前

如何确定一个字符串是否以 C++ 中的另一个字符串结尾?

22 Answers
0
kdt 回答 12分钟 前

简单对比一下最后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;
}
Noldorin 回复 12分钟 前

是的,毫无疑问,这是最好的方法。

sofr 回复 12分钟 前

我试过但不知何故它不起作用我还需要我的代码来处理如果在结束后它有 \r 或 \n 等谢谢你的帮助

xtofl 回复 12分钟 前

我总是讨厌计算子字符串的索引,它非常容易出错……我宁愿从两个字符串的末尾向后迭代,试图找到一个不匹配的地方。

j_random_hacker 回复 12分钟 前

@sofr:听起来您应该首先从字符串的末尾剥离 \r 和 \n (只是 fullString 或两者兼而有之)。以下函数就地执行此操作: void trimCrLf(string&amp; s) { string::size_type n = s.size(); if (n &amp;&amp; s[n – 1] == '\n') –n; if (n &amp;&amp; s[n – 1] == '\r') –n; s.erase(n); }

LeviX 回复 12分钟 前

只是想指出的用例ending = ""这将返回 true。 (这是 IMO 的预期行为,也是 Java 所做的)。

masterxilo 回复 12分钟 前

@Noldorin 我不同意。这很简单——最好的方法是使用库。遗憾的是,C++ 标准库做了这么少有用的事情。

Brandin 回复 12分钟 前

@masterxilo 您建议使用什么库来解决这个问题,该库如何比(基本上)单行函数更好?

Conchylicultor 回复 12分钟 前

@Brandin 因为它是一个如此基本的功能。 C++ 迫使我们一次又一次地重新编程与任何其他现代计算机语言开箱即用的相同功能。人们需要去stackoverflow来解决这个问题的事实表明有一个pb。

Brandin 回复 12分钟 前

@Conchylicultor 错了。您可以查看 compare 函数或浏览任何 C++ 文档源中的 std::string 成员函数。例如,查看示例中的第二个 if 语句:cplusplus.com/reference/string/string/compare这正是这个答案中使用的解决方案。

user997112 回复 12分钟 前

C++ 应该真正关注 Python 以使琐碎的事情变得更容易!它很容易做困难的事情,但容易做的事情很困难。

Robin Davies 回复 12分钟 前

@Brandin:我有知道你想表达什么观点。 Javascript:String.prototype.endsWith()。 Python:Python String endswith() 方法,C#:String.EndsWith。 Clojure:str/ends-with。飞镖:结束。去:hasSuffix (lolz)。哈斯克尔:isSuffixOf。 Java:结束。 Pascal:AnsiEndsStr(不要问)。红宝石:end_with。锈:ends_with。斯卡拉:结束。 C++:一个丑陋的不可读补丁,总是产生 822 编译器错误。只要有 C++,我就一直在用 C++ 进行专业编程。它只是变得更糟而没有变得更好。

Brandin 回复 12分钟 前

@RobinDavies 显然 C++ 委员会听取了这一点——从 C++20 开始,它采用以下语言:en.cppreference.com/w/cpp/string/basic_string/ends_with再看一遍,该功能有点反直觉。比较明显,但在这种情况下不容易正确使用。标准版相当于return size() >= x.size() && compare(size() - x.size(), npos, x) == 0这基本上是这个答案中所写的,但标准公式更紧凑,并且是同一类的成员函数。

Brandin 回复 12分钟 前

无论如何,在 C++ 中没有提供这么长时间的事实对我来说显然是保守主义的设计选择。不要包括没有明确需要的东西。然而,最后,std::ends_with 似乎是一个有用的补充。如果我用 C++20 编程,我个人更喜欢使用标准版本。但是,如果我正在为较旧的编译器编程,我的偏好仍然是在需要时制作我自己的函数,而不是仅仅为了拥有一些这样的东西而获得像 Boost 这样的第三方库。最初的评论者从未真正回答过她更喜欢哪个图书馆。

0
Joseph 回答 12分钟 前

使用这个功能:

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());
}
remi.chateauneu 回复 12分钟 前

请注意 MSVC10 不喜欢此解决方案:std::equal(suffix.rbegin(), suffix.rend(), str.rbegin()在调试模式下,它会抛出:_DEBUG_ERROR("string iterator not decrementable");

Deduplicator 回复 12分钟 前

@remi.chateauneu 我相信他们现在已经修复了他们的大错误 😉

0
Andre Holzner 回答 12分钟 前

利用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));
0
Pavel P 回答 12分钟 前

注意,从c++20std::string 最终将提供以。。开始以。。结束.似乎有机会通过 c++ 中的 c++30 字符串最终变得可用,如果您没有从遥远的将来阅读此内容,您可以将这些startsWith/endsWith 与 C++17 一起使用:

#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

IMO,c++ 字符串显然是功能失调的,并没有被用于现实世界的代码。但有希望至少会好转。

Thomas Tempelmann 回复 12分钟 前

由于 str.compare 不返回布尔值,因此使用 not (&quot;!&quot;) 运算符来测试 &quot;==0&quot; 并不是那么聪明,因为这可能会让读者感到困惑。为了清楚起见,请使用“… &amp;&amp; str.compare(…) == 0”。

Maxime Oudot 回复 12分钟 前

@Pavel 是否有理由不在您的“startsWith”方法中使用 std::string::find ?

Pavel P 回复 12分钟 前

@MaximeOudot 当然有!如果您需要知道它是否以某些东西开头,为什么要搜索整个字符串?换句话说,您最终可能会搜索 100mb 长的字符串以找到末尾的片段,然后忽略该结果,因为它不在字符串的开头。

Super-intelligent Shade 回复 12分钟 前

加“1”表示 c++30 预测。

Nick 回复 12分钟 前

+1 虽然你不应该盲目和不必要地向后写相等比较。这从来都不是一个好主意,尤其是在不小心丢失 = 时自然会出现语法错误的情况下。

Deduplicator 回复 12分钟 前

如果你接受 C++17std::string_views 相反,它更加通用,您将不再需要这些变体来提高效率。

Pavel P 回复 12分钟 前

@Deduplicator 添加string_view基于版本。 IMO 如果想要使用这些功能的代码已经有了std::stringargs,那么最好直接使用 std::string 版本

0
Tom 回答 12分钟 前

我知道 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 );
}
Deduplicator 回复 12分钟 前

如果您期望一个字符串但得到一个NULL,这是一个错误。因此,我会assert()或崩溃,而不是在腐败状态下默默地步履蹒跚。