Anuncios

Bienvenidos sean a este post, hoy veremos como manipular errores.

Anuncios

En realidad, en programacion no se los denomina como errores sino mas bien como excepcion. Y si bien existen errores, tambien conocidos como bugs, pero esos estaran manejados de otra manera. Nosotros manejaremos a excepciones y estos pueden tener principalmente dos causas:

  • logicos
  • sintacticos
Anuncios
Anuncios

Los errores de tipo logicos podemos considerarlos como humanos porque principalmente seran debido a una logica erronea a la hora de trabajar con nuestro codigo, por eso podemos considerarlo como humano, Los sintacticos tambien pueden ser humanos porque principalmente es la mala aplicacion de una funcion o parametros. En el caso de los errores logicos, el compilador no nos dira nada pero veremos que el programa no se comporta como queremos. Pero en el caso de sintacticos, el compilador si nos lo notificara y en los ultimos tiempos inclusive te da unas sugerencias, cosa que hace un tiempo no sucedia, pero que sucede cuando el codigo compila pero al ejecutarlo y en alguna accion ocurre un error? Ahi es cuando entran en accion las excepciones y las podemos manejar mediante varias funciones.

Anuncios

La funcion try sera la encargada de evaluar a nuestro codigo y mediante catch podemos atrapar las excepciones que sucedan y las manipularemos. Veamos como se aplica:

int main()
{
	try
	{
		--- instrucciones ...
	}
	catch(excepcion) {
		... instrucciones ...
	}

	return 0;
}
Anuncios
Anuncios

Siempre ira dentro del main. Como dijimos, en el try iran todas las instrucciones del main o las que deseemos evaluar. Luego tenemos el catch para interceptar cualquier excepcion que surja en el try. Si no sucede nada, la ejecucion sera como siempre. De lo contrario, el catch procede a ejecutar su bloque para manipular el error pero eso lo veremos en un momento. Y por ultimo, todo esto siempre estara antes del return 0 que usamos habitualmente para cerrar nuestros codigos. Antes de pasar al ejemplo, les comento que podemos usar catch todas las veces que necesitemos. Con esto comentado, veamos el siguiente ejemplo:

#include <iostream>
#include <string.h>

const int tamanoPred = 10;

template < class T >
class Arreglo
{
public:
        Arreglo(int tamano = tamanoPred);
        Arreglo(const Arreglo & rhs);
        ~Arreglo() { delete [] pTipo; }
        Arreglo & operator= (const Arreglo &);
        T & operator[] (int pos) { return pTipo[pos]; }
        const T & operator[] (int pos) const { return pTipo[pos]; }
        int GetTamano() const { return tamano; }
private:
        T *pTipo;
        int tamano;
};

template <class T>
Arreglo< T >::Arreglo(int tam): tamano(tam)
{
        pTipo = new T[ tam ];
}

template <class T>
Arreglo< T >::Arreglo(const Arreglo & rhs)
{
        tamano = rhs.GetTamano();
        pTipo = new T[tamano];
        for(int i=0; i < tamano; i++)
                pTipo[i] = rhs[i];
}

template <class T>
Arreglo< T > & Arreglo< T >::operator=(const Arreglo & rhs)
{
        if (this == &rhs)
                return *this;
        delete [] pTipo;
        tamano = rhs.largo();
        pTipo = new T[ tamano ];
        for(int i=0; i < tamano; i++)
                pTipo[i] = rhs[i];
        return *this;
}

int main()
{
        Arreglo< std::string > coches(5);
        coches[0] = "FORD";
        coches[1] = "VW";
        coches[2] = "AUDI";
        coches[3] = "TOYOTA";
        coches[4] = "PEUGEOT";

        for(int i=0; i < 5; i++)
                std::cout << coches[i] << std::endl;

        return 0;
}
Anuncios
Anuncios

Este codigo lo usaremos para crear unos arrrays de distintos tipos. Lo primero que haremos es incluir las dos librerias que usaremos. Lo siguiente sera definir una constante que usaremos para establecer un tamaño predeterminado para nuestros arrays cuando no lo informemos. Lo siguiente sera la clase que usaremos para crear los arrays. La plantilla sera para que podamos usar cualquier tipo. En la parte publica de la clase tenemos dos constructores. El primero para crear uno vacio y otro para asignarle valores recibidos mediante otro array. El destructor para eliminar al array en si y luego una serie de sobrecargas. La primera sera para el operador = y las sguientes son para el operador de posicion y nos permita recuperar el dato de la posicion informada. Lo hacemos para el operador comun y otro en una constante. Para finalente, definir un metodo donde recuperaremos el valor de una propiedad privada. En la parte privada tenemos: un puntero que sera donde almacenaremos los distintos elementos del «array» y la otra sera para almacenar el tamaño del array generado, este es el valor que recupera el ultimo metodo en la parte publica.

Anuncios
Anuncios

Luego definiremos varios de los metodos de la clase anterior. Los primeros dos son para definir los constructores. El primero es el basico donde inicia el valor de tamano en base al recibido o el de la constante sino lo informamos, este crea un objeto para el puntero de la parte privada con la cantidad de posiciones que recibe como dato. El siguiente constructor es para cuando recibe valores mediante rhs. Donde estableceremos el valor de tamano con los datos recibidos. Creamos un objeto para el puntero y mediante un bucle le asignaremos todos los elementos al nuevo array. Por ultimo, tenemos la definicion de la sobrecarga del operador =. En este haremos algo similar al constructor anterior pero primero verificaremos si el objeto es similar al recibido. En caso de ser verdadero, devolvemos al objeto directamente mediante this. En caso contrario, elimina al puntero y lo vuelva a generar para luego rellenarlo mediante el objeto recibido con el mismo procedimiento del constructor anterior y devolveremos el objeto creado.

Anuncios

En el main crearemos un objeto del tipo Arreglo y almacenara cinco elementos de tipo string. Luego agregaremos distintos valores a cada posicion. Para finalmente mostrar los valores en el array cargado. Compilemos y veamos como es la salida:

$ ./probar
FORD
VW
AUDI
TOYOTA
PEUGEOT
$
Anuncios

Con esto tenemos un codigo funcional pero hagamos una pequeña modificacion en el main:

int main()
{
        Arreglo< std::string > coches(5);
        coches[0] = "FORD";
        coches[1] = "VW";
        coches[2] = "AUDI";
        coches[3] = "TOYOTA";
        coches[4] = "PEUGEOT";
        coches[5] = "CHEVROLET";

        for(int i=0; i < 5; i++)
                std::cout << coches[i] << std::endl;


        return 0;
}
Anuncios

En este caso, agregamos una sola linea nueva y esta es un nuevo valor para nuestro array, en una posicion por fuera de las existentes. El resto del codigo sigue siendo igual. Si lo compilan no devolvera ningun error pero si lo ejecutamos sucedera lo siguiente:

$ ./probar
Violación de segmento
$
Anuncios

Tomemos el codigo y modifiquemoslo de la siguiente manera:

#include <iostream>
#include <string.h>

const int tamanoPred = 10;

template < class T >
class Arreglo
{
public:
        Arreglo(int tamano = tamanoPred);
        Arreglo(const Arreglo & rhs);
        ~Arreglo() { delete [] pTipo; }
        Arreglo & operator= (const Arreglo &);
        T & operator[] (int pos) {
                int tam = GetTamano();
                if (pos >= 0 && pos < tam) return pTipo[pos];
                throw limite();
                return pTipo[0];
        }
        const T & operator[] (int pos) const {
                int tam = GetTamano();
                if (pos >= 0 && pos < tam) return pTipo[pos];
                throw limite(pTipo);
                return pTipo[0];
        }
        int GetTamano() const { return tamano; }
        class limite {};
private:
        T *pTipo;
        int tamano;
};

template <class T>
Arreglo< T >::Arreglo(int tam): tamano(tam)
{
        pTipo = new T[ tam ];
}

template <class T>
Arreglo< T >::Arreglo(const Arreglo & rhs)
{
        tamano = rhs.largo();
        pTipo = new T[tamano];
        for(int i=0; i < tamano; i++)
                pTipo[i] = rhs[i];
}

template <class T>
Arreglo< T > & Arreglo< T >::operator=(const Arreglo & rhs)
{
        if (this == &rhs)
                return *this;
        delete [] pTipo;
        tamano = rhs.largo();
        pTipo = new T[ tamano ];
        for(int i=0; i < tamano; i++)
                pTipo[i] = rhs[i];
        return *this;
}

int main()
{
Arreglo< std::string > coches(5);
try
{
        coches[0] = "FORD";
        coches[1] = "VW";
        coches[2] = "AUDI";
        coches[3] = "TOYOTA";
        coches[4] = "PEUGEOT";
        coches[5] = "CHEVROLET";

        for(int i=0; i < 5; i++)
                std::cout << coches[i] << std::endl;
}
catch ( Arreglo< std::string >::limite) {
        std::cout << "Esta fuera del limite" << std::endl;
}

return 0;
}
Anuncios

En este codigo hicimos dos modificaciones importantes, la primera sera en la clase Arreglo. Veamos como es la nueva clase:

template < class T >
class Arreglo
{
public:
        Arreglo(int tamano = tamanoPred);
        Arreglo(const Arreglo & rhs);
        ~Arreglo() { delete [] pTipo; }
        Arreglo & operator= (const Arreglo &);
        T & operator[] (int pos) {
                int tam = GetTamano();
                if (pos >= 0 && pos < tam) return pTipo[pos];
                throw limite();
                return pTipo[0];
        }
        const T & operator[] (int pos) const {
                int tam = GetTamano();
                if (pos >= 0 && pos < tam) return pTipo[pos];
                throw limite();
                return pTipo[0];
        }
        int GetTamano() const { return tamano; }
        class limite {};
private:
        T *pTipo;
        int tamano;
};
Anuncios
Anuncios

La primera es que agregamos una clase vacia llamada limite y sera una sub-parte de esta clase. Las otras modificaciones la hicimos en la sobrecarga del operador[] para las posiciones del array. En lugar de devolver solamente la posicion del mismo le hemos agregado un par de cosas mas. La primera es una nueva variable donde almacenara el tamaño del array. Luego tenemos un condicional donde si la posicion que debemos usar es mayor o igual a 0 y menor que el tamaño obtenido procede a devolver la posicion del array. En caso de no cumplirse utiliza una funcion throw y que enviara a la clase vacia que definimos anteriormente. Para finalmente, devolver el valor en la primera posicion. Esto es simplemente para que el compilador no devuelva ningun error.

Anuncios

throw es una funcion que nos permite emitir una excepcion. Es decir, cuando suceda un error o algo inesperado emitira una excepcion personalizada. En este caso, va a ser cuando la posicion informada se encuentre por fuera del condicional. Pero como nos ayuda esta funcion en nuestro error? Para ello pasemos al main y veamos como lo modificamos:

int main()
{
Arreglo< std::string > coches(5);
try
{
        coches[0] = "FORD";
        coches[1] = "VW";
        coches[2] = "AUDI";
        coches[3] = "TOYOTA";
        coches[4] = "PEUGEOT";
        coches[5] = "CHEVROLET";

        for(int i=0; i < 5; i++)
                std::cout << coches[i] << std::endl;
}
catch ( Arreglo< std::string >::limite) {
        std::cout << "Esta fuera del limite" << std::endl;
}

return 0;
}
Anuncios
Anuncios

Al codigo le agregamos al try y catch para poder manipular nuestras excepciones. Por fuera del try y el catch declararemos o definiremos todas nuestras variables y objetos de las clases. Esto es asi porque todo lo declarado dentro de los bloques de try o catch sera local para ellos y no podran ser accedidos. Por esta razon, declaramos antes del try al objeto coches. En el bloque del try agregaremos todos los valores y haremos un bucle para mostrar todos los valores agregados. En el catch esperaremos una excepcion del tipo de la clase limite pero debemos especificar el origen. Por esta razon, usamos a Arreglo y el tipo string. Y en este bloque mostraremos un mensaje indicando que esta fuera del limite. Si lo compilamos y ejecutamos tendremos la siguiente salida:

$ ./probar
Esta fuera del limite
$
Anuncios

Pero esto lo podemos mejorar un poco mas y para ello debemos modificar unicamente al catch de la siguiente manera:

catch ( Arreglo< std::string >::limite) {
        std::cout << "++ Esta respuesta viene desde catch ++\n";
        for(int i=0; i < coches.GetTamano(); i++)
                std::cout << coches[i] << std::endl;
}
Anuncios

En esta ocasion modificamos unicamente el contenido del bloque no solamente para indicar que se ejeccuta desde aca sino que tambien realiza la tarea que debia pero se interrumpio debido al envio mediante throw. Compilemos y veamos como es la salida:

$ ./probar
++ Esta respuesta viene desde catch ++
FORD
VW
AUDI
TOYOTA
PEUGEOT
$
Anuncios

Con esto tenemos la respuesta basica para manejar un tipo de excepcion pero como podemos manejar varias? Para eso, modificaremos el codigo anterior de la siguiente manera:

#include <iostream>
#include <string.h>

const int tamanoPred = 10;

template < class T >
class Arreglo
{
public:
        Arreglo(int);
        Arreglo(const Arreglo & rhs);
        ~Arreglo() { delete [] pTipo; }
        Arreglo & operator= (const Arreglo &);
        T & operator[] (int pos) { return pTipo[pos]; }
        const T & operator[] (int pos) const { return pTipo[pos]; }
        int GetTamano() const { return tamano; }
        class chico {};
        class grande {};
        class vacio {};
        class negativo {};
private:
        T *pTipo;
        int tamano;
};

template <class T>
Arreglo< T >::Arreglo(int tam): tamano(tam)
{
        if (tamano == 0) throw vacio();
        if (tamano < tamanoPred) throw chico();
        if (tamano > tamanoPred) throw grande();
        if (tamano < 0) throw negativo();

        pTipo = new T[ tam ];
}

template <class T>
Arreglo< T >::Arreglo(const Arreglo & rhs)
{
        tamano = rhs.largo();
        pTipo = new T[tamano];
        for(int i=0; i < tamano; i++)
                pTipo[i] = rhs[i];
}

template <class T>
Arreglo< T > & Arreglo< T >::operator=(const Arreglo & rhs)
{
        if (this == &rhs)
                return *this;
        delete [] pTipo;
        tamano = rhs.largo();
        pTipo = new T[ tamano ];
        for(int i=0; i < tamano; i++)
                pTipo[i] = rhs[i];
        return *this;
}

typedef Arreglo< int > Numeros;

template < class T >
void mostrar_datos(const Arreglo< T > & d, int tam)
{
        for(int i=0; i < tam; i++)
                std::cout << d[i] << std::endl;
}

int main()
{
try
{
        Numeros arreglo(20);
        for (int i=0, j=1; i < arreglo.GetTamano(); i++, j++)
                arreglo[i] = j;
        mostrar_datos(arreglo, arreglo.GetTamano());
}
catch ( Numeros::grande ) {
        std::cout << "++ Este Arreglo es de tamaño grande ++\n";
}
catch ( Numeros::vacio ) {
        std::cout << "++ Este Arreglo esta vacio ++\n";
}
catch ( Numeros::chico ) {
        std::cout << "++ Este Arreglo es de tamaño chico ++\n";
}
catch(...) {
        std::cout << "Algo salio realmente mal...\n";
}
return 0;
}
Anuncios

Hablemos de los primeros cambios. En la clase Arreglo modificamos a los operadores de sobrecarga de posicion de array para que solo muestre la posicion que le pedimos, eliminando el condicional y el throw. La siguiente modificacion fue el agregado de varias clases que usaremos para enviar mediante throw.

Anuncios
Anuncios

Continuando con las modificaciones, la siguiente es en el constructor donde le pasamos el tamaño. En ella tendremos una serie de condicionales donde en base al tamaño recibido enviaremos mediante throw una de las clases definidas anteriormente en Arreglo. Para el caso de cuando sea cero se enviara a la clase vacio. Para cuando es menor al tamaño predeterminado, la constante, enviara a chico. Cuando es mayor al predeterminado enviara a grande y para valores negativos enviara a negativo. El resto sigue siendo de la misma manera pero nos queda un par de cambios mas.

Anuncios

Antes del main agregaremos una nueva funcion que tendra una plantilla para manejar cualquier dato. Esta nueva funcion la usaremos para mostrar los datos almacenados en nuestros arrays creados desde Arreglo. Recibira dos datos, el primero sera el objeto de tipo Arreglo y luego la cantidad que mostraremos. Para mostrarlos usamos a un bucle que pasara por todas por las posiciones del objeto.

Anuncios
Anuncios

En el main, tenemos un try donde crearemos un array de 20 posiciones, lo llenaremos con un bucle for. Este tendra dos variables, siendo la primera para las posiciones y la segunda para el valor que almacenarmos en cada posicion. Una vez creado, lo siguiente sera llamar a la funcion anterior para mostrar el contenido. Despues tenemos un catch para cada clase enviada desde el constructor. En cada uno mostraran un mensaje relacionado a la clase interceptada. Por ultimo, tenemos un catch con tres puntos, …, y este sera para interceptar cualquier error que no este contemplado por los anteriores. Compilemos y veamos como es la salida:

$ ./probar
++ Este Arreglo es de tamaño grande ++
$
Anuncios

En este caso, al ser mayor nos devovio el mensaje indicando que es grande. Si modifican unicamente el tamaño de arreglo a 10, la salida sera la siguiente:

$ ./probar
1
2
3
4
5
6
7
8
9
10
$
Anuncios

Como pueden ver al no cumplirse ninguna condicion del constructor y no enviar una clase, ejecuta las instrucciones dentro del bucle para cargarlas y mostrarlas. Pero como podemos mejorar la utilizacion de la intercepcion de las excepciones. Bueno para ello debemos tomar el codigo anterior y modificarlo de la siguiente manera:

#include <iostream>
#include <string.h>

const int tamanoPred = 10;

template < class T >
class Arreglo
{
public:
        Arreglo(int);
        Arreglo(const Arreglo & rhs);
        ~Arreglo() { delete [] pTipo; }
        Arreglo & operator= (const Arreglo &);
        T & operator[] (int pos) { return pTipo[pos]; }
        const T & operator[] (int pos) const { return pTipo[pos]; }
        int GetTamano() const { return tamano; }
        class Tamanio
        {
        public:
                Tamanio(int tam): tamanio(tam){}
                ~Tamanio() {}
                virtual int GetTam() { return tamanio; }
                virtual void Mostrar()
                {
                        std::cout << "Error de tamaño.\n";
                }
        protected:
                int tamanio;
        };
        class chico: public Tamanio {
        public:
                chico(int tam): Tamanio(tam) {}
                virtual void Mostrar()
                {
                  std::cout << "++ Este Arreglo es de tamaño chico.";
                  std::cout << " Porque tiene " << Tamanio::tamanio;
                  std::cout << " posiciones. ++" << std::endl;
                }
        };
        class grande: public Tamanio
        {
        public:
                grande(int tam): Tamanio(tam) {}
                virtual void Mostrar()
                {
                  std::cout << "++ Este Arreglo es de tamaño grande.";
                  std::cout << " Porque tiene " << Tamanio::tamanio;
                  std::cout << " posiciones. ++" << std::endl;
                }
        };
        class vacio: public Tamanio
        {
        public:
                vacio(int tam): Tamanio(tam) {}
                virtual void Mostrar()
                {
                  std::cout << "++ Este Arreglo esta vacio";
                  std::cout << " y no se puede usar. ++" << std::endl;
                }
        };
        class negativo: public Tamanio
        {
        public:
                negativo(int tam): Tamanio(tam) {}
                virtual void Mostrar()
                {
                  std::cout << "++ Este Arreglo tiene un valor negativo ";
                  std::cout << " y no se puede usar. ++" << std::endl;
                }
        };
protected:
        T *pTipo;
        int tamano;
};

template <class T>
Arreglo< T >::Arreglo(int tam): tamano(tam)
{
        if (tamano == 0) throw vacio(tam);
        if (tamano < 0) throw negativo(tam);
        if (tamano < tamanoPred) throw chico(tam);
        if (tamano > tamanoPred) throw grande(tam);

        pTipo = new T[ tam ];
}

template <class T>
Arreglo< T >::Arreglo(const Arreglo & rhs)
{
        tamano = rhs.largo();
        pTipo = new T[tamano];
        for(int i=0; i < tamano; i++)
                pTipo[i] = rhs[i];
}

template <class T>
Arreglo< T > & Arreglo< T >::operator=(const Arreglo & rhs)
{
        if (this == &rhs)
                return *this;
        delete [] pTipo;
        tamano = rhs.largo();
        pTipo = new T[ tamano ];
        for(int i=0; i < tamano; i++)
                pTipo[i] = rhs[i];
        return *this;
}

typedef Arreglo< int > Numeros;

template < class T >
void mostrar_datos(const Arreglo< T > & d, int tam)
{
        for(int i=0; i < tam; i++)
                std::cout << d[i] << std::endl;
}

int main()
{
bool salir = false;
while(!salir) {
try
{
        int pos;
        std::cout << "Ingresa la cantiddad de posiciones: ";
        std::cin >> pos;
        Numeros arreglo(pos);
        for (int i=0, j=1; i < arreglo.GetTamano(); i++, j++)
                arreglo[i] = j;
        mostrar_datos(arreglo, arreglo.GetTamano());
        salir = true;
}
catch ( Numeros::Tamanio & excepcional ) {
        excepcional.Mostrar();
}
catch(...) {
        std::cout << "Algo salio realmente mal...\n";
}
}
return 0;
}
Anuncios

Los primeros cambios que realizamos fueron principalmente en la clase Arreglo y en las clases que agregamos dentro de esta. Veamos la primera que es la clase Tamanio y es nueva:

        class Tamanio
        {
        public:
                Tamanio(int tam): tamanio(tam){}
                ~Tamanio() {}
                virtual int GetTam() { return tamanio; }
                virtual void Mostrar()
                {
                        std::cout << "Error de tamaño.\n";
                }
        protected:
                int tamanio;
        };
Anuncios

Esta tendra una para almacenar el tamaño de nuestros arrays, por esta razon tendremos una propieddad en protected, no private, para que sus herederas puedan acceder libremente. En la parte publica tenemos un constructor para iniciar a la propiedad anterior con un valor recibido, un destructor, un metodo para recuperar el valor «privado» y un metodo para mostrar un mensaje de error. Luego tenemos las clases anteriores pero en lugar de estar vacias tendran algunas instrucciones. Las cuatro clases son muy similares en su estructura por lo que tomaremos una de ejemplo para comentarlas:

        class chico: public Tamanio {
        public:
                chico(int tam): Tamanio(tam) {}
                virtual void Mostrar()
                {
                  std::cout << "++ Este Arreglo es de tamaño chico.";
                  std::cout << " Porque tiene " << Tamanio::tamanio;
                  std::cout << " posiciones. ++" << std::endl;
                }
        };
Anuncios
Anuncios

Todas seran herederas de la clase nueva, Tamanio, y todas tendran un constructor que recibira un valor. Este lo usaremos para iniciar la propiedad heredada mediante el llamado a su constructor. Lo siguiente es una anulacion u override del metodo heredado. En este caso, lo haremos para indicar que el tamaño es chico y mostramos cual fue el valor pasado. Para ello usaremos a la propiedad tamanio y le indicamos cual es la clase donde lo contiene. Recuerden que esta en modo protected y al ser heredera directa se puede acceder como si fuera publica. Esto es muy similar para la clase grande pero indicaremos que el valor pasado es mayor y tambien mostraremos el valor. En cambio, en el caso de la clase vacio y negativo solo indicaremos que esta vacio y tiene valores negativos, impidiendo que podamos usarlo. Otra pequeña modificacion que realizamos fue cambiar el orden de los condicionales donde ahora el encargado de enviar la clase negativo esta antes que chico. Esto debemos hacerlo asi porque el valor cumplira la condicion de chico y nunca veremos a la clase negativo. Y la ultima modificacion, la hicimos en el main. Veamos como quedo ahora:

int main()
{
bool salir = false;
while(!salir) {
try
{
        int pos;
        std::cout << "Ingresa la cantiddad de posiciones: ";
        std::cin >> pos;
        Numeros arreglo(pos);
        for (int i=0, j=1; i < arreglo.GetTamano(); i++, j++)
                arreglo[i] = j;
        mostrar_datos(arreglo, arreglo.GetTamano());
        salir = true;
}
catch ( Numeros::Tamanio & excepcional ) {
        excepcional.Mostrar();
}
catch(...) {
        std::cout << "Algo salio realmente mal...\n";
}
}
return 0;
}
Anuncios
Anuncios

Primero agregamos una variable de tipo bool con un valor false. Despues, envolvimos con un while al try con todo el contenido asi como el catch. Este bucle se repetira mientras salir sea false. En el try tambien hicimos un par de modificaciones. La primera es agregar la posibilidad de poder ingresar la cantidad de posiciones para nuestro array. Con este dato ingresado lo crearemos y aqui se dispararan las excepciones. En caso de no dispararse alguno, procede a usar un bucle para ingresar los datos en el array anterior. Lo siguiente es mostrar los datos con la funcion mostrar_datos. Y finalmente, establecemos a salir con el valor de true para salir del bucle. La otra modificacion fue eliminar todos los catch que teniamos para cada excepcion. Esto podemos hacerlo porque la clase que pasamos al catch es Tamanio. Y ahora todas al ser herederas de esta, se encarga automaticamente de usar a la clase correcta. Pero en cada ocasion usaremos un objeto de esta clase. Por lo tanto, en el bloque ahora tomara la clase recibida y este llamara al metodo Mostrar de la clase. Como pueden ver, esto hace exactamente lo mismo pero con un solo catch. Seguimos manteniendo el ultimo caso para ver si surge una eventualidad no contemplada. Compilemos y veamos como trabaja:

$ ./probar
Ingresa la cantiddad de posiciones: 0
++ Este Arreglo esta vacio y no se puede usar. ++
Ingresa la cantiddad de posiciones: -1
++ Este Arreglo tiene un valor negativo  y no se puede usar. ++
Ingresa la cantiddad de posiciones: 9
++ Este Arreglo es de tamaño chico. Porque tiene 9 posiciones. ++
Ingresa la cantiddad de posiciones: 11
++ Este Arreglo es de tamaño grande. Porque tiene 11 posiciones. ++
Ingresa la cantiddad de posiciones: 10
1
2
3
4
5
6
7
8
9
10
$
Anuncios

Observen como nos manejo cada excepcion en base al valor ingresado. Nunca se termino el bucle y siempre estuvo activo. Pero al momento de ingresar el mismo valor que en la constante se realizo la ejecucion del try y procedio a salir del bucle. Esta es una forma mas «avanzada» de manejar nuestras excepciones o errores. Donde de otras formas hubiera salido del programa, por ejemplo con un array de posiciones con valores negativos.

Anuncios

En resumen, hoy hemos visto a excepciones, las instrucciones que las manejan, las distintas posibilidades, asi como mediante algunos ejemplos vimos como mejorar el manejo de las mismas. Espero les haya resultado de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios

Donatión

It’s for site maintenance, thanks!

$1.50