Как проверить, содержит ли строка подстроку в C++?
Правильное использование метода find()
Ваша проблема в том, что вы неправильно интерпретируете возвращаемое значение метода find(). Давайте разберёмся подробно.
Метод std::string::find() возвращает позицию (индекс) первого вхождения подстроки. Если подстрока не найдена, он возвращает специальное значение std::string::npos (обычно это максимально возможное значение для типа size_t, например 18446744073709551615).
Ваша ошибка в том, что вы используете if (text.find(substr)). В C++ любое ненулевое значение считается true, а ноль — false. Поскольку find() возвращает индекс, начиная с 0, то если подстрока находится в самом начале строки (индекс 0), условие if (0) даст false, и вы получите "Не найдено", хотя подстрока есть.
Правильный код
#include <iostream>
#include <string>
int main() {
std::string text = "Hello, world!";
std::string substr = "world";
// Правильный способ: сравниваем с npos
if (text.find(substr) != std::string::npos) {
std::cout << "Подстрока найдена!" << std::endl;
} else {
std::cout << "Подстрока не найдена" << std::endl;
}
return 0;
}
Дополнительные возможности find()
Метод find() имеет несколько перегрузок, которые могут быть полезны:
find(const std::string& str, size_t pos = 0)— поиск подстроки, начиная с позицииposfind(const char* s, size_t pos, size_t n)— поиск первыхnсимволов C-строкиfind(const char* s, size_t pos = 0)— поиск C-строкиfind(char c, size_t pos = 0)— поиск одиночного символа
Пример с указанием начальной позиции
#include <iostream>
#include <string>
int main() {
std::string text = "Hello, world! Hello again!";
std::string substr = "Hello";
size_t pos = text.find(substr); // первое вхождение на позиции 0
std::cout << "Первое вхождение: " << pos << std::endl;
pos = text.find(substr, pos + 1); // ищем следующее, начиная с pos+1
if (pos != std::string::npos) {
std::cout << "Второе вхождение: " << pos << std::endl;
}
return 0;
}
Другие методы для проверки
В C++ есть и другие способы проверить, содержит ли строка подстроку:
rfind()— ищет подстроку справа налево (последнее вхождение)find_first_of()— ищет любой символ из набораcontains()(C++23) — самый простой и интуитивный метод, возвращаетbool
Пример с C++23 (если ваш компилятор поддерживает)
#include <iostream>
#include <string>
int main() {
std::string text = "Hello, world!";
if (text.contains("world")) {
std::cout << "Содержит!" << std::endl;
}
return 0;
}
Заключение
Главное правило: всегда сравнивайте результат find() с std::string::npos. Не используйте find() в булевом контексте напрямую. Если вы используете современный C++ (C++23 и новее), метод contains() сделает код чище и понятнее.
Альтернативный подход: использование std::search из алгоритмов STL
Если вы предпочитаете работать с алгоритмами STL, можете использовать std::search из заголовочного файла <algorithm>. Этот подход более гибкий, так как работает с любыми последовательностями, а не только со строками.
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string text = "Hello, world!";
std::string substr = "world";
auto it = std::search(text.begin(), text.end(),
substr.begin(), substr.end());
if (it != text.end()) {
std::cout << "Найдено на позиции: "
<< std::distance(text.begin(), it) << std::endl;
} else {
std::cout << "Не найдено" << std::endl;
}
return 0;
}
Плюсы и минусы
- Плюсы: Работает с любыми контейнерами (vector, list, array), можно легко изменить логику сравнения (например, для регистронезависимого поиска)
- Минусы: Более громоздкий синтаксис, требует дополнительного заголовочного файла
Для простого поиска подстроки в строке обычно достаточно find(), но если вам нужно что-то нестандартное (например, поиск с кастомным предикатом), std::search будет отличным выбором.