CENTRO UNIVERSITARIO UAEM
ATLACOMULCO
LICENCIATURA EN
INGENIERÍA EN COMPUTACIÓN
NOMBRE DEL DOCENTE:
INGENIERO.
HÉCTOR CABALLERO HERNÁNDEZ
NOMBRE MATERIA:
AUTÓMATAS Y LENGUAJES FORMALES
NOMBRE DE LA ALUMNA:
HEIVILINA PÉREZ ARIAS
GRUPO:
ICO-19
TURNO:
MATÚTINO
TRABAJO A ENTREGAR:
*MANEJO DE EXCEPCIONES
*LA CLASE STRING Y EL PROCESAMIENTO DE
FLUJOS DE CADENA
FECHA DE ENTREGA:
21 DE ABRIL DE 2015.
LA
CLASE STRING Y EL PROCESAMIENTO
DE FLUJOS DE CADENA
Un
objeto string se puede inicializar con un argumento constructor tal como string
texto ( "Hola" ); // crea una cadena a partir de un const char * que
crea un objeto string que contiene los caracteres en "Hola", o con
dos argumentos constructores como en: string nombre( 8, 'x' ); que crea un
objeto string que contiene ocho caracteres 'x'.
La
clase string también proporciona un constructor predeterminado (que crea una
cadena vacía) y un constructor de copia. Una cadena vacía es un objeto string que no contiene caracteres.
Un
objeto string también se puede inicializar mediante la sintaxis constructora
alternativa en su definición, como en: string mes = "Marzo"; // igual
que: string mes( "Marzo" ); la clase string no proporciona
conversiones de int o char a string en una definición string.
Por ejemplo, las definiciones
string error1 = 'c';
string error2( 'u' );
string error3 = 22;
string error4( 8 );
ASIGNACIÓN Y CONCATENACIÓN DE OBJETOS STRING
[1]La función miembro at proporciona
un acceso comprobado (o comprobación de rango); es decir, al
ir más allá del final del objeto string se lanza una excepción out_of_range.
La
clase string también proporciona una versión sobrecargada de la función miembro
assign que copia un número especificado de caracteres, como en cadenaDestino.assign(
cadenaOrigen, inicio, numeroDeCaracteres ); en donde cadenaOrigen es el objeto
string que se va a copiar, inicio es el subíndice inicial y numeroDeCaracteres es
el número de caracteres a copiar.
COMPARACIÓN DE OBJETOS STRING
La clase string
proporciona funciones miembro para comparar objetos string.
Todas las funciones operador
sobrecargadas de la clase string que se demuestran aquí, así como las que no se
demuestran aquí (!=, <, >= y <=), devuelven valores bool.
Demostración de las herramientas de
comparación de cadena:
string
cadena1( "Probando las funciones de comparacion." );
string
cadena2( "Hola" );
string
cadena3( "probador" );
string cadena4( cadena2 );
SUBCADENAS
La
clase string proporciona la función miembro substr para obtener una subcadena de un objeto string. El resultado
es un nuevo objeto string que se copia del objeto string de origen.
Demostración de la función miembro
substr:
int
main()
{
string
cadena1( "El aeroplano aterrizo a tiempo." );
cout
<< cadena1.substr( 7, 5 ) << endl;
return
0;
18 }
INTERCAMBIO DE OBJETOS STRING
La
clase string proporciona la función miembro swap para intercambiar objetos string.
La
función miembro swap de string es útil para implementar programas que ordenan
cadenas.
Uso de la función swap para intercambiar
dos objetos string:
Antes
Swap:
Primero:
uno
Segundo:
dos
Después
Swap:
Primero:
dos
Segundo:
uno
CARACTERÍSTICAS DE LOS OBJETOS STRING
[2]La clase
string proporciona funciones miembro para recopilar información acerca del
tamaño de un objeto string, su longitud, capacidad, longitud máxima y otras
características. El tamaño o la longitud de un objeto string es el número de
caracteres actualmente almacenados en el objeto string. La capacidad de un objeto string es
el número de caracteres que se pueden almacenar en el objeto string sin
necesidad de asignar más memoria. La capacidad de un objeto string debe ser
cuando menos igual a su tamaño actual, aunque puede ser mayor. La capacidad
exacta de un objeto string depende de la implementación. El tamaño máximo es el mayor tamaño posible que puede tener un objeto string. Si se
excede este valor, se lanza una excepción length_error.
[3]La
función imprimirEstadisticas recibe una referencia a un objeto const string como
argumento, e imprime la capacidad (usando la función miembro capacity), el tamaño máximo (usando la función miembro max_size), el tamaño (usando la función miembro size), la longitud (usando
la función miembro length) y si el objeto string está o no vacío (usando la
función miembro empty). La llamada inicial a imprimirEstadisticas indica que
los valores iniciales para la capacidad, tamaño y longitud de cadena1 son 0.
El tamaño y la longitud de 0 indican que no hay
caracteres almacenados en un objeto string.
BÚSQUEDA DE SUBCADENAS Y CARACTERES EN UN OBJETO
STRING
La
clase string proporciona funciones miembro const para buscar subcadenas y
caracteres en un objeto string.
Declaracion:
La cadena cadena1 se declara y se inicializa. Después se trata de buscar
"es" en cadena1, usando la función find. Si se encuentra "es", se devuelve el subíndice de
la ubicación inicial de esa cadena. Si no se encuentra el objeto string, se
devuelve el valor string::npos (una
constante public static definida en la clase string).
Se
utiliza la función miembro find_first_of
para localizar la primera ocurrencia en cadena1 de cualquier carácter en
"liesop".
REEMPLAZO
DE CARACTERES EN UN OBJETO STRING
Se
utiliza la función miembro erase de
string para borrar todo, desde (e incluyendo a) el carácter en la posición x
hasta el final de cadena1. [Nota: cada carácter de nueva línea ocupa un
elemento en el objeto string].
Se
utiliza find para localizar cada ocurrencia del carácter de espacio. Después,
cada espacio se reemplaza con un punto mediante una llamada a la función
miembro replace de string.
La función replace recibe tres argumentos: el
subíndice del carácter en el objeto string en el que debe empezar el reemplazo,
el número de caracteres a reemplazar y la cadena de reemplazo. La función
miembro find devuelve string::npos cuando no se encuentra el carácter de
búsqueda. Se utiliza la función find para buscar cada punto y otra función
replace sobrecargada para reemplazar cada periodo y su siguiente carácter con
dos signos de punto y coma.
Los
argumentos que se pasan a esta versión de replace son el subíndice del elemento
en el que comienza la operación de reemplazo, el número de caracteres a
reemplazar, una cadena de caracteres de reemplazo de la cual se selecciona una
subcadena para utilizarla como caracteres de [4]reemplazo, el elemento en
la cadena de caracteres en la que empieza la subcadena de reemplazo, y el
número de caracteres en la cadena de caracteres de reemplazo que se debe
utilizar.
INSERCIÓN DE CARACTERES EN UN OBJETO STRING
La
clase string proporciona funciones miembro para insertar caracteres en un
objeto string.
Al utilizar string::npos, se
inserta todo el objeto string.
Al utilizar string::npos, se
inserta todo el objeto string.
Demostración de las funciones
miembro insert de string.
cadena3.insert(
3, cadena4, 0, string::npos );
CONVERSIÓN A CADENAS ESTILO C
La
clase string proporciona funciones miembro para convertir objetos de la clase
string en cadenas basadas en apuntador estilo C. Como dijimos antes, a
diferencia de las cadenas basadas en apuntador, los objetos string no tienen necesariamente
una terminación nula. Estas funciones de conversión son útiles cuando una
función dada recibe una cadena basada en apuntador como argumento.
El objeto string cadena1 se
inicializa con "cadenas", ptr1 se inicializa con 0 y longitud se
inicializa con la longitud de cadena1. La memoria de un tamaño suficiente como
para contener una cadena basada en apuntador equivalente al objeto string
cadena1 se asigna en forma dinámica y se adjunta al apuntador char ptr2.
Esta
función miembro devuelve un arreglo de caracteres estilo C sin terminación
nula.
ITERADORES
La
clase string proporciona iteradores para realizar recorridos hacia adelante y
hacia atrás de objetos string. Los iteradores proporcionan acceso a los
caracteres individuales con una sintaxis similar a las operaciones de los
apuntadores.
No se comprueba el rango de los
iteradores.
El
iterador iterador1 se inicializa al principio de cadena1 con la función miembro
begin de la clase string.
Existen dos versiones de begin: una que devuelve un iterator para iterar a
través de un objeto string no const y una versión const que devuelve un
const_iterator para iterar a través de un objeto const_string.
La
clase string proporciona las funciones miembro rend y rbegin para
acceder a los caracteres individuales de un objeto string en forma inversa,
desde el fi nal de un objeto string hacia su inicio. Las funciones miembro rend
y rbegin devuelven objetos reverse_iterator
o const_reverse_iterator (dependiendo
de si el objeto string es no const o const).
PROCESAMIENTO DE FLUJOS DE CADENA
Además
de la E/S de f lujos estándar y la E/S de f lujos de archivos, en C++ la E/S de
f lujos incluye herramientas para recibir datos de (y enviar datos a) objetos
string en la memoria. A menudo, a estas herramientas se les conoce como E/S en memoria o procesamiento de flujos de cadena.
[5]La entrada desde un objeto
string está soportada por la clase istringstream.
La salida hacia un objeto string está soportada por la clase ostringstream. Los nombres de las
clases istringstream y ostringstream son en realidad alias definidos por las
siguientes definiciones typedef:
typedef
basic_istringstream< char > istringstream;
typedef
basic_ostringstream< char > ostringstream;
Las
plantillas de clase basic_istringstream y basic_ostringstream proporcionan la
misma funcionalidad que las clases istream y ostream, además de otras funciones
miembro específi cas para el formato en memoria. Los programas que utilizan el
formato en memoria deben incluir los archivos de encabezado <sstream> y <iostream>.
Enviar
datos a un objeto string es una buena forma de aprovechar las poderosas
herramientas de formato de la salida de los f lujos de C++. Los datos se pueden
preparar en un objeto string para imitar el formato de pantalla editado.
Ese
objeto string se podría escribir en un archivo en disco para preservar la
imagen de la pantalla.
Un
objeto ostringstream utiliza un objeto string para almacenar los datos de
salida. La función miembro str de
la clase ostringstream devuelve una copia de ese objeto string.
MANEJO
DE EXCEPCIONES
GENERALIDADES
[6]El manejo de excepciones
permite al programador remover el código para manejo de errores de la “línea
principal” de ejecución del programa, lo cual mejora la claridad y capacidad de
modificación del mismo. Esta flexibilidad reduce la probabilidad de que los
errores se pasen por alto y, por consecuencia, hace que los programas sean más
robustos.
Definición
de una clase de excepción para representar el tipo del problema que podría
ocurrir
La clase runtime_error, una clase derivada
de la clase exception de la
Biblioteca estándar (definida en el archivo de encabezado <exception>), es la clase base
estándar de C++ para representar errores en tiempo de ejecución.
La
clase exception es la clase base estándar de C++ para todas las excepciones.
[7]Una clase de excepción típica que
se deriva de la clase runtime_error define sólo un constructor que pasa una cadena de mensaje de error al
constructor de la clase base runtime_error. Cada clase de excepción que se deriva
en forma directa o indirecta de exception contiene la función virtual what, la cual devuelve el mensaje de
error de un objeto excepción. No es obligatorio derivar una clase de excepción
personalizada (como ExcepcionDivision- EntreCero) de las clases de excepciones
estándar que proporciona C++.
Encerrar
código en un bloque try
El manejo de excepciones está orientado a
situaciones en las que la función que detecta un error no puede manejarlo.
El lenguaje de C++ proporciona bloques try para permitir el manejo de
excepciones. Un bloque try consiste en la palabra clave try, seguida de llaves ({}) que definen un bloque de código en el
que podrían ocurrir errores. El bloque try encierra instrucciones que podrían
ocasionar excepciones, e instrucciones que se deberían omitir si ocurre una
excepción.
Definición
de un manejador catch para procesar una excepcion division entre cero
Las excepciones se procesan mediante los manejadores catch también conocidos
como manejadores de excepciones,
que atrapan y manejan las excepciones. Inmediatamente después de cada bloque
try. Cada manejador catch empieza con la palabra clave catch y especifica entre paréntesis un parámetro de excepción que representa el tipo de excepción que
puede procesar el manejador catch (en este caso, ExcepcionDivisionEntreCero).
Cuando ocurre una excepción en un bloque
try, el manejador catch que se ejecuta es aquél cuyo tipo coincide con el tipo
de la excepción que ocurrió. Si un parámetro de excepción incluye un nombre de
parámetro opcional, el manejador catch puede usar ese nombre de parámetro para
interactuar con la excepción atrapada en el cuerpo del manejador catch, que
está delimitado por llaves ({y}).
Modelo
de terminación del manejo de excepciones
Si ocurre una excepción como resultado de
una instrucción en un bloque try, este bloque expira (termina de inmediato).El
programa busca el primer manejador catch que pueda procesar el tipo de
excepción que ocurrió. El programa localiza el catch que coincida, comparando
el tipo de la excepción lanzada con el tipo del parámetro de excepción de cada
catch, hasta que el programa encuentra una coincidencia.
Flujo
del control del programa cuando el usuario escribe un denominador de cero
[8]El operando de una instrucción
throw puede ser de cualquier tipo. Si el operando es un objeto, lo llamamos objeto excepción; en este ejemplo, el
objeto excepción es un objeto de tipo Excepcion Division Entre Cero. Un
operando de throw también puede asumir otros valores, como el valor de una expresión
que no produce un objeto (throw x > 5) o el valor de un int (por ejemplo,
throw 5).
En realidad, el manejador catch atrapa una
referencia al objeto Error Division EntreCero creado por la instrucción throw
de la función cociente. El objeto excepción se mantiene mediante el mecanismo de
manejo de excepciones.
CUÁNDO
UTILIZAR EL MANEJO DE EXCEPCIONES
El manejo de excepciones no está diseñado
para procesar los errores asociados con los eventos síncronos (por ejemplo, completar la E/S de disco, la llegada de
mensajes de red, los clics del ratón y las pulsaciones de tecla), los cuales
ocurren en paralelo con, y de manera independiente a, el f lujo de control del
programa.
El mecanismo de manejo de errores también
es útil para procesar problemas que ocurren cuando un programa interactúa con
los elementos de software, como las funciones miembro, los constructores, los
destructores y las clases.
[9] Las funciones con condiciones de errores
comunes deben devolver 0 o NULL (u otros valores apropiados), en vez de lanzar excepciones.
Un programa que llame a dicha función puede comprobar el valor de retorno para
determinar si la llamada a la función tuvo éxito o fracasó.
VOLVER
A LANZAR UNA EXCEPCIÓN
Es posible que un manejador de
excepciones, al momento de recibir una excepción, decida que no puede procesar
esa excepción o que puede procesar la excepción sólo de manera parcial. En tales casos, el manejador de excepciones
puede diferir el manejo de excepciones a otro manejador de excepciones. En cualquier
caso, para lograr esto hay que volver a lanzar
la excepción mediante la siguiente instrucción:
throw;
ESPECIFICACIONES
DE EXCEPCIONES
Una especificación de excepciones opcional también conocida como lista throw enumera una lista de
excepciones que puede lanzar una función. Por ejemplo, se considera la
siguiente Declaración de una función:
int unaFuncion( double valor )
throw ( ExcepcionA, ExcepcionB, ExcepcionC
)
{
}
La especificación de la función, que
empieza con la palabra clave throw justo después del paréntesis de cierre de la
lista de parámetros de la función, indica que la función unaFuncion puede
lanzar excepciones de los tipos ExcepcionA, ExcepcionB y ExcepcionC.
Una función sólo puede lanzar excepciones
de los tipos indicados por la especificación, o excepciones de cualquier tipo
derivado de estos tipos. Si la función lanza (throw) una excepción que no
pertenezca a un tipo especificado, el mecanismo de manejo de excepciones llama
a la función unexpected, la cual
termina el programa.
Una función que no proporciona una
especificación de excepciones puede lanzar cualquier excepción. Al colocar throw()
(una especificación de excepciones
vacía) después de la lista de parámetros de una función, se establece
que esa función no lanza excepciones. Si la función intenta lanzar una
excepción, se invoca la función unexpected.
PROCESAMIENTO
DE EXCEPCIONES INESPERADAS
La función unexpected llama a la función
registrada con la función set_unexpected (definida en el archivo de encabezado <exception>).
Si no se ha registrado una función de esta forma, se hace una llamada a la
función terminate de manera predeterminada.
Las funciones set_terminate y
set_unexpected devuelven un apuntador a la última función llamada por terminate
y unexpected, respectivamente (0, la primera vez que se llama a cada una). Esto permite al programador guardar el apuntador
a la función, para poder restaurarlo más adelante. Las funciones set_terminate
y set_unexpected reciben como argumentos apuntadores a funciones con tipos de
valores de retorno void y sin argumentos.
LIMPIEZA
DE LA PILA
Limpiar la pila de llamadas a funciones
significa que la función en la que no se atrapó la excepción termina, todas las
variables locales en la función se destruyen y el control regresa a la
instrucción que invocó originalmente a esa función. Si un bloque try encierra
esa instrucción, se hace un intento de atrapar la excepción. Si un bloque try
no encierra esa instrucción, se vuelve a realizar la limpieza de la pila.
El constructor no puede devolver un valor
para indicar un error, debemos elegir un medio alternativo de indicar que el
objeto no se ha construido en forma apropiada. Un esquema es devolver el objeto
mal construido y esperar que alguien que lo use realice las pruebas apropiadas
para determinar que se encuentra en un estado inconsistente. Otro esquema es
establecer una variable fuera del constructor.
Una excepción podría impedir la operación
de código que por lo general liberaría un recurso, con lo cual se produciría una
fuga de recursos. Una técnica para resolver este problema es inicializar un
objeto local para adquirir el recurso.
[10]Cuando ocurra una
excepción, se invocará al destructor para ese objeto y se podrá liberar el
recurso.
EXCEPCIONES
Y HERENCIA
El uso
de la herencia con excepciones permite a un manejador de excepciones atrapar
los errores relacionados con una notación concisa. Una metodología es atrapar
cada tipo de apuntador o referencia a un objeto excepción de clase derivada en
forma individual, pero una metodología más concisa es atrapar mejor apuntadores
o referencias a objetos excepción de la clase base.
Además,
al atrapar apuntadores o referencias a objetos excepción de una clase derivada
se pueden cometer errores, en especial si el programador olvida evaluar de
manera explícita uno o más de los tipos apuntador o referencia de la clase
derivada.
PROCESAMIENTO
DE LAS FALLAS DE NEW
El estándar de C++ especifica que, cuando
falla el operador new, lanza una excepción bad_alloc (definida en el archivo de encabezado <new>). Algunos
compiladores no están en conformidad con el estándar de C++, y por lo tanto
utilizan la versión de new que devuelve 0 al fallar.
Los
compiladores varían en cuanto a su soporte para el manejo de fallas de new.
Manejo
de las fallas de new mediante la función set_new_handler
Una característica adicional para manejar
las fallas de new es la función set_new_handler (cuyo prototipo se encuentra en
el archivo de encabezado estándar <new>). Esta función recibe como argumento
un apuntador a una función que no recibe argumentos y devuelve void. Este
apuntador apunta a la función que se llamará si new falla. Esto proporciona al
programador una metodología uniforme para manejar todas las fallas de new, sin
importar que ocurra una falla en el programa.
[11]Una vez que
set_new_handler registra un manejador
de new en el programa, el operador new no lanza bad_alloc en el futuro;
en vez de ello, difiere el manejo de errores a la función manejadora de new.
Si new asigna memoria con éxito, devuelve
un apuntador a esa memoria.
LA
CLASE AUTO_PTR Y LA ASIGNACIÓN DINÁMICA DE MEMORIA
Un objeto de la clase auto_ptr mantiene un
apuntador a la memoria que se asigna en forma dinámica. Cuando se hace una
llamada al destructor de un objeto auto_ptr (cuando un objeto auto_ptr queda
fuera de alcance), realiza una operación delete con su miembro de datos
apuntador.
La plantilla de clase auto_ptr proporciona
los operadores sobrecargados * y ->, de manera que un objeto auto_ptr se
puede utilizar de la misma forma que una variable apuntador común.
Sólo un objeto auto_ptr puede poseer un
objeto asignado en forma dinámica en un momento dado, y el objeto no puede ser
un arreglo. Al usar su operador de asignación sobrecargado o su constructor de
copia, un objeto auto_ptr puede transferir la propiedad de la memoria dinámica
que maneja. El último objeto auto_ptr que mantiene el apuntador a la memoria
dinámica eliminará la memoria.
JERARQUÍA
DE EXCEPCIONES DE LA BIBLIOTECA ESTÁNDAR
La experiencia ha demostrado que las
excepciones se pueden clasificar en varias categorías. La Biblioteca estándar de C++ incluye una jerarquía de clases
de excepciones. Las clases derivadas inmediatas de la clase base exception
incluyen a runtime_error y logic_error (ambas
definidas en el encabezado <stdexcept>), cada una de las cuales tiene
varias clases derivadas. De exception también se derivan las excepciones
lanzadas por los operadores de C++; clase logic_error es la clase base de
varias clases de excepciones estándar que indican errores en la lógica del
programa.
Por ejemplo, la clase invalid_argument indica que se pasó un
argumento inválido a una función. (Sin duda, la codificación apropiada puede
evitar que lleguen argumentos inválidos a una función). La clase length_error indica que para ese
objeto se utilizó una longitud mayor que el tamaño máximo permitido para el objeto
que se está manipulando.
[12]La clase runtime_error, es
la clase base de varias otras clases de excepciones estándar que indican
errores en tiempo de ejecución. Por ejemplo, la clase overflow_error describe un error
de desbordamiento aritmético (es decir, el resultado de una operación
aritmética es mayor que el número más grande que se puede almacenar en la
computadora) y la clase underflow_error
describe un error de
subdesbordamiento.
OTRAS
TÉCNICAS PARA MANEJAR ERRORES
Ignorar la excepción. Si ocurre una
excepción, el programa podría fallar como resultado de la excepción que no se
atrapó. Esto es devastador para los productos de software comerciales y el
software de misión crítica y propósito especial, pero para el software desarrollado
para nuestros propios fines, es común ignorar muchos tipos de errores:
1.-Abortar el programa. Sin duda, esto
evita que un programa se ejecute hasta completarse y que produzca resultados incorrectos.
Para muchos tipos de errores esta técnica es apropiada, en especial para los
errores no fatales que permiten a un programa ejecutarse hasta completarse (con
lo cual el programador podría pensar que el programa funciona correctamente).
2.-Establecer indicadores de errores. El
problema con esta metodología es que los programas tal vez no comprueben estos
indicadores de errores en todos los puntos en los que los errores podrían
resultar problemáticos.
3.-Probar la condición de error, generar
un mensaje de error y llamar a exit (en <cstdlib>) para pasar un código de
error apropiado al entorno del programa.
4.-Usar las funciones setjump y longjump.
Estas funciones de la biblioteca <csetjump> permiten al programador
especificar un salto inmediato, desde una llamada a una función con muchos niveles
de anidamiento hasta un manejador de errores.
REFERENCIA
BIBLIOGRAFICA:
|
DEITEL, HARVEY M. Y PAUL J. DEITEL
Cómo programar en C++. Sexta edición.
PEARSON EDUCACIÓN, México 2008.
|
No hay comentarios:
Publicar un comentario