检查一个字符串是否是另一个字符串的前缀

fre*_*ley 44 c++ prefix string-comparison

我有两个字符串,我想比较一下:StringString:.是否有一个库函数在传递这两个字符串时会返回true,但是对于say StringOtherString

确切地说,我想知道一个字符串是否是另一个字符串的前缀.

Nim*_*Nim 50

使用std::mismatch.传入较短的字符串作为第一个迭代器范围,将较长的字符串作为第二个迭代器范围传递.返回是一对迭代器,第一个是第一个范围中的迭代器,第二个是第二个范围内的迭代器.如果第一个是第一个范围的结尾,那么您知道短字符串是较长字符串的前缀,例如

std::string foo("foo");
std::string foobar("foobar");

auto res = std::mismatch(foo.begin(), foo.end(), foobar.begin());

if (res.first == foo.end())
{
  // foo is a prefix of foobar.
}
Run Code Online (Sandbox Code Playgroud)

  • +1,但如果第二个字符串较短,那么这很危险,因为你会迭代它的结尾.因此需要检查`foo.size()<= foobar.size()`. (10认同)
  • +1,这实际上可以扩展为测试*共享一个前缀*而不是*是一个前缀*通过比较结果与`begin()`而不是end(并且可以得到公共前缀的实际长度,通过从其减去) (3认同)
  • @Benoit 注意,我认为您对大小的担忧已在 C++14 中得到解决。请参阅对 [mismatch](http://en.cppreference.com/w/cpp/algorithm/mismatch) 的返回值的评论。 (3认同)

Jam*_*nze 18

如果您知道哪个字符串更短,则过程很简单,只需先使用 std::equal较短的字符串即可.如果不这样,以下内容应该起作用:

bool
unorderIsPrefix( std::string const& lhs, std::string const& rhs )
{
    return std::equal(
        lhs.begin(),
        lhs.begin() + std::min( lhs.size(), rhs.size() ),
        rhs.begin() );
}
Run Code Online (Sandbox Code Playgroud)


MSa*_*ers 15

std::string(X).find(Y)当且仅当Y是前缀时,该值为零X

  • 这是简洁的,但可能效率低下(想象一下,如果`X`很长而且'Y`是*不是*X'的前缀). (5认同)
  • 它可能不是最有效的.编译器需要内联它,否则它也必须在非零偏移处搜索"Y". (4认同)

RY_*_*eng 14

在C++20之后,我们可以使用starts_with来检查字符串是否以给定的前缀开头。

str.starts_with(prefix)
Run Code Online (Sandbox Code Playgroud)

另外,还有ends_with来检查后缀


Nei*_*hew 10

这既高效又方便:

str.compare(0, pre.size(), pre) == 0
Run Code Online (Sandbox Code Playgroud)

compare之所以快,是因为它使用快速traits::compare方法并且不必复制任何数据。

在这里,它将比较std::min(str.size(), pre.size())字符,但是如果两个范围内的字符相等,则还将检查的长度,pre如果pre长度大于此值,则返回非零值。

请参阅cplusplus.com上的文档

  • @ony你是对的!不需要比较大小。我刚刚检查了 http://www.cplusplus.com/reference/string/string/compare/ 上的文档,只有当比较的两个字符范围长度相同时,“compare”才会返回“0”。如果“str”比“pre”短,则比较将返回负值(在我的测试中为“-1”)。我会编辑我的答案,但你应该有一份功劳。然而,我能做的最好的就是对你的评论进行投票。 (2认同)

Vla*_*lad 9

使用string :: compare,您应该可以编写如下内容:

bool match = (0==s1.compare(0, min(s1.length(), s2.length()), s2,0,min(s1.length(),s2.length())));

或者,如果我们不想使用length()成员函数:

bool isPrefix(string const& s1, string const&s2)
{
    const char*p = s1.c_str();
    const char*q = s2.c_str();
    while (*p&&*q)
        if (*p++!=*q++)
            return false;
    return true;
}
Run Code Online (Sandbox Code Playgroud)

  • `.length()是O(n)`?您是否有机会查看`character_traits`表? (4认同)
  • 在C++ 11中,`length()`必须占用恒定的时间; 在C++ 03中,它"应该". (4认同)
  • @FrerichRaabe:基本原理1)字符串需要在常量时间内知道`begin()`和`end()`,迭代器是随机的,所以它们可以在恒定时间内减去,差别就是字符串的大小,到它必须在恒定时间内*已知*.基本原理2)除非字符串用*ropes*实现(在C++ 11中禁止,未在任何*已知*当前标准库实现中实现),内存是连续的,这意味着*知道*`begin()`和`end()`并且知道`size()`是等价的,你需要存储三个中的两个,另一个可以在恒定时间内计算. (3认同)

Fre*_*abe 5

如果您可以合理地忽略任何多字节编码(例如,UTF-8),那么您可以使用strncmp:

// Yields true if the string 's' starts with the string 't'.
bool startsWith( const std::string &s, const std::string &t )
{
    return strncmp( s.c_str(), t.c_str(), t.size() ) == 0;
}
Run Code Online (Sandbox Code Playgroud)

如果您坚持使用花哨的C++版本,则可以使用该std::equal算法(附加的好处是您的函数也适用于其他集合,而不仅仅是字符串):

// Yields true if the string 's' starts with the string 't'.
template <class T>
bool startsWith( const T &s, const T &t )
{
    return s.size() >= t.size() &&
           std::equal( t.begin(), t.end(), s.begin() );
}
Run Code Online (Sandbox Code Playgroud)


Fle*_*exo 5

怎么样简单:

bool prefix(const std::string& a, const std::string& b) {
  if (a.size() > b.size()) {
    return a.substr(0,b.size()) == b;
  }
  else {
    return b.substr(0,a.size()) == a;
  }
}
Run Code Online (Sandbox Code Playgroud)

C++不是C,安全,简单,高效.

经测试:

#include <string>
#include <iostream>

bool prefix(const std::string& a, const std::string& b);

int main() {
  const std::string t1 = "test";
  const std::string t2 = "testing";
  const std::string t3 = "hello";
  const std::string t4 = "hello world";
  std::cout << prefix(t1,t2) << "," << prefix(t2,t1) << std::endl;
  std::cout << prefix(t3,t4) << "," << prefix(t4,t3) << std::endl;
  std::cout << prefix(t1,t4) << "," << prefix(t4,t1) << std::endl;
  std::cout << prefix(t1,t3) << "," << prefix(t3,t1) << std::endl;

}
Run Code Online (Sandbox Code Playgroud)