Перевірте, чи містить рядок рядок у C ++


493

У мене є змінна тип std::string. Я хочу перевірити, чи містить він певне std::string. Як би я це зробив?

Чи є функція, яка повертає true, якщо рядок знайдена, і false, якщо її немає?


6
Ви маєте на увазі рядок char * або рядок із STL?
антреси

1
Це не рядок char *. Мені довелося #include <string> використовувати його.
невроман

1
У деяких рішеннях використовується s2 для рядка, який я хочу знайти. Чи все одно це буде працювати, якщо я використовую щось на кшталт "це рядок" замість s2?
невроман

2
Так, тому що існує строковий literl конструктор для типу std :: string.

18
Хтось, будь ласка, зробить пропозицію додати std::basic_string::containsдо stdlib.
emlai

Відповіді:


722

Використовуйте std::string::findнаступним чином:

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

Примітка: "знайдено!" буде надруковано, якщо s2є підрядком s1обох s1і s2мають тип std::string.



27

Насправді, ви можете спробувати використовувати boost-бібліотеку, я думаю, що std :: string не забезпечує достатньо методу для виконання всіх загальних рядкових операцій. Підсилюючи, ви можете просто використовувати 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
"Я думаю, що std :: string не забезпечує достатньо методу для виконання всіх загальних рядкових операцій". Але є findметод для саме заданого питання. Не потрібно вводити залежність від бібліотеки.
Стефан

8
@stefan, ви маєте рацію, є спосіб пошуку, але як бути з розділенням, заміною та багатьма іншими співробітниками. Ви можете порівняти std :: string з рядком api в Java.PS:Также я думаю, що він містить набагато елегантніше, ніж знайти, щоб перевірити, чи містить рядок інший рядок.
Ген Джіавен

1
Крім того, це короткий і простіший запам'ятовування. Cpp 17 має підтримку файлової системи. Я сподіваюся, що Cpp 2x теж зробить щось для рядка. Дуже болісно відсутність підтримки базових рядкових методів у сучасному cpp.
Ген

1
Вам справді потрібні "вставки"? Коли я прочитав цей код, я поняття не маю containsце std::containsабо boost::contains, що здається істотним недоліком. Я думаю, що std :: містить наразі не існує, але я не впевнений, що розумно припустити, що читач запам'ятав усе, що є у 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.
Тестування123

3
Просто для майбутніх відвідувачів: Цей алгоритм насправді не правильний. Оскільки "я" ніколи не повертається після невдалого збігу підрядків, деякі випадки не узгоджуються, наприклад, враховуйте: 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, ви можете скористатися пошуком 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

Ви також можете скористатися простором імен системи. Потім ви можете використовувати метод містить.

#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 ++ Microsoft або C ++ / CX, або C ++ / CLI
H. Al-Amri

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
Привіт, ласкаво просимо до SO. Чи можете ви відредагувати свою відповідь та додати коментар про те, як вона працює та чим вона відрізняється від інших відповідей? Дякую!
Фабіо каже, що поверніть Моніку

-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
Яким чином головна відповідь ("використовувати 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.