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.