/* cadena.cpp - Definición de la clase CCadena
 */
#include <iostream>
#include "cadena.h"
using namespace std;

/////////////////////////////////////////////////////////////////
// Mensajes de error
static char *MensajeError[] = {
   "insuficiente memoria" };
  
// Manipulación del error
void CCadena::error(char *mensaje)
{
  cerr << "\aerror: " << mensaje << endl;
  exit(1);
}  

// Constructores
// Constructor para: CCadena c y CCadena c("cadena")
CCadena::CCadena(const char *pcad)
{
  if (pcad == 0) // construir una cadena nula
    nlong = 0;
  else
    nlong = strlen(pcad);

  pmCad = new (nothrow) char[nlong + 1];
  if (!pmCad) CCadena::error(MensajeError[0]);

  if (pcad == 0) // construir una cadena nula
    *pmCad = 0;
  else
    strcpy(pmCad, pcad);
}

// Constructor copia
CCadena::CCadena(const CCadena& x)
{
  nlong = x.nlong;
  pmCad = new (nothrow) char[nlong + 1];
  if (!pmCad) CCadena::error(MensajeError[0]);
  strcpy(pmCad, x.pmCad);
}

// Construye una cadena de n caracteres igual a car      
CCadena::CCadena(char car, int n)
{
  nlong = n;
  pmCad = new (nothrow) char[nlong + 1];
  if (!pmCad) CCadena::error(MensajeError[0]);
  fill(pmCad, pmCad+nlong, car);
  pmCad[nlong] = '\0';
}

// Destructor. Liberar memoria
CCadena::~CCadena()
{
  delete [] pmCad;
}

// Operadores de asignación
CCadena& CCadena::operator=(const CCadena& x)
{
  nlong = x.nlong;
  delete [] pmCad;
  pmCad = new (nothrow) char[nlong + 1];
  if (!pmCad) CCadena::error(MensajeError[0]);
  strcpy(pmCad, x.pmCad);
  return *this;
}

CCadena& CCadena::operator=(const char *c)
{
  nlong = strlen(c);
  delete [] pmCad;
  pmCad = new (nothrow) char[nlong + 1];
  if (!pmCad) CCadena::error(MensajeError[0]);
  strcpy(pmCad, c);
  return *this;
}

// Operador de indexación
char& CCadena::operator[](unsigned int ind)
{
  if (ind < 0 || nlong < ind)
    cerr << "error: índice fuera de rango\n";
  return pmCad[ind];
}

// Concatenar cadenas de caracteres
CCadena operator+(const CCadena& x, const CCadena& y)
{
  CCadena CadTemp;
  CadTemp.nlong = x.nlong + y.nlong;
  // Liberar la cadena nula asignada por el constructor
  delete [] CadTemp.pmCad;
  CadTemp.pmCad = new (nothrow) char[CadTemp.nlong + 1];
  if (!CadTemp.pmCad) CCadena::error(MensajeError[0]);
  strcpy(CadTemp.pmCad, x.pmCad);
  strcat(CadTemp.pmCad, y.pmCad);
  return CadTemp;
}

CCadena CCadena::operator+=(const CCadena& x)
{
  return *this = *this + x;
}

// Comparación de cadenas
bool operator==(const CCadena& x, const CCadena& y)
{
  return strcmp(x.pmCad, y.pmCad) == 0;
}

bool operator!=(const CCadena& x, const CCadena& y)
{
  return !(x == y);
}

bool operator<(const CCadena& x, const CCadena& y)
{
  return strcmp(x.pmCad, y.pmCad) < 0;
}

bool operator>(const CCadena& x, const CCadena& y)
{
  return strcmp(x.pmCad, y.pmCad) > 0;
}

// Operaciones de entrada/salida
ostream& operator<<(ostream& os, const CCadena& x)
{
  return os << x.pmCad;
}
    
istream& operator>>(istream& is, CCadena& x)
{
  char cadena[256], c;
  
  is.get (cadena, 256, '\n');
  if (is.get(c) && c != '\n')
    cerr << "Cadena demasiado larga; se ha truncado\n";

  x = cadena; // llama al operador =  
  return is;
}
/////////////////////////////////////////////////////////////////

