Проверка содержимого строки в строке на C++
У меня есть переменная типа std::string
. Я хочу проверить, содержит ли она определенную подстроку типа std::string
. Как я могу это сделать?
Существует ли функция, которая возвращает true
, если подстрока найдена, и false
, если нет?
5 ответ(ов)
Вы можете попробовать следующий код:
#include <iostream>
#include <cstring>
using namespace std;
int main() {
string s1 = "Hello";
string s2 = "el";
if (strstr(s1.c_str(), s2.c_str())) {
cout << "S1 содержит S2";
}
return 0;
}
Этот код проверяет, содержит ли строка s1
подстроку s2
с помощью функции strstr()
. Если подстрока найдена, выводится сообщение "S1 содержит S2".
В случае, если данная функциональность критична для вашей системы, использование старого метода 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 << "Генерация " << haystacksCount << " случайных строк размером " << sizes[s] << std::endl;
for(size_t i=0; i<haystacksCount; ++i)
{
haystacks[i] = randomString(sizes[s]);
}
std::cout << "Запуск метода std::string.find" << 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; // бесполезное действие
}
}
end = high_resolution_clock::now();
timespan = duration_cast<duration<double>>(end-start);
std::cout << "Обработка " << haystacksCount << " элементов заняла " << timespan.count() << " секунд." << std::endl;
std::cout << "Запуск метода strstr" << 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; // бесполезное действие
}
}
end = high_resolution_clock::now();
timespan = duration_cast<duration<double>>(end-start);
std::cout << "Обработка " << haystacksCount << " элементов заняла " << timespan.count() << " секунд." << std::endl;
std::cout << "Запуск метода std::search" << 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; // бесполезное действие
}
}
end = high_resolution_clock::now();
timespan = duration_cast<duration<double>>(end-start);
std::cout << "Обработка " << haystacksCount << " элементов заняла " << timespan.count() << " секунд." << 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 в конце. Большая часть времени программа тратит на генерацию случайных строк, но это вполне ожидаемо.
Вот результаты выполнения программы:
Генерация 200000 случайных строк размером 10
Запуск метода std::string.find
Обработка 200000 элементов заняла 0.00358503 секунд.
Запуск метода strstr
Обработка 200000 элементов заняла 0.0022727 секунд.
Запуск метода std::search
Обработка 200000 элементов заняла 0.0346258 секунд.
Генерация 200000 случайных строк размером 20
Запуск метода std::string.find
Обработка 200000 элементов заняла 0.00480959 секунд.
Запуск метода strstr
Обработка 200000 элементов заняла 0.00236199 секунд.
Запуск метода std::search
Обработка 200000 элементов заняла 0.0586416 секунд.
Генерация 200000 случайных строк размером 40
Запуск метода std::string.find
Обработка 200000 элементов заняла 0.0082571 секунд.
Запуск метода strstr
Обработка 200000 элементов заняла 0.00341435 секунд.
Запуск метода std::search
Обработка 200000 элементов заняла 0.0952996 секунд.
Генерация 200000 случайных строк размером 80
Запуск метода std::string.find
Обработка 200000 элементов заняла 0.0148288 секунд.
Запуск метода strstr
Обработка 200000 элементов заняла 0.00399263 секунд.
Запуск метода std::search
Обработка 200000 элементов заняла 0.175945 секунд.
Генерация 200000 случайных строк размером 160
Запуск метода std::string.find
Обработка 200000 элементов заняла 0.0293496 секунд.
Запуск метода strstr
Обработка 200000 элементов заняла 0.00504251 секунд.
Запуск метода std::search
Обработка 200000 элементов заняла 0.343452 секунд.
Генерация 200000 случайных строк размером 320
Запуск метода std::string.find
Обработка 200000 элементов заняла 0.0522893 секунд.
Запуск метода strstr
Обработка 200000 элементов заняла 0.00850485 секунд.
Запуск метода std::search
Обработка 200000 элементов заняла 0.64133 секунд.
Генерация 200000 случайных строк размером 640
Запуск метода std::string.find
Обработка 200000 элементов заняла 0.102082 секунд.
Запуск метода strstr
Обработка 200000 элементов заняла 0.00925799 секунд.
Запуск метода std::search
Обработка 200000 элементов заняла 1.26321 секунд.
Генерация 200000 случайных строк размером 1280
Запуск метода std::string.find
Обработка 200000 элементов заняла 0.208057 секунд.
Запуск метода strstr
Обработка 200000 элементов заняла 0.0105039 секунд.
Запуск метода std::search
Обработка 200000 элементов заняла 2.57404 секунд.
Генерация 200000 случайных строк размером 5120
Запуск метода std::string.find
Обработка 200000 элементов заняла 0.798496 секунд.
Запуск метода strstr
Обработка 200000 элементов заняла 0.0137969 секунд.
Запуск метода std::search
Обработка 200000 элементов заняла 10.3573 секунд.
Генерация 200000 случайных строк размером 10240
Запуск метода std::string.find
Обработка 200000 элементов заняла 1.58171 секунд.
Запуск метода strstr
Обработка 200000 элементов заняла 0.0143111 секунд.
Запуск метода std::search
Обработка 200000 элементов заняла 20.4163 секунд.
Как видно из результатов, strstr
действительно показывает наилучшие времена выполнения, особенно на больших объемах данных. Это важно учитывать при проектировании систем, где производительность имеет значение.
Если размер строк достаточно велик (сотни байт и более) и у вас есть доступ к 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 << "Строка " << needle << " найдена на смещении "
<< it - in.begin() << '\n';
else
std::cout << "Строка " << needle << " не найдена\n";
}
Этот алгоритм эффективно выполняет поиск подстроки в большой строке, благодаря чему вы можете значительно сократить время выполнения поиска по сравнению с простыми методами.
В данном коде на C++ мы инициализируем строку response
с текстом "hello world"
и строку findMe
с текстом "world"
. Используя метод find
, мы проверяем, содержится ли строка findMe
в строке response
.
Если find
находит подстроку, он возвращает позицию первого вхождения, и условие response.find(findMe) != string::npos
будет истинным. Здесь string::npos
— это специальное значение, которое указывает на то, что подстрока не была найдена.
Таким образом, если подстрока найдена, можно выполнить соответствующие действия в блоке if
, где отмечено //found
. Это подойдёт, например, для выполнения каких-либо операций, зависящих от наличия указанного текста в строке.
Если вы не хотите использовать функции стандартной библиотеки, вот одно из решений:
#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(firstString[i] == secondString[j]){
int k = i;
while (firstString[i] == secondString[j] && j < secondString.size()){
j++;
i++;
}
if (j == secondString.size())
return true;
else // Сбрасываем i на его исходное значение
i = k;
}
}
return false;
}
int main(){
std::string firstString, secondString;
std::cout << "Введите первую строку:";
std::getline(std::cin, firstString);
std::cout << "Введите вторую строку:";
std::getline(std::cin, secondString);
if(CheckSubstring(firstString, secondString))
std::cout << "Вторая строка является подстрокой первой строки.\n";
else
std::cout << "Вторая строка не является подстрокой первой строки.\n";
return 0;
}
В этом коде реализована функция CheckSubstring
, которая проверяет, является ли одна строка подстрокой другой без использования стандартных функций. Сначала мы проверяем, не длиннее ли вторая строка первой. Затем мы перебираем символы первой строки и сравниваем их с символами второй строки. Если все символы совпадают, мы возвращаем true
, иначе продолжаем проверку. В main
мы считываем строки и выводим результат проверки.
Есть ли в Python метод подстроки 'contains' для строк?
Как проверить, содержит ли строка конкретное слово?
Как перебрать слова в строке?
Как проверить, содержит ли строка подстроку?
`std::wstring` против `std::string`: когда использовать и в чем разница?