La familia de funciones miembro de string
find localiza un carácter o grupo de
caracteres en una cadena dada. Aquí los miembros de la familia
find() y su uso general:
Función miembro de búsqueda en un string
¿Qué/Cómo lo encuentra?
find()
Busca en un string un carácter
determinado o un grupo de caracteres y retorna la posición de
inicio de la primera ocurrencia o npos si ha
sido encontrado.
find_first_of()
Busca en un string y retorna la posición
de la primera ocurrencia de cualquier carácter en un grupo
especifico. Si no encuentra ocurrencias, retorna
npos.
find_last_of()
Busca en un string y retorna la posición
de la última ocurrencia de cualquier carácter en un grupo
específico. Si no encuentra ocurrencias, retorna
npos.
find_first_not_of( )
Busca en un string y retorna la posición
de la primera ocurrencia que no pertenece a un grupo
específico. Si no encontramos ningún elemento, retorna un
npos
find_last_not_of( )
Busca en un string y retorna la posición
del elemento con el indice mayor que no pertenece a un grupo
específico. Si no encontramos ningún elemento, retorna un
npos
rfind()
Busca en un string, desde el final hasta
el origen, un carácter o grupo de caracteres y retorna la
posición inicial de la ocurrencia si se ha encontrado alguna. Si
no encuentra ocurrencias, retorna npos.
El uso más simple de find(), busca uno o
más caracteres en un string. La versión
sobrecargada de find() toma un parámetro
que especifica el/los carácter(es) que buscar y opcionalmente un
parámetro que dice donde empezar a buscar en el
string la primera ocurrencia. (Por
defecto la posición de incio es 0). Insertando la llamada a la
función find() dentro de un bucle puede
buscar fácilmente todas las ocurrencias de un carácter dado o un
grupo de caracteres dentro de un string.
El siguiente programa usa el método del Tamiz de Eratostenes para hallar los números primos menores de 50. Este método empieza con el número 2, marca todos los subsecuentes múltiplos de 2 ya que no son primos, y repite el proceso para el siguiente candidato a primo. El constructor de sieveTest inicializa sieveChars poniendo el tamaño inicial del arreglo de carácter y escribiendo el valor 'P' para cada miembro.
//: 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 ///:~
Listado 4.11. C03/Sieve.h
//: C03:Sieve.cpp //{L} ../TestSuite/Test #include "Sieve.h" int main() { SieveTest t; t.run(); return t.report(); } ///:~
Listado 4.12. C03/Sieve.cpp
La función find() puede recorrer el
string, detectando múltiples ocurrencias
de un carácter o un grupo de caracteres, y
find_first_not_of() encuentra otros
caracteres o subcadenas.
No existen funciones en la clase string
para cambiar entre mayúsculas/minúsculas en una cadena, pero
puede crear esa función fácilmente usando la función de la
libreria estándar de C toupper() y
tolower(), que cambian los caracteres entre
mayúsculas/minúsculas de uno en uno. El ejemplo siguiente
ilustra una búsqueda sensible a mayúsculas/minúsculas.
//: 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 ///:~
Listado 4.13. C03/Find.h
//: C03:Find.cpp //{L} ../TestSuite/Test #include "Find.h" #include "../TestSuite/Test.h" int main() { FindTest t; t.run(); return t.report(); } ///:~
Listado 4.14. C03/Find.cpp
Tanto las funciones upperCase() como
lowerCase() siguen la misma forma: hacen
una copia de la cadena argumento y cambian entre
mayúsculas/minúsculas. El programa Find.cpp no es la mejor
solución para el problema para las mayúsculas/minúsculas, por lo
que lo revisitaremos cuando examinemos la comparación entre
cadenas.
Si necesita buscar en una cadena desde el final hasta el
principio (para encontrar datos en orden "último
entra / primero sale"), puede usar la función
miembro de string
rfind().
//: C03:Rparse.h #ifndef RPARSE_H #define RPARSE_H #include <cstddef> #include <string> #include <vector> #include "../TestSuite/Test.h" using std::size_t; using std::string; using std::vector; class RparseTest : public TestSuite::Test { // To store the words: vector<string> strings; public: void parseForData() { // The ';' characters will be delimiters string s("now.;sense;make;to;going;is;This"); // The last element of the string: int last = s.size(); // The beginning of the current word: size_t current = s.rfind(';'); // Walk backward through the string: while(current != string::npos) { // Push each word into the vector. // Current is incremented before copying // to avoid copying the delimiter: ++current; strings.push_back(s.substr(current, last - current)); // Back over the delimiter we just found, // and set last to the end of the next word: current -= 2; last = current + 1; // Find the next delimiter: current = s.rfind(';', current); } // Pick up the first word -- it's not // preceded by a delimiter: strings.push_back(s.substr(0, last)); } void testData() { // Test them in the new order: test_(strings[0] == "This"); test_(strings[1] == "is"); test_(strings[2] == "going"); test_(strings[3] == "to"); test_(strings[4] == "make"); test_(strings[5] == "sense"); test_(strings[6] == "now."); string sentence; for(size_t i = 0; i < strings.size() - 1; i++) sentence += strings[i] += " "; // Manually put last word in to avoid an extra space: sentence += strings[strings.size() - 1]; test_(sentence == "This is going to make sense now."); } void run() { parseForData(); testData(); } }; #endif // RPARSE_H ///:~
Listado 4.15. C03/Rparse.h
//: C03:Rparse.cpp //{L} ../TestSuite/Test #include "Rparse.h" int main() { RparseTest t; t.run(); return t.report(); } ///:~
Listado 4.16. C03/Rparse.cpp
La función miembro de string
rfind() vuelve por la cadena buscando
elementos y reporta el indice del arreglo de las coincidencias
de caracteres o
string::npos si no
tiene éxito.