Start learning free

LESSON 60 OF 343 · STRINGS I

String Find in C++: find, rfind and string::npos

Lesson Read the full explanation

In C++, you can find the index of a substring using std::string::find():

s.find(sub)          // returns index of first occurrence, or string::npos if not found
s.rfind(sub)         // returns index of last occurrence
s.find(sub, start)   // search starting from index `start`

Here are some examples:

string sentence = "Hello World";
int idx = sentence.find("World");
cout << idx;  // 6

if (sentence.find("xyz") == string::npos) {
    cout << "not found";
}

The index returned is the position of the first character of the found substring. Returns string::npos (a large number) if not found.


Assignment
Follow the Coding Tutorial and find the index of "World" in sentence!


Hint
Use sentence.find("World") and assign the result to idx.

STEP 1 OF 1
    Ctrl + Enter to check

    C++ · STRINGS I

    String Find in C++, explained

    What find does

    Finding out whether a piece of text appears inside a string, and where, is one of the most common string tasks. In C++ the tool is the member function find of std::string. It scans the string from the left and returns the index of the first character of the first match. Indexes start at 0, like everything else in C++.

    string sentence = "Hello World";
    cout << sentence.find("World");   // 6
    cout << sentence.find("o");       // 4
    

    "World" begins at index 6 because H e l l o and the space take up indexes 0 to 5. The second call finds the first o, the one in "Hello", not the one in "World".

    You can search for a string literal, another string variable, or a single character.

    When there is no match

    If the text is absent, find cannot return a valid index, so it returns a special constant, string::npos. It is the largest value the index type can hold. The index type is size_t, an unsigned integer, so npos is a huge positive number rather than -1. Always compare against the constant by name:

    if (sentence.find("xyz") == string::npos) {
        cout << "not found";
    }
    

    This is the check to write every time the text might be missing. Never test find(...) > 0 or find(...) != -1 to mean "found". The first is wrong when the match is at index 0, and the second depends on a conversion between signed and unsigned numbers.

    rfind and the start position

    Two variations cover most of the remaining needs:

    • s.rfind(sub) searches from the right and returns the index of the last occurrence.
    • s.find(sub, start) begins the search at index start instead of 0, which lets you find the second occurrence, the third, and so on.

    With t = "one two one", t.find("one") is 0, t.rfind("one") is 8, and t.find("one", 1) is also 8, because the search skips the match at index 0.

    To visit every occurrence, repeat find with a start position just after the previous match, and stop when the result is string::npos.

    The type of the result

    The return type is size_t (spelled string::size_type in full), not int. For short strings it makes no practical difference, and the lesson stores the result in an int. When the text is missing, converting npos to an int gives -1 on common compilers, which is why that code appears to work. For code you want to keep correct, store the result in a size_t (or auto) and compare it with string::npos before doing anything else with it.

    The same rule explains why using the result without checking is dangerous. An index of string::npos passed to another string function, such as replace or substr, makes it throw std::out_of_range.

    The exercise, step by step

    The editor starts with string sentence = "Hello World";. The task is to find where "World" begins.

    1. Call find on sentence with the text to look for, "World". The call is written with a dot, because find belongs to the string.
    2. Store the result in a new int variable named idx, declared below the existing line.
    string sentence = "Hello World";
    
    int idx = sentence.find("World");
    

    The value of idx is 6. The text is present in this exercise, so no npos check is needed here, but in a real program you would add one.

    Common mistakes

    • Forgetting that the result is an index, not a count or a boolean. A match at the very start returns 0, which is a valid result.
    • Using the result without a npos check. The result then feeds a huge number into whatever comes next.
    • Mixing up case. find is case sensitive, so sentence.find("world") does not match "World". Lowercase both strings first if you want a case-insensitive search.
    • Expecting every occurrence. find returns only one index. Loop with the start position to get the rest.

    Key takeaways

    • s.find(sub) returns the index of the first match, s.rfind(sub) the last, and s.find(sub, start) searches from start.
    • A missing match gives string::npos. Compare with it by name.
    • Check for npos before you use the index.
    Keep going with C++About 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free