// IG17 2004-05, II17 2005-06 // Cadena.h // 16-11-2004 // Ejemplo del Tema 2: // clase para representar cadenas de caracteres // Cada objeto de la clase Cadena contiene un vector de char acabado en '\0' como en C, // que se reserva y libera dinamicamente, y un entero con la talla (sin contar el '\0'). // Este ejemplo ilustra como sobrecargar operadores para concatenar cadenas, // gestionando dinamicamente la memoria necesaria, y aceptando como argumentos tanto // objetos de la clase Cadena como cadenas de C (vectores de char acabados en '\0'): // haciendo uso implicitamente del constructor que convierte un vector de char en una Cadena, // a los operadores que aceptan un argumento explicito de tipo Cadena se les podra pasar // en su lugar un vector de char. // Lo que ganaria el usuario de la clase con esta implementacion, respecto de trabajar // con cadenas como en C, es la comodidad de poder concatenar cadenas con los operadores // + y += y de no tener que gestionar el la memoria para el vector de char (la misma // comodidad que tenemos cuando usamos la clase string de la STL). // En esta clase, el constructor sin argumentos por defecto, el operador de asignacion por defecto, // el constructor de copia por defecto y el destructor por defecto NO funcionan correctamente, // por lo que se han implementado tambien. // Entre las siguientes representaciones posibles de la cadena vacia: // (1) el vector vale NULL // (2) el vector tiene un solo char, el '\0' // en esta implementacion se ha optado por la (1). Se ha tenido en cuenta que a cualquiera // de los operadores y demas funciones de la clase se les podria pasar como argumento (explicito // o implicito) un objeto que ha sido destruido mediante una llamada explicita al destructor, // o con el que no se ha hecho nada mas que la llamada al constructor sin argumentos. // Por tanto, tanto el destructor como el constructor sin argumentos deben dejar una // representacion de la cadena vacia, y las demas funciones no deben fallar si alguno // de sus argumentos es asi. En ese sentido, haber optado por la (2) habria simplificado // la implementacion de las demas funciones, ahorrando comprobaciones. Pero se ha preferido // la (1) considerando mas adecuado que en esos casos, y especialmente tras la llamada // al destructor, el vector no consuma memoria, ni siquiera para un solo caracter. // Otra alternativa habria sido escoger (1) en el destructor y (2) en el constructor sin // argumentos, pero eso no simplificaria las demas funciones. En cualquier caso, la representacion // escogida es interna: desde el punto de vista del usuario de la clase, una cadena inicializada // sin argumentos o destruida se comporta como una cadena vacia en las concatenaciones, y con ella // la funcion EsVacia() le devolvera true y la funcion Talla() le devolvera 0. // Ejercicios: // * Anyadir a la clase operadores que permitan concatenar una cadena c consigo misma n veces, // siendo n un entero no negativo, haciendo c*n o n*c (para crear una cadena nueva) // o c*=n (para modificar c). // * Anyadir a la clase mas operadores relacionales: !=, <, >, >= #ifndef _CADENA_H #define _CADENA_H #include using namespace std; class Cadena { int talla; char *caracteres; void Vaciar(); void Copiar(const char *); void Copiar(const Cadena &); public: Cadena (); // Crea una cadena vacia cuyo vector no consume memoria Cadena(const char *); // Crea una cadena dado un vector de char acabado en '\0' Cadena (const Cadena &); // Crea una cadena copia de otra ~Cadena (); // Deja una cadena vacia cuyo vector no consume memoria bool EsVacia() const; int Talla() const; friend Cadena operator+ (const Cadena &, const Cadena &); // c1+c2 devuelve c1 seguida de c2 Cadena & operator+= (const Cadena &); // c1+=c2 modifica c1 concatenandole c2 Cadena & operator= (const Cadena &); // c1 = c2 asigna c2 a c1 friend bool operator== (const Cadena &, const Cadena &); // c1==c2 vale true si son iguales friend bool operator<= (const Cadena &, const Cadena &); // c1<=c2 vale true si c1 precede lexicograficamente a c2 friend ostream & operator<< (ostream &, const Cadena &); }; #endif