• No se han encontrado resultados

Haga que buscar_y_reemplazar_ign_mayus() devuelva el valor true si se hace el reempla zo y false si cad no contiene un caso de subcadant.

In document C++ SOLUCIONES DE PROGRAMACION (página 96-102)

Cree una búsqueda no sensible a mayúsculas y minúsculas y funciones de búsqueda y reemplazo para objetos string

5. Haga que buscar_y_reemplazar_ign_mayus() devuelva el valor true si se hace el reempla zo y false si cad no contiene un caso de subcadant.

Análisis

Antes de que use el algoritmo search() para realizar una búsqueda no sensible a mayúsculas y minúsculas, debe crear una función que compara dos valores char de una manera independiente de mayúsculas y minúsculas. Debe regresar true si los caracteres son iguales y false si no lo son. En el lenguaje de STL, a esta función se le denomina predicado binario. (Consulte el capítulo 3 para conocer un análisis de los predicados binarios.)

Esta función se utiliza con el algoritmo search() para comparar dos elementos. Al hacer que ignore las diferencias entre mayúsculas y minúsculas, la búsqueda se realizará independientemente de estas diferencias. He aquí una manera de codifi car esta función:

bool comp_ign_mayus(char x, char y) { return tolower(x) == tolower(y); }

Observe que se utiliza la función tolower() para obtener el equivalente en minúsculas de cada carácter. (Consulte Ignore diferencias entre mayúsculas y minúsculas cuando compare cadenas terminadas en un carácter nulo para conocer detalles sobre tolower().) Al convertir cada argumento a minúscu- las, se eliminan las diferencias entre mayúsculas y minúsculas.

Para encontrar una subcadena, llame al algoritmo search(). Aquí se muestra la versión utiliza- da en esta solución:

template <class ForIter1, class ForIter2, class BinPred> ForIter3 search(ForIter1 inicio1, ForIter1 fi nal1, ForIter2 inicio2, ForIter2 fi nal2, BinPred pfn)

Busca una aparición de la secuencia especifi cada por inicio2 y fi nal2 dentro del rango de la secuen- cia especifi cada por inicio1 y fi nal1. En este libro, los nombres de tipo genérico ForIter1 y ForIter2 indican iteradores que tienen capacidades de lectura/escritura y que puedan moverse hacia adelante. El predicado binario pfn determina cuando dos elementos son iguales. (En este libro, el nombre de tipo genérico BinPred indica un predicado binario.) Para los objetivos de la solución, pase comp_ign_mayus() a este parámetro. Si se encuentra una coincidencia, la función devuelve un iterador al principio de la secuencia coincidente. De otra manera, se devuelve fi nal1.

La función buscar_y_reemplazar_ign_mayus() usa el iterador devuelto por buscar_ign_mayus() para encontrar la ubicación en que se sustituye una subcadena con otra. Para manejar el reemplazo real, puede usar esta versión de la función replace() de string, que opera mediante iteradores:

string &replace(iterator inicio, iterator fi nal, const string &subcadnue)

Reemplaza el rango especifi cado por inicio y fi nal con subcadnue. Por tanto, se modifi ca la cadena que invoca. Devuelve una referencia a la cadena que invoca.

Ejemplo

He aquí una manera de crear la función buscar_ign_mayus(). Utiliza comp_ign_mayus() para determinar cuándo dos caracteres son iguales.

// Ignora la diferencia entre mayúsculas y minúsculas cuando busca. // una subcadena. La cadena en que se busca se pasa en cad. La // subcadena que se buscará se pasa en subcad. Devuelve un iterador // al principio de la coincidencia o cad.end() si no se encuentra una. //

// Obsérvese que se usa el algoritmo search() y especifica el // predicado binario comp_ign_mayus().

string::iterator buscar_ign_mayus(string &cad, const string &subcad) { return search(cad.begin(), cad.end(),

subcad.begin(), subcad.end(), comp_ign_mayus);

Como lo indican los comentarios, buscar_ign_mayus() encuentra (independientemente de las dife- rencias entre mayúsculas y minúsculas) la primera aparición de subcad y devuelve un iterador al principio de la secuencia coincidente. Devuelve cad.end() si no se encuentra una coincidencia.

He aquí una manera de implementar buscar_y_reemplazar_ign_mayus(). Observe que utiliza buscar_ign_mayus() para encontrar la subcadena que se reemplazará.

// Esta función reemplaza la primera aparición de subcadant con // subcadnue en la cadena pasada en cad. Devuelve true si ocurre // un reemplazo, y falso, si no.

//

// Observe que esta función modifica la cadena a la que cad hace

// referencia. Además, nótese que usa buscar_ign_mayus() para encontrar la // subcadena que se reemplazará.

bool buscar_y_reemplazar_ign_mayus(string &cad, const string &subcadant, const string &subcadnue) {

string::iterator itrinicio;

itrinicio = buscar_ign_mayus(cad, subcadant); if(itrinicio != cad.end()) {

cad.replace(itrinicio, itrinicio+subcadant.size(), subcadnue); return true;

}

return false; }

Esta función reemplaza la primera aparición de subcadant con subcadnue. Devuelve el valor true si ocurre un reemplazo (es decir, si cad contiene subcadant) y falso, si no. Como lo indican los comentarios, esta función modifi ca cad en el proceso. Utiliza buscar_ign_mayus() para encontrar la primera aparición de subcadant. Por tanto, la búsqueda se realiza independientemente de las diferencias entre mayúsculas y minúsculas.

En el siguiente ejemplo se muestran buscar_ign_mayus() y buscar_y_reemplazar_ign_ma- yus() en acción:

// Implementa búsquedas y búsquedas y reemplazo no sensibles // a mayúsculas y minúsculas para objetos de cadena.

#include <iostream> #include <string> #include <cctype> #include <algorithm> using namespace std;

bool comp_ign_mayus(char x, char y);

string::iterator buscar_ign_mayus(string &cad, const string &subcad); bool buscar_y_reemplazar_ign_mayus(string &cad, const string &subcadant, const string &subcadnue);

int main() {

string cadA("Es una prueba no sensible a may\u00a3sculas y min\u00a3sculas."); string cadB("prueba");

string cadC("PRUEBA"); string cadD("pruebas");

cout << "Primero, se demuestra buscar_ign_mayus().\n"; cout << "Cadena en que se busca:\n" << cadA << "\n\n"; cout << "Buscando " << cadB << ". ";

if(buscar_ign_mayus(cadA, cadB) != cadA.end()) cout << "Encontrada\n";

cout << "Buscando " << cadC << ". ";

if(buscar_ign_mayus(cadA, cadC) != cadA.end()) cout << "Encontrada\n";

cout << "Buscando " << cadD << ". ";

if(buscar_ign_mayus(cadA, cadD) != cadA.end()) cout << "Encontrada\n";

else

cout << "No encontrada\n";

// Usa el iterador devuelto por buscar_ign_mayus() para // desplegar el resto de la cadena.

cout << "\nEl resto de la cadena tras encontrar 'no':\n"; string::iterator itr = buscar_ign_mayus(cadA, "no"); while(itr != cadA.end())

cout << *itr++; cout << "\n\n";

// Ahora, demuestra la búsqueda y reemplazo. cadA = "Alfa Beta Gamma alfa beta gamma";

cout << "Ahora se demuestra buscar_y_reemplazar_ign_mayus().\n"; cout << "Cadena que recibe los reemplazos:\n" << cadA << "\n\n"; cout << "Reemplazando todos los casos de alfa con zeta:\n"; while(buscar_y_reemplazar_ign_mayus(cadA, "alfa", "zeta")) cout << cadA << endl;

return 0; }

// Ignora la diferencia entre mayúsculas y minúsculas cuando busca. // una subcadena. La cadena en que se busca se pasa en cad. La // subcadena que se buscará se pasa en subcad. Devuelve un iterador // al principio de la coincidencia o cad.end() si no se encuentra una. //

// Obsérvese que se usa el algoritmo search() y especifica el // predicado binario comp_ign_mayus().

string::iterator buscar_ign_mayus(string &cad, const string &subcad) { return search(cad.begin(), cad.end(),

subcad.begin(), subcad.end(), comp_ign_mayus);

}

// Ignora la diferencia entre mayúsculas y minúsculas cuando se compara // la igualdad entre dos caracteres. Devuelve true si los caracteres

// son iguales, independientemente de las diferencias entre mayúsculas // y minúsculas.

bool comp_ign_mayus(char x, char y) { return tolower(x) == tolower(y); }

// Esta función reemplaza la primera aparición de subcadant con // subcadnue en la cadena pasada en cad. Devuelve true si ocurre // un reemplazo, y falso, si no.

//

// Observe que esta función modifica la cadena a la que cad hace

// referencia. Además, nótese que usa buscar_ign_mayus() para encontrar la // subcadena que se reemplazará.

bool buscar_y_reemplazar_ign_mayus(string &cad, const string &subcadant, const string &subcadnue) {

string::iterator itrinicio;

itrinicio = buscar_ign_mayus(cad, subcadant); if(itrinicio != cad.end()) {

cad.replace(itrinicio, itrinicio+subcadant.size(), subcadnue); return true;

}

return false; }

Aquí se muestra la salida:

Primero, se demuestra buscar_ign_mayus(). Cadena en que se busca:

Es una prueba no sensible a mayúsculas y minúsculas. Buscando prueba. Encontrada.

Buscando PRUEBA. Encontrada. Buscando pruebas. No encontrada.

El resto de la cadena tras encontrar 'no': no sensible a mayúsculas y minúsculas.

Ahora se demuestra buscar_y_reemplazar_ign_mayus(). Cadena que recibe los reemplazos:

Alfa Beta Gamma alfa beta gamma

Reemplazando todos los casos de alfa con zeta: zeta Beta Gamma alfa beta gamma

zeta Beta Gamma zeta beta gamma

Opciones

Aunque el autor prefi ere implementar una búsqueda no sensible a mayúsculas y minúsculas mediante el uso del algoritmo STL search() como en esta solución, hay otro método. Puede im- plementar usted mismo esta función de búsqueda, trabajando carácter tras carácter y tratando de encontrar manualmente una subcadena coincidente. He aquí una manera de hacer esto:

// Implementa manualmente buscar_ign_mayus().

// Como la versión original, la cadena de búsqueda se pasa en cad // y la subcadena que se buscará se pasa en subcad. Devuelve // un iterador al inicio de la coincidencia o cad.end() // si no se encuentra una coincidencia.

string::iterator buscar_ign_mayus(string &cad, const string &subcad) { string::iterator inicio1, encontrada_en;

string::const_iterator inicio2;

// Si la cadena coincidente es nula, devuelve un iterador al // principio de cad.

if(subcad.begin() == subcad.end()) return cad.begin(); inicio1 = encontrada_en = cad.begin();

while(inicio1 != cad.end()) { inicio2 = subcad.begin();

while(tolower(*inicio1) == tolower(*inicio2)) { ++inicio1;

++inicio2;

if(inicio2 == subcad.end()) return encontrada_en; if(inicio1 == cad.end()) return cad.end();

} ++encontrada_en; inicio1 = encontrada_en; } return cad.end(); }

Como verá, el método manual incluye mucho más código. Es más, el desarrollo y la prueba de esta función toma más tiempo que el uso del algoritmo STL search(). Por último, no se hizo un intento de optimizar el código anterior. La optimización también toma una cantidad importante de tiempo. Por esto, casi siempre son preferibles los algoritmos STL a los métodos "caseros".

La función tolower() convierte caracteres con base en la confi guración regional de idioma. Para comparar caracteres para una confi guración diferente, puede usar la versión de tolower() que se declara dentro de <locale>.

Aunque no hay ventaja en hacerlo, también es posible convertir cada carácter en la cadena a mayúsculas (en lugar de minúsculas) para eliminar las diferencias entre mayúsculas y minúsculas. Esto se hace mediante la función toupper(), que se muestra aquí:

int toupper(int car)

In document C++ SOLUCIONES DE PROGRAMACION (página 96-102)

Outline

Documento similar