Skip to content
C++ Better Explained
Go back
C++ Check if String Contains Substring (find and contains)
Edit page

C++ Check if String Contains Substring

To check if a string contains a substring in C++, use find: text.find("word") != std::string::npos is true when the substring is present. In C++23 there’s also a cleaner contains() method. Let’s look at both, plus how to do a case-insensitive search.


The Standard Way: find

std::string::find searches for a substring and returns the index where it starts — or the special value std::string::npos if it isn’t there:

#include <iostream>
#include <string>

int main() {
    std::string text = "the quick brown fox";

    if (text.find("brown") != std::string::npos) {
        std::cout << "Found it!\n";
    } else {
        std::cout << "Not found.\n";
    }
    return 0;
}

The key is comparing against std::string::npos. Because find returns an index (and index 0 is a valid match at the very start), you must not test it as a simple true/false — always compare with npos.


Getting the Position

The return value of find is useful on its own when you want to know where the match is:

std::string text = "name=Alice";
size_t pos = text.find("=");
if (pos != std::string::npos) {
    std::string value = text.substr(pos + 1);  // "Alice"
    std::cout << value << "\n";
}

Here find locates the =, and substr grabs everything after it. This pairs naturally with splitting and parsing tasks.

If you're looking to go deeper with C++, the C++ Better Explained Ebook is perfect for you — whether you're a complete beginner or looking to solidify your understanding. Just $19.

The Modern Way: contains (C++23)

C++23 added a contains() method that returns a bool directly, so there’s no npos comparison to remember:

// Requires C++23: compile with g++ -std=c++23
std::string text = "the quick brown fox";
if (text.contains("brown")) {
    std::cout << "Found it!\n";
}

This is the most readable option when your compiler supports it. If you’re on an older toolchain, the find approach above does exactly the same job.


find is case-sensitive, so "Brown" won’t match "brown". For a case-insensitive check, convert both strings to lowercase first:

#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>

std::string toLower(std::string s) {
    std::transform(s.begin(), s.end(), s.begin(),
                   [](unsigned char c){ return std::tolower(c); });
    return s;
}

int main() {
    std::string text = "The Quick Brown Fox";
    bool found = toLower(text).find("brown") != std::string::npos;
    std::cout << (found ? "found\n" : "missing\n");  // found
    return 0;
}

We lowercase a copy of the text (and your search term, if needed) so the comparison ignores case. Wrapping std::tolower in a lambda with unsigned char avoids a subtle undefined-behavior trap with negative characters.


Quick Reference

GoalCode
Does it contain X?s.find("X") != std::string::npos
C++23 shortcuts.contains("X")
Where is X?size_t pos = s.find("X");
Ignore caselowercase both, then find


Take Your C++ Further

If you’re looking to go deeper with C++, the C++ Better Explained Ebook is perfect for you — whether you’re a complete beginner or looking to solidify your understanding. Just $19.

👉 Get the C++ Better Explained Ebook — $19

📋

Free Download: The 10 Mistakes Every C++ Beginner Makes

A free 1-page checklist that shows the exact traps that slow down every C++ beginner — so you can avoid them from day one.

🔒 No spam. Unsubscribe anytime.


Edit page
Share this post on:

Previous Post
C++ Split String: How to Split a String by Delimiter (3 Ways)
Next Post
C++ endl vs \n: What's the Difference and Which to Use