Проверьте, содержит ли строка строку в C ++


494

У меня есть переменная типа std::string. Я хочу проверить, содержит ли он определенное std::string. Как бы я это сделал?

Есть ли функция, которая возвращает true, если строка найдена, и false, если это не так?


6
Вы имеете в виду char * string или строку из STL?
Anthares

1
Это не строка char *. Я должен был #include <string>, чтобы использовать его.
нейромант

1
Некоторые решения используют s2 для строки, которую я хочу найти. Будет ли это работать, если я использую что-то вроде «это строка» вместо s2?
нейромант

2
Да, потому что есть строковый конструктор literl для типа std :: string.

18
Кто-то, пожалуйста, сделайте предложение, чтобы добавить std::basic_string::containsв stdlib.
Emlai

Ответы:


723

Используйте std::string::findследующим образом:

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

Примечание: "найдено!" будет напечатан, если s2является подстрокой s1, оба s1и 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;
}

33
Msgstr "Я думаю, что std :: string не предоставляет достаточный метод для выполнения всей обычной строковой операции". Но есть findметод для решения именно этой задачи. Не нужно вводить библиотечную зависимость.
Стефан

8
@stefan, вы правы, есть метод find, но как насчет split, replace и многих других сотрудников? Вы можете сравнить std :: string со строкой api в Java. PS: Я тоже думаю, что содержит намного более элегантно, чем найти, чтобы проверить, содержит ли строка другую строку.
Geng Jiawen

1
Также это коротко, и более легко для памяти. Cpp 17 имеет добавленную поддержку файловой системы. Я надеюсь, что Cpp 2x тоже сделает что-то для строки. Очень больно отсутствие поддержки базового строкового метода в современном cpp.
Гэн

1
Вы действительно нуждаетесь в "использовании"? Когда я читаю этот код, я понятия не имею, containsесть ли 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

Да, это хороший момент. Не думал, что когда я написал это. Я думаю, что я подумал, когда писал это, может быть, как просто избежать использования std :: find.
Testing123

3
Только для будущих посетителей: этот алгоритм на самом деле не правильный. Поскольку «i» никогда не возвращается после неудачного совпадения подстроки, некоторые случаи не совпадают, например, рассмотрим: aaabc, aab
sAm_vdP

1
Это имеет несколько ошибок. CheckSubstring(std::string firstString, std::string secondString)глубокие копии обеих строк передаются в функцию, что дорого, особенно для более длинных строк, требующих выделения кучи. Кроме того, говорят , что вы звоните CheckSubstring("XYZab", "ab\0\0")- whileцикл будет в конечном итоге по сравнению aс a, bчтобы bнеявный NUL в конце первой строки в явном NUL в секунду, то он будет читать дальше буфер первой строки, имея неопределенное поведение. Для исправления используйте for (... i <= firstString.size () - secondString (). Size (); ...) `.
Тони Делрой

1

Если размер строк относительно большой (сотни байт или более) и доступен c ++ 17, вы можете использовать поисковик Бойера-Мура-Хорспула (пример с 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

Вы также можете использовать пространство имен System. Тогда вы можете использовать метод содержит.

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

Этот ответ относится только к проприетарному расширению Microsoft C ++ - C ++ / CX или C ++ / CLI
Х. Аль-Амри,

1
да, я извиняюсь, я не знал, что это работает только до тех пор, пока я не опубликую это.
Малинду Диланка

-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
Здравствуйте, добро пожаловать в ТАК. Не могли бы вы отредактировать свой ответ и добавить комментарий о том, как он работает и чем он отличается от других ответов? Спасибо!
Фабио говорит восстановить Монику

-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ᴇᴌᴀ, я думаю, что пользователь не читал комментарии в вашем коде.
v010дя

-2

Из такого большого количества ответов на этом сайте я не нашел четкого ответа, поэтому через 5-10 минут я сам нашел ответ. Но это можно сделать в двух случаях:

  1. Либо вы ЗНАЕТЕ положение подстроки, которую вы ищете в строке
  2. Либо вы не знаете положение и искать его, символ за символом ...

Итак, давайте предположим, что мы ищем подстроку "cd" в строке "abcde", и мы используем простейшую встроенную функцию substr в C ++

за 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
Каким образом верхний ответ («use std :: string :: find»), опубликованный 8 годами ранее, был недостаточно ясным?
Стив Смит

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

}

Извините, я не видел, чтобы кто-то опубликовал то же самое, что я делал ранее.
Малинду Диланка

1
«Подписывайся на меня на YouTube» можно считать спамом. Пожалуйста, имейте это в виду в будущем. Кроме того, прочитайте, как ответить и как не быть спамером
Zoe
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.