The find method is passed using either a character, a C string, or a C++ string, and you can provide an initial search position to start the search. The find method returns the position (rather than an iterator) to where the search text was located, or a value of npos if the text cannot be found. The offset parameter, and a successful return value from the find method, enables you to parse a string repeatedly to find specific items. The find method searches for the specified text in the forward direction, and there is also an rfind method that performs the search in the reverse direction.
Note that rfind is not the complete opposite of the find method. The find method moves the search point forward in the string and at each point compares the search string with the characters from the search point forwards (so the first search text character, then the second, and so on). The rfind method moves the search point backwards, but the comparisons are still made forwards. So, assuming the rfind method is not given an offset, the first comparison will be made at an offset from the end of the string the size of the search text. Then, the comparison is made by comparing the first character in the search text with the character at the search point in the searched string, and if this succeeds, the second character in the search text is compared with the character after the search point. So, the comparisons are made in a direction opposite to the direction of the movement of the search point.
This becomes important because if you want to parse a string using the return value from the find method as an offset, after each search you should move the search offset forwards, and for rfind you should move it backwards.
For example, to search for all the positions of the in the following string, you can call:
string str = "012the678the234the890";
string::size_type pos = 0;
while(true)
{
pos++;
pos = str.find("the",pos);
if (pos == string::npos) break;
cout << pos << " " << str.substr(pos) << "n";
}
// 3 the678the234the890
// 9 the234the890
// 15 the890
This will find the search text at the character positions of 3, 9, and 15. To search the string backwards, you could call:
string str = "012the678the234the890";
string::size_type pos = string::npos;
while(true)
{
pos--;
pos = str.rfind("the",pos);
if (pos == string::npos) break;
cout << pos << " " << str.substr(pos) << "n";
}
// 15 the890
// 9 the234the890
// 3 the678the234the890
The highlighted code shows the changes that should be made, showing you that you need to search from the end and use the rfind method. When you have a successful result you need to decrement the position before the next search. Like the find method, the rfind method returns npos if it cannot find the search text.
There are four methods that allow you to search for one of several individual characters. For example:
string str = "012the678the234the890";
string::size_type pos = str.find_first_of("eh");
if (pos != string::npos)
{
cout << "found " << str[pos] << " at position ";
cout << pos << " " << str.substr(pos) << "n";
}
// found h at position 4 he678the234the890
The search string is eh and the find_first_of will return when it finds either the character e or h in the string. In this example, the character h is found first at position 4. You can provide an offset parameter to start the search, so you can use the return value from find_first_of to parse through a string. The find_last_of method is similar, but it searches the string in the reverse direction for one of the characters in the search text.
There are also two search methods that will look for a character other than the characters provided in the search text: find_first_not_of and find_last_not_of. For example:
string str = "012the678the234the890";
string::size_type pos = str.find_first_not_of("0123456789");
cout << "found " << str[pos] << " at position ";
cout << pos << " " << str.substr(pos) << "n";
// found t at position 3 the678the234the890
This code looks for a character other than a digit and so it finds the t at position 3 (the fourth character).
There is no library function to trim whitespace from a string, but you can trim spaces on the left and right of strings by using the find functions to find non-whitespace and then use this as an appropriate index for the substr method.
string str = " hello ";
cout << "|" << str << "|n"; // | hello |
string str1 = str.substr(str.find_first_not_of(" trn"));
cout << "|" << str1 << "|n"; // |hello |
string str2 = str.substr(0, str.find_last_not_of(" trn") + 1);
cout << "|" << str2 << "|n"; // | hello|
In the preceding code, two new strings are created: one left-trims spaces, and the other right-trims spaces. The first forward searches for the first character that is not whitespace and uses this as the start index of the substring (no count is provided because all of the remaining string is copied). In the second case the string is reverse searched for a character that is not whitespace, but the location returned will be the last character of hello; since we need the substring from the first character, we increment this index to get the count of characters to copy.