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

发布于 2024-12-12 14:41:22 字数 185 浏览 0 评论 0原文

我有两个要比较的字符串:StringString:。是否有一个库函数在传递这两个字符串时返回 true,但对于 StringOtherString 则返回 false?

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

I have two strings which I'd like to compare: String and String:. Is there a library function that would return true when passed these two strings, but false for say String and OtherString?

To be precise, I want to know whether one string is a prefix of another.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

请持续率性 2024-12-19 14:41:23

使用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.
}

Use std::mismatch. Pass in the shorter string as the first iterator range and the longer as the second iterator range. The return is a pair of iterators, the first is the iterator in the first range and the second, in the second rage. If the first is end of the first range, then you know the the short string is the prefix of the longer string e.g.

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.
}
寄居人 2024-12-19 14:41:23

这既高效又方便:

str.compare(0, pre.size(), pre) == 0

compare 速度很快,因为它使用快速的 traits::compare 方法,并且不需要复制任何数据。

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

请参阅 cplusplus.com 上的文档

我编写了一个 测试程序,它使用此代码来比较命令行上给出的前缀和字符串。

This is both efficient and convenient:

str.compare(0, pre.size(), pre) == 0

compare is fast because it uses the fast traits::compare method and doesn't have to copy any data.

Here, it will compare std::min(str.size(), pre.size()) characters but if the characters in the two ranges are equal it also checks the length of pre and returns a non-zero value if pre is longer than this.

See the documentation at cplusplus.com.

I've written a test program that uses this code to compare prefixes and strings given on the command line.

东京女 2024-12-19 14:41:23

如果您知道哪个字符串更短,则过程很简单,只需使用
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() );
}

If you know which string is shorter, the procedure is simple, just use
std::equal with the shorter string first. If you don't, something
like the following should work:

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() );
}
通知家属抬走 2024-12-19 14:41:23

当且仅当 YX 的前缀时,std::string(X).find(Y) 为零

std::string(X).find(Y) is zero if and only if Y is a prefix of X

情域 2024-12-19 14:41:23

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

str.starts_with(prefix)

另外,还有 ends_with 来检查后缀

After C++20, we can use starts_with to check if a string begins with given prefix.

str.starts_with(prefix)

Also, there is ends_with to check suffix

七秒鱼° 2024-12-19 14:41:23

使用 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;
}

With string::compare, you should be able to write something like:

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

Alternatively, in case we don't want to use the length() member function:

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;
}
你不是我要的菜∠ 2024-12-19 14:41:23

如果您可以合理地忽略任何多字节编码(例如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;
}

如果您坚持使用奇特的 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() );
}

If you can reasonably ignore any multi-byte encodings (say, UTF-8) then you can use strncmp for this:

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

If you insist on using a fancy C++ version, you can use the std::equal algorithm (with the added benefit that your function also works for other collections, not just strings):

// 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() );
}
绿萝 2024-12-19 14:41:23

简单来说怎么样:

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;
  }
}

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;

}

如果您有 C++17,您可以使用 std::string_view 编写更好的版本:

#include <string>
#include <string_view>

bool prefix(const std::string& a, const std::string& b) {
  if (a.size() > b.size()) {
    return std::string_view(a.c_str(),b.size()) == b;
  }
  else {
    return std::string_view(b.c_str(),a.size()) == a;
  }
}

使用 g++ 7 at -O3,这会折叠为单个 memcmp code> 调用,这比旧版本有相当大的改进。

How about simply:

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;
  }
}

C++ not C, safe, simple, efficient.

Tested with:

#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;

}

If you have C++17 you can write a better version of this, using std::string_view instead:

#include <string>
#include <string_view>

bool prefix(const std::string& a, const std::string& b) {
  if (a.size() > b.size()) {
    return std::string_view(a.c_str(),b.size()) == b;
  }
  else {
    return std::string_view(b.c_str(),a.size()) == a;
  }
}

With g++ 7 at -O3 this collapses to a single memcmp call, which is a fairly substantial improvement over the older version.

亣腦蒛氧 2024-12-19 14:41:23

最简单的方法是使用 substr()compare() 成员函数:

string str = "Foobar";
string prefix = "Foo";

if(str.substr(0, prefix.size()).compare(prefix) == 0) cout<<"Found!";

Easiest way is to use substr() and compare() member functions:

string str = "Foobar";
string prefix = "Foo";

if(str.substr(0, prefix.size()).compare(prefix) == 0) cout<<"Found!";
榕城若虚 2024-12-19 14:41:23

如果在 str1 的索引 0 处找到整个 str2,则 str1.find(str2) 返回 0:

#include <string>
#include <iostream>

// does str1 have str2 as prefix?
bool StartsWith(const std::string& str1, const std::string& str2)
{   
    return (str1.find(str2)) ? false : true;
}

// is one of the strings prefix of the another?
bool IsOnePrefixOfAnother(const std::string& str1, const std::string& str2)
{   
    return (str1.find(str2) && str2.find(str1)) ? false : true;
}

int main()
{
    std::string str1("String");
    std::string str2("String:");
    std::string str3("OtherString");

    if(StartsWith(str2, str1))
    {
        std::cout << "str2 starts with str1" << std::endl;      
    }
    else
    {
        std::cout << "str2 does not start with str1" << std::endl;
    }

    if(StartsWith(str3, str1))
    {
        std::cout << "str3 starts with str1" << std::endl;      
    }
    else
    {
        std::cout << "str3 does not start with str1" << std::endl;
    }

        if(IsOnePrefixOfAnother(str2, str1))
        {
            std::cout << "one is prefix of another" << std::endl;      
        }
        else
        {
            std::cout << "one is not prefix of another" << std::endl;
        }

        if(IsOnePrefixOfAnother(str3, str1))
        {
            std::cout << "one is prefix of another" << std::endl;      
        }
        else
        {
            std::cout << "one is not prefix of another" << std::endl;
        }

    return 0;
}

输出:

  str2 starts with str1
  str3 does not start with str1
  one is prefix of another
  one is not prefix of another

str1.find(str2) returns 0 if entire str2 is found at the index 0 of str1:

#include <string>
#include <iostream>

// does str1 have str2 as prefix?
bool StartsWith(const std::string& str1, const std::string& str2)
{   
    return (str1.find(str2)) ? false : true;
}

// is one of the strings prefix of the another?
bool IsOnePrefixOfAnother(const std::string& str1, const std::string& str2)
{   
    return (str1.find(str2) && str2.find(str1)) ? false : true;
}

int main()
{
    std::string str1("String");
    std::string str2("String:");
    std::string str3("OtherString");

    if(StartsWith(str2, str1))
    {
        std::cout << "str2 starts with str1" << std::endl;      
    }
    else
    {
        std::cout << "str2 does not start with str1" << std::endl;
    }

    if(StartsWith(str3, str1))
    {
        std::cout << "str3 starts with str1" << std::endl;      
    }
    else
    {
        std::cout << "str3 does not start with str1" << std::endl;
    }

        if(IsOnePrefixOfAnother(str2, str1))
        {
            std::cout << "one is prefix of another" << std::endl;      
        }
        else
        {
            std::cout << "one is not prefix of another" << std::endl;
        }

        if(IsOnePrefixOfAnother(str3, str1))
        {
            std::cout << "one is prefix of another" << std::endl;      
        }
        else
        {
            std::cout << "one is not prefix of another" << std::endl;
        }

    return 0;
}

Output:

  str2 starts with str1
  str3 does not start with str1
  one is prefix of another
  one is not prefix of another
赢得她心 2024-12-19 14:41:23

“查找”并检查位置 0 的结果有什么问题?

string a = "String";
string b = "String:";

if(b.find(a) == 0)
{
// Prefix

}
else
{
// No Prefix
}

What's wrong with the "find" and checking the result for position 0 ?

string a = "String";
string b = "String:";

if(b.find(a) == 0)
{
// Prefix

}
else
{
// No Prefix
}
讽刺将军 2024-12-19 14:41:23

我认为 strncmp 最接近您正在寻找的内容。

不过,如果改写的话,您可能会寻找 strstr(s2,s1)==s2,这不一定是最有效的方法。但你不想算出 n ;-)

好吧,好吧,C++ 版本将是 !s1.find(s2)

好吧,你可以让它更加c++,像这样: std::mismatch(s1.begin(),s1.end(),s2.begin()).first==s1.end()< /代码>。

I think strncmp is the closest to what you're looking for.

Though, if reworded, you may be looking for strstr(s2,s1)==s2, which is not necessarily the most performant way to do that. But you do not want to work out n ;-)

Okay, okay, the c++ version would be !s1.find(s2).

Okay, you can make it even more c++, something like this: std::mismatch(s1.begin(),s1.end(),s2.begin()).first==s1.end().

芯好空 2024-12-19 14:41:23

你可以使用这个:

对于c ++ 14或更少

bool has_prefix
    (const std::string& str, const std::string& prefix)  {
    return str.find(prefix, 0) == 0;
}

对于c ++ 17

//it's a little faster
auto has_prefix
    (const std::string& str, const std::string_view& prefix) -> decltype(str.find(prefix) == 0) {
    return str.find(prefix, 0) == 0;
}

You can use this:

for c++14 or less

bool has_prefix
    (const std::string& str, const std::string& prefix)  {
    return str.find(prefix, 0) == 0;
}

for c++17

//it's a little faster
auto has_prefix
    (const std::string& str, const std::string_view& prefix) -> decltype(str.find(prefix) == 0) {
    return str.find(prefix, 0) == 0;
}
固执像三岁 2024-12-19 14:41:23
bool IsPrefix(const std::string& prefix, const std::string& whole)
{
  return whole.size() >= prefix.size() && whole.compare(0, prefix.size(), prefix) == 0;
}
bool IsPrefix(const std::string& prefix, const std::string& whole)
{
  return whole.size() >= prefix.size() && whole.compare(0, prefix.size(), prefix) == 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文