Universidad de Costa Rica
Escuela de Ciencias de la Computación e Informática
CI-1201 Programación II - 2014b
Profesor Jeisson Hidalgo-Céspedes

Tarea 04: Clase String

Complete la clase ecci::String para que pueda ser reutilizada, la cual se encuentra dentro del archivo ecci.zip. Si utiliza Microsoft Windows requierirá descargar catch.hpp y colocarlo en la misma carpeta donde extrajo ecci.zip. Debe proveer la funcionalidad mínima para que los casos de prueba en Test.cpp puedan correr sin errores. Todo método debe estar documentado en Doxygen (resumen, parámetros, valor de retorno, etc., al menos en forma muy básica). En concreto implemente:

  1. [5%] Implemente un método isEmpty() que retorna true si el String es vacío. Sobrecargue el operador ! que retorna true si el String es vacío. Por ejemplo, si s1 es un ecci::String vacío, la expresión if ( !s1 ) se evaluará como verdadera.

  2. [5%] Sobrecargue el operador de asignación, de tal forma que se pueda asignar a un String una cadena de caracteres terminada en nulo. Por ejemplo, si s1 es un ecci::String, la expresión s1 = "hola" cambia el valor de s1 a "hola". El objeto s1 debe resultar con la cantidad de memoria justa. En este ejemplo, debe ocupar 5 bytes para almacenar la cadena "hola" más el carácter de fin de cadena.

  3. [10%] Sobrecargue el operador == que permita comparar si el valor del objeto ecci::String es equivalente a un carácter, una cadena terminada en nulo u otro objeto ecci::String. Debe retornar un valor booleano. La comparación se hace considerando minúsculas como diferentes de las mayúsculas. Trate de hacer la implementación tan eficiente como sea posible, es decir, a lo sumo un recorrido por cada cadena involucrada. El operador debe ser commutativo, es decir, implemente:

  4. [10%] Sobrecargue el operador < que permita comparar si el valor del objeto ecci::String se ordena alfabéticamente antes de un carácter, una cadena terminada en nulo u otro objeto ecci::String. Debe retornar un valor booleano. La comparación se hace considerando minúsculas como diferentes de las mayúsculas. Trate de hacer la implementación tan eficiente como sea posible, es decir, a lo sumo un recorrido por cada cadena involucrada. El operador debe ser commutativo, es decir, implemente:

  5. [20%] Sobrecargue el operador + para que pueda hacer concatenación commutativa de objetos ecci::String con los siguientes tipos de datos: char, long long, unsigned long long, double, const char* y String. Para los números reales (double) utilice una precisión de 6 decimales, que es el por defecto de sprintf(str,"%lf",d). El código de varios de estos métodos es muy similar, trate de factorizarlo en nuevos métodos:

  6. [10%] Implemente el método substr(pos, len) que retorna la subcadena que se encuentra a partir de pos y tiene una longitud de len caracteres. Por ejemplo, si s1 es un ecci::String con el valor "Hola mundo ECCI", la invocación s1.substr(6, 4) retornaría el objeto ecci::String "undo". Si len se omite o se provee un valor fuera de rango, se retorna la subcadena comprendida entre pos y el final de la cadena. Por ejemplo, la invocación s1.substr(8) retornaría un ecci::String con el valor "do ECCI". Idee y documente qué retorna el método si pos está fuera de rango.

  7. [5%] Sobrecargue el operador () para que realice el mismo trabajo que substr(pos, len), con la diferencia de que ambos parámetros son obligatorios. Por ejemplo, si s1 es un ecci::String con el valor "Hola mundo ECCI", la invocación s1(6, 4) retornaría el objeto ecci::String "undo". Documente qué ocurre si el parámetro pos, len o ambos están fuera de rango.

  8. [5%] Implemente el método find(ch, pos) que busca el carácter ch en el objeto String a partir de la posición pos. Si pos se omite, se asume 0. Si encuentra el carácter, retorna la posición donde se encuentra. Por ejemplo, sea ecci::String s1("crecer");, la invocación s1.find('e') retorna 2, y s1.find('e', 3) retorna 4. Si el carácter ch no se encuentra, retorne la posición no válida -1. El método considera minúsculas y mayúculas como distintas. Decida y documente qué hace su método si recibe una posición fuera de rango. Sugerencia: indague sobre la función std::strchr().

  9. [5%] Implemente el método find(cstr, pos) que busca la cadena terminada en nulo cstr en el objeto String a partir de la posición pos. Si pos se omite, se asume 0. Si encuentra la cadena, retorna la posición donde se encuentra. Por ejemplo, sea ecci::String s1("crecer");, la invocación s1.find("rece") retorna 1, y s1.find("rece", 2) retorna la posición no válida -1 indicando que no se encuentra. El método considera minúsculas y mayúculas como distintas. Decida y documente qué hace su método si recibe una posición fuera de rango. Sugerencia: indague sobre la función std::strstr().

  10. [5%] Implemente el método findNoCase(ch, pos) que realiza la misma labor que find(ch, pos), con la diferencia de que considera la mayúscula y minúscula de cada letra como la misma. Por ejemplo, sea ecci::String s1("crecer");, la invocación s1.find('E') retorna -1, mientras que s1.findNoCase('E') retorna 2. Indague sobre las funciones libres std::tolower(ch) y std::toupper(ch).

  11. [10%] Implemente el método findNoCase(cstr, pos) que recibe una cadena terminada en nulo (const char* cstr) y realiza la misma labor que find(cstr, pos), con la diferencia de que considera la mayúscula y minúscula de cada letra como la misma. Por ejemplo, sea ecci::String s1("crecer");, la invocación s1.find("rEcE") retorna -1, mientras que s1.findNoCase('rEcE') retorna 1.

  12. [5%] Todos los métodos de clase anteriores que al ser invocados no modifican al objeto, son constantes. Es decir, reciben el parámetro this en modo const. Los métodos cuyo cuerpo son de una única sentencia, se implementan en línea.

  13. [5%] Todos los métodos están debidamente documentados con Doxygen. Tienen al menos un resumen. Si reciben parámetros, cada uno de ellos indica qué se debe enviar en ellos y qué pasa cuando se reciben valores excepcionales (por ejemplo, qué ocurre con un índice fuera de rango). Si el tipo del valor de retorno es distinto de void se indica qué retorna el método. En caso de que el método realice una tarea muy compleja, se debe explicar con un comentario detallado y preferiblemente indicar un ejemplo de uso.