Avatar ·

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

Всем привет! Я только начал изучать C++ и столкнулся с проблемой: как проверить, содержит ли одна строка другую строку? В других языках, например в Python, это делается просто через оператор `in` или метод `.find()`. А в C++ я что-то запутался. У меня есть переменная `std::string text = "Hello, world!";` и мне нужно проверить, есть ли в ней подстрока `"world"`. Я попробовал написать такой код: ```cpp #include #include int main() { std::string text = "Hello, world!"; std::string substr = "world"; if (text.find(substr)) { std::cout << "Найдено!" << std::endl; } else { std::cout << "Не найдено" << std::endl; } return 0; } ``` Но этот код работает неправильно: когда подстрока есть, он иногда выводит "Не найдено", а когда подстроки нет – может вывести "Найдено". Я читал, что `find()` возвращает какой-то индекс, но не понял, как его правильно использовать. Пожалуйста, объясните, как правильно проверить наличие подстроки в C++? Может быть, есть другие методы, кроме `find()`? И как вообще работать с поиском в строках в этом языке? Заранее спасибо за помощь! <<>>

Правильное использование метода 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) — поиск подстроки, начиная с позиции pos
  • find(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 будет отличным выбором.