检查字符串是否包含C ++中的字符串


493

我有一个类型的变量 std::string。我想检查它是否包含某个std::string。我该怎么做?

是否存在一个函数,如果找到该字符串,则返回true;否则,返回false?


6
您是指char *字符串还是STL中的字符串?
anthares 2010年

1
这不是一个char *字符串。我必须#include <string>才能使用它。
Neuromancer 2010年

1
一些解决方案将s2用作我要查找的字符串。如果我使用诸如“ this is a string”之类的东西而不是s2,它仍然可以工作吗?
Neuromancer

2
是的,因为有一个std :: string类型的字符串literl构造函数。

18
有人建议添加std::basic_string::contains到stdlib。
埃莱2016年

Answers:


722

用法std::string::find如下:

if (s1.find(s2) != std::string::npos) {
    std::cout << "found!" << '\n';
}

注意:“找到了!” 如果s2s1s1和的子字符串,且s2类型为,将被打印std::string


117

您可以尝试使用以下find功能:

string str ("There are two needles in this haystack.");
string str2 ("needle");

if (str.find(str2) != string::npos) {
//.. found.
} 

27

实际上,您可以尝试使用boost库,我认为std :: string没有提供足够的方法来执行所有常见的字符串操作。在boost中,您可以仅使用boost::algorithm::contains

#include <string>
#include <boost/algorithm/string.hpp>

int main() {
    std::string s("gengjiawen");
    std::string t("geng");
    bool b = boost::algorithm::contains(s, t);
    std::cout << b << std::endl;
    return 0;
}

32
“我认为std :: string没有提供足够的方法来执行所有常见的字符串操作”。但是,有一种find方法可以准确地解决所讨论的任务。无需引入库依赖性。
stefan 2014年

8
@stefan,您是对的,有一个查找方法,但是split,replace和其他许多人员呢。您可以将std :: string与Java中的字符串api进行比较。查找检查一个字符串是否包含另一个字符串。
耿家文

1
而且这很短,并且更易于记忆。Cpp 17增加了对文件系统的支持。我希望Cpp 2x也可以为字符串做些事情。在现代cpp中缺少基本的字符串方法支持是非常痛苦的。
耿家文

1
您是否真的需要“用法”?当我阅读此代码时,我不知道containsis std::contains还是boost::contains,这似乎是一个重大缺陷。我猜std :: contains当前不存在,但是我不确定假设读者已经记住了std中的所有内容是否合理。并且std::contains可能会在将来的c ++版本中存在,这可能会破坏该程序。
唐·哈奇

12

你可以试试这个

string s1 = "Hello";
string s2 = "el";
if(strstr(s1.c_str(),s2.c_str()))
{
   cout << " S1 Contains S2";
}

4

如果功能对于您的系统至关重要,则使用旧strstr方法实际上是有益的。其中的std::search方法algorithm是最慢的。我的猜测是创建这些迭代器会花费很多时间。

我用来计时整个事情的代码是

#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <random>
#include <chrono>

std::string randomString( size_t len );

int main(int argc, char* argv[])
{
        using namespace std::chrono;

        const size_t haystacksCount = 200000;
        std::string haystacks[haystacksCount];
        std::string needle = "hello";

        bool sink = true;

        high_resolution_clock::time_point start, end;
        duration<double> timespan;

        int sizes[10] = { 10, 20, 40, 80, 160, 320, 640, 1280, 5120, 10240 };

        for(int s=0; s<10; ++s)
        {
                std::cout << std::endl << "Generating " << haystacksCount << " random haystacks of size " << sizes[s] << std::endl;
                for(size_t i=0; i<haystacksCount; ++i)
                {
                        haystacks[i] = randomString(sizes[s]);
                }

                std::cout << "Starting std::string.find approach" << std::endl;
                start = high_resolution_clock::now();
                for(size_t i=0; i<haystacksCount; ++i)
                {
                        if(haystacks[i].find(needle) != std::string::npos)
                        {
                                sink = !sink; // useless action
                        }
                }
                end = high_resolution_clock::now();
                timespan = duration_cast<duration<double>>(end-start);
                std::cout << "Processing of " << haystacksCount << " elements took " << timespan.count() << " seconds." << std::endl;

                std::cout << "Starting strstr approach" << std::endl;
                start = high_resolution_clock::now();
                for(size_t i=0; i<haystacksCount; ++i)
                {
                        if(strstr(haystacks[i].c_str(), needle.c_str()))
                        {
                                sink = !sink; // useless action
                        }
                }
                end = high_resolution_clock::now();
                timespan = duration_cast<duration<double>>(end-start);
                std::cout << "Processing of " << haystacksCount << " elements took " << timespan.count() << " seconds." << std::endl;

                std::cout << "Starting std::search approach" << std::endl;
                start = high_resolution_clock::now();
                for(size_t i=0; i<haystacksCount; ++i)
                {
                        if(std::search(haystacks[i].begin(), haystacks[i].end(), needle.begin(), needle.end()) != haystacks[i].end())
                        {
                                sink = !sink; // useless action
                        }
                }
                end = high_resolution_clock::now();
                timespan = duration_cast<duration<double>>(end-start);
                std::cout << "Processing of " << haystacksCount << " elements took " << timespan.count() << " seconds." << std::endl;
        }

        return 0;
}

std::string randomString( size_t len)
{
        static const char charset[] = "abcdefghijklmnopqrstuvwxyz";
        static const int charsetLen = sizeof(charset) - 1;
        static std::default_random_engine rng(std::random_device{}());
        static std::uniform_int_distribution<> dist(0, charsetLen);
        auto randChar = [charset, &dist, &rng]() -> char
        {
                return charset[ dist(rng) ];
        };

        std::string result(len, 0);
        std::generate_n(result.begin(), len, randChar);
        return result;
}

在这里,我生成随机数haystacks并在其中搜索needle。设置了干草堆计数,但是每个干草堆中字符串的长度从开始的10增加到最后的10240。程序大部分时间实际上是在生成随机字符串,但这是可以预期的。

输出为:

Generating 200000 random haystacks of size 10
Starting std::string.find approach
Processing of 200000 elements took 0.00358503 seconds.
Starting strstr approach
Processing of 200000 elements took 0.0022727 seconds.
Starting std::search approach
Processing of 200000 elements took 0.0346258 seconds.

Generating 200000 random haystacks of size 20
Starting std::string.find approach
Processing of 200000 elements took 0.00480959 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00236199 seconds.
Starting std::search approach
Processing of 200000 elements took 0.0586416 seconds.

Generating 200000 random haystacks of size 40
Starting std::string.find approach
Processing of 200000 elements took 0.0082571 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00341435 seconds.
Starting std::search approach
Processing of 200000 elements took 0.0952996 seconds.

Generating 200000 random haystacks of size 80
Starting std::string.find approach
Processing of 200000 elements took 0.0148288 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00399263 seconds.
Starting std::search approach
Processing of 200000 elements took 0.175945 seconds.

Generating 200000 random haystacks of size 160
Starting std::string.find approach
Processing of 200000 elements took 0.0293496 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00504251 seconds.
Starting std::search approach
Processing of 200000 elements took 0.343452 seconds.

Generating 200000 random haystacks of size 320
Starting std::string.find approach
Processing of 200000 elements took 0.0522893 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00850485 seconds.
Starting std::search approach
Processing of 200000 elements took 0.64133 seconds.

Generating 200000 random haystacks of size 640
Starting std::string.find approach
Processing of 200000 elements took 0.102082 seconds.
Starting strstr approach
Processing of 200000 elements took 0.00925799 seconds.
Starting std::search approach
Processing of 200000 elements took 1.26321 seconds.

Generating 200000 random haystacks of size 1280
Starting std::string.find approach
Processing of 200000 elements took 0.208057 seconds.
Starting strstr approach
Processing of 200000 elements took 0.0105039 seconds.
Starting std::search approach
Processing of 200000 elements took 2.57404 seconds.

Generating 200000 random haystacks of size 5120
Starting std::string.find approach
Processing of 200000 elements took 0.798496 seconds.
Starting strstr approach
Processing of 200000 elements took 0.0137969 seconds.
Starting std::search approach
Processing of 200000 elements took 10.3573 seconds.

Generating 200000 random haystacks of size 10240
Starting std::string.find approach
Processing of 200000 elements took 1.58171 seconds.
Starting strstr approach
Processing of 200000 elements took 0.0143111 seconds.
Starting std::search approach
Processing of 200000 elements took 20.4163 seconds.

答案的简短版本是:使用c代替c ++ :)
r0ng

3

如果您不想使用标准库函数,下面是一种解决方案。

#include <iostream>
#include <string>

bool CheckSubstring(std::string firstString, std::string secondString){
    if(secondString.size() > firstString.size())
        return false;

    for (int i = 0; i < firstString.size(); i++){
        int j = 0;
        // If the first characters match
        if(firstString[i] == secondString[j]){
            int k = i;
            while (firstString[i] == secondString[j] && j < secondString.size()){
                j++;
                i++;
            }
            if (j == secondString.size())
                return true;
            else // Re-initialize i to its original value
                i = k;
        }
    }
    return false;
}

int main(){
    std::string firstString, secondString;

    std::cout << "Enter first string:";
    std::getline(std::cin, firstString);

    std::cout << "Enter second string:";
    std::getline(std::cin, secondString);

    if(CheckSubstring(firstString, secondString))
        std::cout << "Second string is a substring of the frist string.\n";
    else
        std::cout << "Second string is not a substring of the first string.\n";

    return 0;
}

6
您已经在使用std :: string,因此您的代码已经取决于std lib。我几乎看不出为什么要避免使用std :: string :: find接受解决方案的任何原因。
b00n12 '18

是的,这很不错。当我写这篇文章的时候没有想到。我想我写这篇文章时的想法也许就是避免使用std :: find的方法。
测试123年

3
仅针对未来的访客:此算法实际上并不正确。由于子字符串匹配失败后“ i”再也不会返回,因此某些情况下将不匹配,例如,请考虑:aaabc,aab
sAm_vdP

1
这有几个错误。 CheckSubstring(std::string firstString, std::string secondString)深度复制传递给函数的两个字符串,这很昂贵,尤其是对于需要堆分配的较长字符串而言。另外,说你叫CheckSubstring("XYZab", "ab\0\0")-的while循环将结束比较aabb在第一个字符串在第二明确NUL结束隐含NUL,那么它会读取超出第一个字符串的缓冲区,有不确定的行为。要修复,请使用for (... i <= firstString.size()-secondString()。size(); ...)`。
托尼·德罗伊

1

如果字符串的大小相对较大(数百个字节或更多),并且可以使用c ++ 17,则可能要使用Boyer-Moore-Horspool搜索器(来自cppreference.com的示例):

#include <iostream>
#include <string>
#include <algorithm>
#include <functional>

int main()
{
    std::string in = "Lorem ipsum dolor sit amet, consectetur adipiscing elit,"
                     " sed do eiusmod tempor incididunt ut labore et dolore magna aliqua";
    std::string needle = "pisci";
    auto it = std::search(in.begin(), in.end(),
                   std::boyer_moore_searcher(
                       needle.begin(), needle.end()));
    if(it != in.end())
        std::cout << "The string " << needle << " found at offset "
                  << it - in.begin() << '\n';
    else
        std::cout << "The string " << needle << " not found\n";
}

3
时代的迹象。在过去,有人会提供功能bool contains(const std::string& haystack, const std::string& needle)。如今,他们提供了一套益智作品集,这些作品以一些晦涩的论文作者来命名,以使其看起来更像计算机科学……
BitTickler

0

您还可以使用系统名称空间。然后,您可以使用contains方法。

#include <iostream>
using namespace System;

int main(){
    String ^ wholeString = "My name is Malindu";

    if(wholeString->ToLower()->Contains("malindu")){
        std::cout<<"Found";
    }
    else{
        std::cout<<"Not Found";
    }
}

这个答案只适用于微软所有的C ++的扩展或者C ++ / CX或C ++ / CLI
H.铝阿姆里

1
是的,很抱歉,直到发布后的某天,我才知道它只能那样工作。
Malindu Dilanka '19

-1

这是一个简单的功能

bool find(string line, string sWord)
{
    bool flag = false;
    int index = 0, i, helper = 0;
    for (i = 0; i < line.size(); i++)
    {
        if (sWord.at(index) == line.at(i))
        {
            if (flag == false)
            {
                flag = true;
                helper = i;
            }
            index++;
        }
        else
        {
            flag = false;
            index = 0;
        }
        if (index == sWord.size())
        {
            break;
        }
    }
    if ((i+1-helper) == index)
    {
        return true;
    }
    return false;
}

4
您好,欢迎来到SO。您能否编辑您的答案并添加注释,说明其工作方式以及与其他答案的不同之处?谢谢!
法比奥说莫妮卡(Monica)

-1
#include <algorithm>        // std::search
#include <string>
using std::search; using std::count; using std::string;

int main() {
    string mystring = "The needle in the haystack";
    string str = "needle";
    string::const_iterator it;
    it = search(mystring.begin(), mystring.end(), 
                str.begin(), str.end()) != mystring.end();

    // if string is found... returns iterator to str's first element in mystring
    // if string is not found... returns iterator to mystring.end()

if (it != mystring.end())
    // string is found
else
    // not found

return 0;
}

11
请尝试避免仅将代码作为答案转储,并尝试解释其作用和原因。对于没有相关编码经验的人,您的代码可能并不明显。请编辑您的答案以包括说明,上下文,并尝试在答案中提及任何限制,假设或简化。
SᴀᴍOnᴇᴌᴀ

感谢您使代码清晰,using仅使用必需的功能而不将整个名称空间转储到全局空间中。至于@SᴀᴍOnᴇᴌᴀ注释,我想用户没有阅读您代码中的注释。
v010dya

-2

从这个网站上的很多答案中,我没有找到一个明确的答案,所以在5-10分钟内,我自己弄清楚了答案。但这可以在两种情况下完成:

  1. 您要么知道要在字符串中搜索的子字符串的位置
  2. 您可能不知道要搜索的位置,一个字符一个字符...

因此,假设我们在字符串“ abcde”中搜索子字符串“ cd”,并使用C ++中最简单的substr内置函数

1:

#include <iostream>
#include <string>

    using namespace std;
int i;

int main()
{
    string a = "abcde";
    string b = a.substr(2,2);    // 2 will be c. Why? because we start counting from 0 in a string, not from 1.

    cout << "substring of a is: " << b << endl;
    return 0;
}

2:

#include <iostream>
#include <string>

using namespace std;
int i;

int main()
{
    string a = "abcde";

    for (i=0;i<a.length(); i++)
    {
        if (a.substr(i,2) == "cd")
        {
        cout << "substring of a is: " << a.substr(i,2) << endl;    // i will iterate from 0 to 5 and will display the substring only when the condition is fullfilled 
        }
    }
    return 0;
}

2
8年前发布的最高答案(使用use std :: string :: find)用什么方式还不够清楚?
史蒂夫·史密斯,

-3

我们可以改用这种方法。只是我的项目中的一个例子。请参阅代码。还包括一些其他功能。

查看if语句!

/*
Every C++ program should have an entry point. Usually, this is the main function.
Every C++ Statement ends with a ';' (semi-colon)
But, pre-processor statements do not have ';'s at end.
Also, every console program can be ended using "cin.get();" statement, so that the console won't exit instantly.
*/

#include <string>
#include <bits/stdc++.h> //Can Use instead of iostream. Also should be included to use the transform function.

using namespace std;
int main(){ //The main function. This runs first in every program.

    string input;

    while(input!="exit"){
        cin>>input;
        transform(input.begin(),input.end(),input.begin(),::tolower); //Converts to lowercase.

        if(input.find("name") != std::string::npos){ //Gets a boolean value regarding the availability of the said text.
            cout<<"My Name is AI \n";
        }

        if(input.find("age") != std::string::npos){
            cout<<"My Age is 2 minutes \n";
        }
    }

}

抱歉,我没有看到有人发布过与以前相同的内容。
Malindu Dilanka '19

1
“在YouTube上订阅我”可以被视为垃圾邮件。请将来记住这一点。另外,请阅读如何应答如何不被垃圾邮件发送者
佐伊
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.