Skip to main content

Section 9.11 find in strings

To search for a specific character in a string we could write a counting loop and look at each character until we find the one we want. But this kind of fundamental task is the kind of thing library functions are good for. string objects provide a find function that finds the first occurrence of a char or string within a string. If you look it up, you will find multiple declarations:
size_t find(const string& str, size_t pos = 0) const;
size_t find(char c, size_t pos = 0) const;
The first one takes a string as a parameter, and the second one takes a character. Both have an optional second parameter pos, which sets a start point for the search. (Recall that the = 0 is the default value, making that parameter optional. See Section 5.9.). Thus yString.find('e', 10) says “find the first ’e’ in myString at or after index 10” while myString.find('e') means “start from 0”. Both functions return the index where they find item being searched from. Because they are returning a location in a string, they return that value as a size_t and not as an int.
The example below demonstrates their use on the string She sells sea shells. For reference, here are the indices for the characters of that string:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
S h e s e l l s s e a s h e l l s
Listing 9.11.1.
Some things to note:
  • The first e is at index 2 (in “She”)
  • The first ell starts at index 5
  • The first se starts at index 4. That is the value stored into seIndex
  • myString.find("se", seIndex + 1) starts from index 5. Starting at that point, the next occurrence of "se" is at index 10.

Warning 9.11.1.

A common mistake is to write myString.find('e', 2) in an attempt to find the second e. That actually says “find the first e that is at or after index 2.” The only way to find() the second occurrence of something is to find it once, and then call find again starting at the index 1 past where the first copy was found. As done to find the second "se" in the sample above.
If you try to find() something that is not there, the find function needs to return a value to you that indicates “not found”. That value can’t be 0, as that is a valid location. So the value it returns is the largest possible size_t. This is find()’s way of saying “I searched until the end and did not find what I was looking for”. Rather than try to memorize the value (which can be different on different platforms!), there is a constant that defines this value: string::npos. (Think of string::npos as meaning “npos which is a part of string”. npos is short for “no position” or “null position”.)
Here is an example of trying to find q in our string:
Listing 9.11.2.
You can try changing the target to some character to see the behavior when the value is found.

Insight 9.11.2.

This is how you check if a string contains some other string: Do a find() and see if the value is != string::npos.

Note 9.11.3.

If you store attempt to store string::npos to an int, it will have the value -1. This is because string::npos is the binary value 111111...1. That value as a signed int is -1.
In many programming languages, a failed find() returns -1. And that is sort of true in C++. If you cast the returned value into an int it becomes -1. But it isn’t accurate to say that it returns -1. If you try to write something like if (s.find('x') == -1) the compiler will give a warning about comparing the signed (-1) and unsigned (string::npos) values.

Checkpoint 9.11.1.

Checkpoint 9.11.2.

Checkpoint 9.11.3.

Construct a block of code that correctly finds and prints where the third i is in the string.
You have attempted of activities on this page.