Thinking in C++ Vol 2 - Practical Programming |
Prev |
Home |
Next |
The find family of string member functions
locates a character or group of characters within a given string. Here are the
members of the find family and their general usage :
string find member function
|
What/how it finds
|
find( )
|
Searches a string for a specified character or group of
characters and returns the starting position of the first occurrence found or
npos if no match is found.
|
find_first_of( )
|
Searches a target string and returns the position of the
first match of any character in a specified group. If no match is
found, it returns npos.
|
find_last_of( )
|
Searches a target string and returns the position of the
last match of any character in a specified group. If no match is
found, it returns npos.
|
find_first_not_of( )
|
Searches a target string and returns the position of the
first element that doesn t match any character in a specified
group. If no such element is found, it returns npos.
|
find_last_not_of( )
|
Searches a target string and returns the position of the
element with the largest subscript that doesn t match any
character in a specified group. If no such element is found, it returns npos.
|
rfind( )
|
Searches a string from end to beginning for a specified
character or group of characters and returns the starting position of the
match if one is found. If no match is found, it returns npos.
|
The simplest use of find( )
searches for one or more characters in a string. This overloaded
version of find( ) takes a parameter that specifies the
character(s) for which to search and optionally a parameter that tells it where
in the string to begin searching for the occurrence of a substring. (The default
position at which to begin searching is 0.) By setting the call to find inside
a loop, you can easily move through a string, repeating a search to find all
the occurrences of a given character or group of characters within the string.
The following program uses the method of The Sieve of
Eratosthenes to find prime numbers less than 50. This method starts with
the number 2, marks all subsequent multiples of 2 as not prime, and repeats the
process for the next prime candidate. The SieveTest constructor
initializes sieveChars by setting the initial size of the character
array and writing the value P to each of its members.
//: C03:Sieve.h
#ifndef SIEVE_H
#define SIEVE_H
#include <cmath>
#include <cstddef>
#include <string>
#include "../TestSuite/Test.h"
using std::size_t;
using std::sqrt;
using std::string;
class SieveTest : public TestSuite::Test {
string sieveChars;
public:
// Create a 50 char string and set each
// element to 'P' for Prime:
SieveTest() : sieveChars(50, 'P') {}
void run() {
findPrimes();
testPrimes();
}
bool isPrime(int p) {
if(p == 0 || p == 1) return false;
int root = int(sqrt(double(p)));
for(int i = 2; i <= root; ++i)
if(p % i == 0) return false;
return true;
}
void findPrimes() {
// By definition neither 0 nor 1 is prime.
// Change these elements to "N" for Not
Prime:
sieveChars.replace(0, 2, "NN");
// Walk through the array:
size_t sieveSize = sieveChars.size();
int root = int(sqrt(double(sieveSize)));
for(int i = 2; i <= root; ++i)
// Find all the multiples:
for(size_t factor = 2; factor * i < sieveSize;
++factor)
sieveChars[factor * i] = 'N';
}
void testPrimes() {
size_t i = sieveChars.find('P');
while(i != string::npos) {
test_(isPrime(i++));
i = sieveChars.find('P', i);
}
i = sieveChars.find_first_not_of('P');
while(i != string::npos) {
test_(!isPrime(i++));
i = sieveChars.find_first_not_of('P', i);
}
}
};
#endif // SIEVE_H ///:~
//: C03:Sieve.cpp
//{L} ../TestSuite/Test
#include "Sieve.h"
int main() {
SieveTest t;
t.run();
return t.report();
} ///:~
The find( ) function can walk forward through a string,
detecting multiple occurrences of a character or a group of characters, and find_first_not_of( )
finds other characters or substrings.
There are no functions in the string class to change
the case of a string, but you can easily create these functions using the
Standard C library functions toupper( ) and tolower( ),
which change the case of one character at a time. The following example
illustrates a case-insensitive search:
//: C03:Find.h
#ifndef FIND_H
#define FIND_H
#include <cctype>
#include <cstddef>
#include <string>
#include "../TestSuite/Test.h"
using std::size_t;
using std::string;
using std::tolower;
using std::toupper;
// Make an uppercase copy of s
inline string upperCase(const string& s) {
string upper(s);
for(size_t i = 0; i < s.length(); ++i)
upper[i] = toupper(upper[i]);
return upper;
}
// Make a lowercase copy of s
inline string lowerCase(const string& s) {
string lower(s);
for(size_t i = 0; i < s.length(); ++i)
lower[i] = tolower(lower[i]);
return lower;
}
class FindTest : public TestSuite::Test {
string chooseOne;
public:
FindTest() : chooseOne("Eenie, Meenie, Miney,
Mo") {}
void testUpper() {
string upper = upperCase(chooseOne);
const string LOWER =
"abcdefghijklmnopqrstuvwxyz";
test_(upper.find_first_of(LOWER) == string::npos);
}
void testLower() {
string lower = lowerCase(chooseOne);
const string UPPER =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
test_(lower.find_first_of(UPPER) == string::npos);
}
void testSearch() {
// Case sensitive search
size_t i = chooseOne.find("een");
test_(i == 8);
// Search lowercase:
string test = lowerCase(chooseOne);
i = test.find("een");
test_(i == 0);
i = test.find("een", ++i);
test_(i == 8);
i = test.find("een", ++i);
test_(i == string::npos);
// Search uppercase:
test = upperCase(chooseOne);
i = test.find("EEN");
test_(i == 0);
i = test.find("EEN", ++i);
test_(i == 8);
i = test.find("EEN", ++i);
test_(i == string::npos);
}
void run() {
testUpper();
testLower();
testSearch();
}
};
#endif // FIND_H ///:~
//: C03:Find.cpp
//{L} ../TestSuite/Test
#include "Find.h"
#include "../TestSuite/Test.h"
int main() {
FindTest t;
t.run();
return t.report();
} ///:~
Both the upperCase( ) and lowerCase( )
functions follow the same form: they make a copy of the argument string
and change the case. The Find.cpp program isn t the best solution to the
case-sensitivity problem, so we ll revisit it when we examine string
comparisons.
Thinking in C++ Vol 2 - Practical Programming |
Prev |
Home |
Next |