En esta lección veremos casi todas las últimas generalidades básicas del lenguaje y de la programación en sí abarcando varios temas.
Esta lección será larga y les dará bastante que hacer.
Introducción a la compatibilidad de tipos:
Hasta ahora hemos visto solo tres tipos de datos, integer , real y string. Una variable integer no puede contener reales pero una real sí puede contener enteros. Esto puede resultar confuso, veamos:
El número entero 4 puede ser guardado en una variable del tipo real ya que automáticamente el compilador transforma el entero 4 en el real 4.0. Esto es totalmente posible porque el entero 4 y el real 4.0 siguen siendo exactamente el mismo valor.
A la inversa no es posible porque un real, por ejemplo, 1.2 no puede ser pasado a entero sin modificar su valor, ya sea truncándolo (dejándolo en 1) o redondeándolo de alguna manera. De este modo se pierde información y no existe un traspaso de real a integer automático.
En sus programas, si ustedes intentan ingresar un valor real, por ejemplo 5.2, verán que sus programas se caen, o sea que se da un error y el programa se cierra abruptamente. Eso pasa porque ustedes indicaron variables del tipo integer dentro de los procedimientos read o readln, entonces el programa intenta guardar un real en una variable integer y al no poder se cae.
A la inversa no habría problema, si ustedes declaran todas sus variables como real e ingresan en la entrada estándar un valor integer pues no habrá problema porque como ya dije, la conversión de integer a real es automática y no afecta en nada los valores.
Ahora, ¿qué pasa si en la entrada de nuestros programas de cálculo de área y perímetro el usuario ingresa una letra o una palabra? El programa se caerá inevitablemente. Obviamente no existe compatibilidad entre tipos numéricos y tipos de caracteres. Un buen programa debería, en vez de caerse, mostrar un mensaje de error al usuario o algo por el estilo, sin embargo eso lo veremos a partir del segundo capítulo de nuestro curso, aún no podemos hacerlo.
Estos errores no son predecibles para el compilador por lo tanto nuestros programas compilan satisfactoriamente, luego los errores vienen por parte de quién ingresa los datos y pues el sistema cae. Sin embargo, existen errores sí predecibles por el compilador y que se nos advertirán al intentar compilar:
Supongan que la variable area de mi programa del triángulo es del tipo integer, o sea que mi declaración fue así:
Código Pascal:
Ver original
Var base, altura, area: integer;
Al intentar compilar nuestro programa tendríamos un error que nos señalaría esta línea:
Código:
¿Por qué? Como dije antes, la operación de división (/) representa la división real y devuelve como valor un número real. Por ejemplo, si altura vale 3 y base vale 7 la operación base*altura/2 da como resultado 10.5, lo cual es un real. Ahora, si base vale 2 y altura vale 3 el resultado de base*altura/2 da 3, pero como / devuelve un real en realidad el 3 es 3.0. Como ven, la operación / siempre devuelve un real sin importar los operandos.area:= base*altura/2;
Al intentar asignar un valor involucrado con / a una variable del tipo integer, el compilador se da cuenta de eso y les dice que hay una incompatibilidad de tipos, que se esperaba un entero y se encontró un real.
Del mismo modo imaginen estas declaraciones de variables:
Código Pascal:
Ver original
Var numero: real; palabra: string;
Imaginen esta asignación:
Código:
Claramente hay una incompatibilidad de tipos, ya que estamos intentando asignar un valor String a un Real. El compilador se dará cuenta y nos regañará.numero:= palabra;
Sin embargo, si intentan asignar una variable entera a una real no habrá regaño, eso ya lo expliqué.
Para sus programas anteriores, lo mejor sería declarar todas las variables del tipo real, lo cual solucionaría los posibles problemas de incompatibilidad de números, sin embargo, si nuestros usuarios ingresan otra cosa que no sean números el programa caerá.
A la tarea de detectar todas las posibles situaciones que puede enfrentar nuestro programa al ser usado y sus consecuencias se le llama Captura de errores y es una de las tareas más difíciles ya que es fácil que se nos pase por alto algún caso, y más aún cuando nuestro programa es muy complejo. A medida que avancemos veremos cómo enfrentar estas situaciones, o sea, como hacer que nuestros programas sepan qué esperar y qué mostrar en caso de que lo ingresado sea incorrecto.
Errores en Tiempo de Ejecución y errores en Tiempo de Compilación:
Luego de escribir el código siempre intentamos compilarlo para generar nuestro ejecutable y ver los resultados de nuestro trabajo. Mientras el programa se compila decimos que estamos en tiempo de compilación. Los errores que pueden sufrirse aquí son generalmente de sintaxis y de compatibilidad de tipos como vimos hace un momento. Cuando hay un error en tiempo de compilación el compilador se detiene y nos indica el lugar donde encontró el error proporcionándonos además alguna información acerca de por qué se produjo. Estos son los errores más fáciles de arreglar ya que son detectables de forma sencilla.
Ahora bien, que un programa compile perfectamente no nos dice que no tenga errores. Cuando ejecutamos un programa decimos que estamos en tiempo de ejecución. Los errores en tiempo de ejecución provocan que el programa se cuelgue, termine inesperadamente perdiéndose toda la información que teníamos o que muestre resultados inesperados. Estos errores son los menos deseados y los más difíciles de detectar ya que se deben a errores en nuestras instrucciones al programa, generalmente conocidos como errores lógicos.
Con los ejemplos de hace un momento, nuestros programas sufrirían errores en tiempo de ejecución si el usuario ingresa valores inesperados en la entrada, sin embargo, puede suceder que el usuario haga todo bien y el programa aún no funcione.
Veamos un ejemplo sencillo, un programa que divide dos números:
Código Pascal:
Ver original
PROGRAM dividir; Var a, b: real; BEGIN Write(‘Ingrese un número: ‘); Readln(a); Write(‘Ingresa otro número: ‘); Readln(b); Wtieln(‘El resultado de la división es: ‘,a/b:1:2); END.
Supongamos que sabemos que nuestros usuarios solo ingresarán números a nuestro programa, o sea que no habrá problemas con los tipos de datos. ¿Cuál sería el problema entonces?
Si ustedes escriben ese código e intentan compilarlo verán que funciona perfectamente. Si asumimos que solo se ingresan números entonces no habría error posible, pero sí lo hay.
Antes de continuar, quiero que todos ustedes compilen y prueben ese programa a ver si son capaces de descubrir el problema. Luego continúen leyendo ya que lo explicaré aquí.
Pues bien. Ese código no tiene errores y el programa en sí tampoco. En realidad, si asumimos que solo se ingresarán números en la entrada estándar, de los infinitos casos de divisiones posibles existe solo una que es problemática: La división entre 0. ¿Qué pasa si el usuario ingresa como segundo valor el número 0?
Supongan el siguiente ejemplo de ejecución:
Código:
¿Qué debería mostrar nuestro programa? Al llegar a la línea 12 he intentar la división de a/b, o sea 5/0, no podrá ya que la división entre 0 no está definida matemáticamente y el programa producirá un error y se terminará su ejecución. Lo correcto sería que si el usuario ingresa un 0 para la variable b el programa nos muestre un mensaje de error y nos vuelva a pedir un nuevo valor. Cuando veamos estructuras de control veremos como tomar distintos caminos según las condiciones que se dan.Ingrese un número: 5 Ingrese otro número: 0
Este es un ejemplo claro para ver que el hecho de que un programa compile no significa que haga lo que queremos o que hayan mil errores posibles. Cuando un programa se vuelve muy complejo los posibles errores son tantos que resulta casi imposible detectarlos todos ya que a veces las posibilidades son verdaderamente infinitas. No es posible, dado un programa muy complejo, detectar todos los errores, sin embargo en la industria del software se intenta minimizar al máximo esto, existiendo equipos de trabajo solo encargados al test de programas (testing).
Palabras reservadas:
Las palabras reservadas por Pascal son aquellas que indican alguna función específica del lenguaje, como por ejemplo, write indica que algo se desplegará en pantalla y readln que el usuario ingresará alguna información. Que una palabra sea reservada indica que esta no puede utilizarse como identificador, o sea, uno no puede crear un programa llamado Writeln o Var, o una variable llamada Readln. Utilizar palabras reservadas indebidamente es un error de sintaxis.
Dicho de otro modo, las palabras reservadas tienen un significado para el lenguaje y no pueden ser utilizadas como identificadores ni colocadas en lugares en los que no concuerden, cualquiera de estos actos en un error de sintaxis y será detectado en tiempo de compilación.
He aquí una lista de casi todas las palabras reservadas en pascal, muchas de las cuales no tocaremos en este curso:
Sigan con la parte b.