Este documento presenta un curso gratuito de programación en Pascal dirigido a todas las personas, independientemente de su nivel de conocimiento. El curso se dictará en línea a través de lecciones semanales publicadas en un foro, donde los estudiantes podrán hacer preguntas y practicar ejercicios. El curso introducirá conceptos básicos de programación estructurada en Pascal, programación modular en Modula y programación orientada a objetos en Java, incluyendo el uso de bases de datos en MySQL.
Este documento presenta un curso gratuito de programación en Pascal dirigido a todas las personas, independientemente de su nivel de conocimiento. El curso se dictará en línea a través de lecciones semanales publicadas en un foro, donde los estudiantes podrán hacer preguntas y practicar ejercicios. El curso introducirá conceptos básicos de programación estructurada en Pascal, programación modular en Modula y programación orientada a objetos en Java, incluyendo el uso de bases de datos en MySQL.
Este documento presenta un curso gratuito de programación en Pascal dirigido a todas las personas, independientemente de su nivel de conocimiento. El curso se dictará en línea a través de lecciones semanales publicadas en un foro, donde los estudiantes podrán hacer preguntas y practicar ejercicios. El curso introducirá conceptos básicos de programación estructurada en Pascal, programación modular en Modula y programación orientada a objetos en Java, incluyendo el uso de bases de datos en MySQL.
Este documento presenta un curso gratuito de programación en Pascal dirigido a todas las personas, independientemente de su nivel de conocimiento. El curso se dictará en línea a través de lecciones semanales publicadas en un foro, donde los estudiantes podrán hacer preguntas y practicar ejercicios. El curso introducirá conceptos básicos de programación estructurada en Pascal, programación modular en Modula y programación orientada a objetos en Java, incluyendo el uso de bases de datos en MySQL.
Descargue como DOC, PDF, TXT o lea en línea desde Scribd
Descargar como doc, pdf o txt
Está en la página 1de 150
Curso de Programacin desde Cero PASCAL
Tienes idea de lo que es programar? Alguna vez intentaste aprender algn
lenguaje de programacin? Tienes idea de lo que es un lenguaje? Ya tienes conocimientos pero sientes que te has quedado trancado y que con lo que sabes no puedes hacer mucho? No tienes ni idea de nada pero te interesa conocer algo de lo que es el mundo de la programacin? Les propongo un curso gratuito de programacin el cual est dirigido absolutamente a todo pblico, no importa si no saben absolutamente nada, si saben algo o si son expertos programadores. Quin no sepa nada podr aprender gradualmente a programar, quin sepa algo podr reafirmar conceptos y aprender nuevos; quin sepa mucho podr aportar sus conocimientos. Cmo ser la modalidad? Pues ser sencilla: Yo ser su tutor on-line, y cada semana publicar una leccin en esta comunidad (a veces dos). Dicha leccin ser un simple hilo en el foro. La administracin les har saber cundo he publicado nuevas lecciones, o ustedes mismos podrn entrar en este hilo y ver si hay algo nuevo. Cada leccin estar dedicada pura y exclusivamente a un tema especfico. Ustedes podrn, y espero que lo hagan, postear para preguntar sus dudas, sugerir ideas, corregir errores, etc. De este modo el curso ser interactivo y dinmico. Les pedir que no me hagan las consultas por mensajes privados ya que la idea es que todos las vean y puedan leer las respuestas que doy, de modo que todos aprendamos de todos. En cada leccin habr ejemplos explicados paso a paso y sobretodo habr ejercicios que espero que hagan. Qu veremos en el curso? Pues, bsicamente el curso estar dividido en tres subcursos, por as llamarlos: Los introducir al mundo de la Programacin Estructurada utilizando el lenguaje de programacin Pascal. Aprendern aspectos de diseo y Programacin Modular en el lenguaje Modula , aplicando lo ya aprendido en Pascal. Terminaremos el curso con Programacin Orientada a Objetos utilizando el lenguaje !ava. La ltima parte nos llevar tambin a aprender a gestionar bases de datos, lo cual implicar aprender un lenguaje para ello, el cual ser M"SQL. Qu podr #acer luego de terminar el curso? Pues tendrn la capacidad de realizar sistemas de porte mediano los cuales podrn manejar bases de datos, tener interfaces grficas bonitas y dinmicas. Sern capaces de disear proyectos interesantes y sumamente complejos, disearlos y resolverlos en el lenguaje !ava. Podrn aprender por su cuenta leyendo simple bibliografa nuevos lenguajes de programacin y as extender sus conocimientos. Es decir, sern programadores avanzados. Desde aqu enlazaremos cada leccin: Leccin 01: ntroduccin al curso y preparacin para comenzar. Leccin 02: Salida estndar bsica Leccin 03: dentificadores, variables y entrada estndar bsica Leccin 04: Errores, tipos primitivos, operadores y algo ms... Leccin 05:Constantes, booleanos e introduccin a la seleccin. Leccin 06: Condiciones booleanas y seleccin. Leccin 07: Secuencia de repeticin FOR Leccin 08: Repeticin condicional con WHLE...DO Leccin 09: Extra Depurador Leccin 10: Repeticin Condicional - Repeat - Leccin 11: Subrangos y arreglos lineales Leccin 12: Arreglos multidimensionales Leccin 13: Primer Proyecto Difcil - Master Mind Leccin 14: Subprogramas - Procedimientos Programando desde $% $&' (ntroduccin al curso " preparacin para comen)ar* (ntroduccin% Existe un gran nmero de personas que escriben a foros y blogs en la WEB en la bsqueda de distintos manuales o tutoriales que enseen a programar desde cero, o sea, que alguien que no sepa nada en absoluto sobre la programacin sea capas de aprender con solo leer. En efecto, eso es posible y es a lo que apunta este curso. Deben saber que la base para ser un buen programador es la prctica. Debern trabajar mucho y realizar muchos programas, por ms tontos e inservibles que parezcan, cada vez que aprendan un concepto nuevo. Encontrarn varios ejercicios en este curso que les ayudarn a solidificar lo que hayan aprendido hasta el momento ya que la mayora de ellos han sido ideados por verdaderos profesores en el campo de la programacin. Quiero reafirmar la importancia de la prctica. Los lenguajes de programacin tienen reglas muy estructuradas sobre sintaxis y semntica as como tambin muchas palabras que uno debe ir aprendiendo y comprendiendo en profundidad. Tambin est el hecho de que uno debe desarrollar una forma de pensar y analizar los problemas demasiado lgica para lograr resolverlos creando programas de computadora. Aadir tambin que el gran conocimiento de matemtica facilitar mucho el desarrollo de software, pero sin embargo, si no se entienden demasiado con esta materia podrn aprender a programar y ser buenos en ello, pero nunca olviden que la matemtica y la programacin estn profundamente ligadas. Una vez hayan completado este curso sern capaces de crear aplicaciones bsicas en el lenguaje Pascal, aunque estas podrn tener una complejidad enorme, de verdad. El objetivo de este texto no es que ustedes salgan programando software para vender ni nada por el estilo, es que aprendan a programar de la nada, es introducirlos al mundo de la programacin estructurada. Teniendo estos conocimientos en mente, ustedes sern capaces de aprender luego un lenguaje mucho ms moderno y complejo con mayor facilidad que si lo intentaran ahora, sin saber nada. ----------------------------------------------------------------------------- +ociones sobre Lengua,e de Programacin% Supongo que cualquiera que se aventure a leer este manual es porque sabe lo que es usar una computadora y por ende, lo que es un programa de computadora, tambin conocido como aplicacin. Sin embargo estoy seguro de que a la mayora de las personas que "saben lo que es un programa, si se les pidiera que le explicaran a alguien que jams ha visto una computadora, sin tener una enfrente, lo que es un programa no sabran como hacerlo. En realidad es muy sencillo de definir: Un programa es un conjunto de instrucciones bien detalladas que la computadora seguir al pie de la letra, nada ms. Un programador es quien escribe ese conjunto de instrucciones que sern interpretadas y seguidas por un procesador. Dicho as suena muy fcil. Uno escribe instrucciones que sern seguidas al pie de la letra por la computadora. Sin embargo este es el gran problema que hace que uno como programador tenga que romperse la cabeza pensando en como hacer que una computadora realice tal o cual accin y como tomar en cuenta todas las variantes que puede haber acerca de una misma situacin. Ahora bien, si uno como programador ha de escribir instrucciones, cmo lo hace? Es aqu donde entran en juego los lenguajes de programacin. Existen de dos tipos: Lengua,es de ba,o nivel y Lengua,es de alto nivel. Los primeros se escriben en el vejo y querido cdigo binario el cual est constituido nicamente por $ y & y es lo nico que un procesador (CPU) puede entender e interpretar. Tambin se conocen como lengua,e de m-uina. Creo que todo el mundo est de acuerdo en que programar as es una tortura, es inhumano y sumamente tedioso y aburrido. Y pensar que en principio todo se haca as y muchas cosas an se hacen as. Gracias a la necesidad de poder crear aplicaciones de computadora de una forma ms fcil y entendible es que nacen los Lenguajes de Alto Nivel, que se parecen ms a los hablados por los seres humanos y por tanto son mucho ms comprensibles para nosotros. Sin embargo, como dije antes, una CPU solo entiende el lenguaje de mquina y por ende no uno de alto nivel. Aqu entra en juego un programa muy especial: el compilador. Un compilador es una aplicacin que se encarga de "traducir ese cdigo de alto nivel parecido a un lenguaje humano a lenguaje de mquina para que pueda ser interpretado por una Unidad Central de Proceso (CPU). Y entonces como se programa un compilador? Como ven, a veces hay que seguir luchando con el cdigo binario. Lenguajes de alto nivel muy nombrados son: C, C++, C-sharp, Pascal, PHP, Java, HTML, Borland, Ruby, entre muchsimos otros ms. Dado que lo escrito en el lenguaje de alto nivel (cdigo fuente del programa) ser luego traducido por un compilador a 0 y 1, debe hacerse respetando una sintaxis y una semntica bien establecidas, sin excepciones. Nosotros especficamente en este manual aprenderemos las nociones bsicas de la programacin estructurada, cmo se estudia un problema dado y se comienza a crear el programa que lo resuelve, entre muchas otras cosas. Todo lo haremos con el lenguaje Pascal, que hoy en da solo es usado con fines acadmicos de aprendizaje, y debo decir que realmente funciona para ese fin. ----------------------------------------------------------------------------- (nstalando el ambiente de desarrollo .ree'Pascal% Para trabajar con Pascal utilizaremos el compilador Free-Pascal 2.2.2. Este programa debe ser descargado desde ESTE ENLACE o desde la pgina oficial de Free Pascal. Una vez descargado el instalador ejecutar el mismo y seguir los siguientes pasos: Nota: En las imgenes se observa la versin 2.0.2 y no la 2.2.2, sin embargo los pasos de instalacin son los mismos. Presionar en Next. Seleccionar un directorio de instalacin. Es recomendable aceptar el directorio que aparece por defecto (C:\FPC\2.x.x). Apretar el botn +e/t. En la siguiente ventana, se seleccionan los componentes del compilador que van a ser instalados. Se recomienda seleccionar Full Instalation. En caso de que dispongan de poco espacio en su disco duro, pueden seleccionar inimal Instalation. Apretar el botn Next. Next otra vez. Asociar todos los tipos de archivos que ofrece, sobre todo los que terminan con la extensin *pas y luego apretar el botn Next. Presionar en Install y esperar a que termine de instalar todos los archivos. Esto a veces puede tardar bastante a pesar de que el compilador pesa muy poco. Si llegaron hasta aqu sin errores, el compilador y el ambiente de desarrollo han quedado instalados. ---------------------------------------------------------------------------- 0eri1icando instalacin% Ahora debemos verificar si el compilador qued correctamente instalado. Lo que haremos es ejecutar el compilador desde la l!nea de comandos de la siguiente manera: El primer paso es reiniciar la computadora para que todas las modificaciones realizadas por el programa instalador tengan efecto. (Es posible que alcance con salir de la sesin y volver a entrar). Acceder al tem del men inicio; Inicio " #jecutar Escribir "cmd sin comillas y apretar la tecla ENTER. En la consola escribir $pc y apretar la tecla ENTER, como en la figura. Si todo est bien debera salir un mensaje similar al siguiente: Para terminar presione enter varias veces hasta que termine de desplegar. NOTA: Es posible que esta prueba no funcione bien y an as puedan trabajar correctamente con Pascal, en todo caso lo terminarn de verificar al crear el primer programa. ----------------------------------------------------------------------------- Si en lugar del mensaje anterior, aparece un mensaje que indica que el comando fpc no es vlido, significa que algo anduvo mal en la instalacin. Pueden probar a reiniciar la computadora y volver a realizar este paso de verificacin. Si siguen teniendo problemas, les recomiendo desinstalar el compilador y volver a comenzar de nuevo la instalacin. Si probaron reinstalar y sigue sin funcionar este paso de verificacin, ser necesario realizar alguna configuracin adicional, como les explico a continuacin: En primer termino, verifiquen la existencia de la carpeta C:\FPC\2.2.2\%IN\I&'()*IN&2. Pueden hacerlo utilizando el explorador de Windows, accediendo por Mi PC, luego Disco X: (donde X es la unidad de disco duro) y as sucesivamente. Tambin pueden verificarlo por el siguiente comando en la consola DOS:dir C:\FPC\2.2.2\%IN\I&'()*IN&2 Si esa carpeta no existe, estamos en problemas. La instalacin no copi los archivos necesarios, quizs no tengan los permisos requeridos para la instalacin. ntenten volver a instalar. Si la carpeta existe, verifiquen que en la misma hay un archivo de nombre fpc.exe. Si este archivo existe, solamente hay que decirle al sistema donde puede encontrarlo (se supone que la instalacin lo hace automticamente, pero por alguna razn no funcion). Procedan de la siguiente manera: 1. Accedan Mi Pc Panel de Control Sistema 2. Seleccionen la pestaa Avanzado 3. Accionen el botn Variables de entorno 4. En la lista superior pulsen nueva e ingresen estos valores: o nombre: path o valor: +pat,+-C:\FPC\2.2.2\%IN\I&'()*IN&2 5. Dar aceptar en todas las ventanas. nsisto que el paso anterior no debera ser necesario, ya que el instalador se encarga de realizarlo, sin embargo algunos usuarios han reportado ese problema. Por ms informacin ver: nstalling under DOS or Windows en el sitio de Free Pascal. NOTA: nsisto en el hecho de que si no funciona la verificacin puede que logren trabajar bien con Pascal, en todo caso podrn solo hacerlo desde el ambiente de desarrollo y no desde la lnea de comandos, lo cual no implica dificultada alguna. Verificaremos eso al crear el primer programa. Si an as no pudieran trabajar, entonces optaremos por otro compilador. ----------------------------------------------------------------------------- Corrigiendo un 2ug " con1igurando para comen)ar% Al intentar compilar por primera vez (ya veremos como se hace esto) el compilador indica un error illegal parameter ./pentium&. Este es un error que sorprende bastante ya que viene por defecto, pero bueno, es as. Por suerte es bien sencillo de solucionar. Al abrir por primera vez el ambiente de desarrollo DE vallan al men /ptions"Compiler En el cuadro de texto 0ditional Compiler 0rgs, cambiar ./pentium& por ./ppentium& Pulsar el botn /1. Acceder al men: /ptions"2a3e Luego cerrar y volver a abrir el DE. Con esto queda solucionado. En caso de presentar problemas con esto posteen aqu y hagan todas las preguntas que quieran. Les ayudar hasta que logren trabajar bien. ----------------------------------------------------------------------------- Con1iguracin de 3ange C#ec4ing e (nteger 5ver1lo6% Hace falta aadir una ltima configuracin antes de comenzar a programar, y esta consta de hacer que el compilador siempre haga un chequeo de que nuestros valores no se van fuera del rango que deben tener. Esto lo entendern en ms profundidad cuando comencemos a trabajar con arreglos, pero es conveniente tenerlo configurado desde ahora para evitarse muchos problemas. Deben ir al men /ptions ..4 Compiler y all presionar sobre la pestaa 5enerate Code. En el cuadro Code generation marcarn las opciones 6ange c,ec7ing e Integer o3er$lo8 c,ec7ing tras lo cual darn /1. Ahora s, ya estamos listos para comenzar a programar. Adelante!!! Programando desde $% $' Salida estndar bsica* L7CC(8+ % Salida estndar bsica Bien, como la primera leccin ha sido simplemente de instalacin y configuracin no tiene caso seguir esperando. Sin embargo, en las lecciones siguientes (incluida esta), tardaremos ms tiempo en publicar una u otra ya que ustedes necesitarn entender y sobretodo practicar. Recuerden en todo momento que esto es de aprendizaje progresivo y todo lo dado anteriormente se usar en el momento. No tiene caso jams continuar con las lecciones siguientes si no han entendido las anteriores, por eso les pedir verdaderamente que pregunten chorrocientas veces todo lo que no entiendan, no tenga vergenza, lo importante es que lo comprendan de verdad, as que pregunten pregunten y pregunten todava ms. En esta segunda leccin veremos la estructura ms bsica de un programa pascal creando dos aplicaciones que simplemente muestren mensajes en pantalla. ----------------------------------------------------------------------------- +97S:35 P3(M73 P35;3AMA% <===>5LA M9+?5@@@A Al abrir el ambiente de desarrollo DE vemos una pantalla azul, realmente espantosa, pero es a la que nos debemos acostumbrar si queremos aprender a programar de verdad. Existen compiladores ms bonitos, pero muchos no son de licencia free y por tanto no los usaremos aqu, y los otros que s son free dan alguna complicacin, as que prefiero que utilicen el Free-Pascal y es en el que centrar las lecciones, sin embargo cada un@ de ustedes es libre de usar el ambiente de desarrollo que quiera. Por defecto, la primera vez que se abre el DE lo hace con una hoja en blanco cuyo ttulo ser "noname9:.pas. El botn verde en la esquina superior izquierda de la pantalla es para cerrar el archivo actualmente abierto, luego veremos como trabajar con varios a la vez (aunque generalmente no ser necesario). La flechita verde en la esquina superior derecha es para maximizar y minimizar la ventana que contiene dicho archivo. En el borde derecho y tambin abajo tenemos barras de desplazamiento para movernos a travs del cdigo que escribiremos. Abajo, a la izquierda de la barra de desplazamiento vemos las coordenadas de nuestra posicin: 1ila%columna, o sea, dnde est nuestro cursor. Para cada ejemplo de programa escrito aqu analizaremos casi lnea por lnea lo que significa cada cosa para que se entienda. En principio uno se dedica a copiar programas hechos sin entender nada y poco a poco va aprendiendo hasta que se hace capaz de crear los propios. Ahora crearemos un programa muy simple que lo nico que har es imprimir en la pantalla el clsico texto ;;;<ola mundo===: Cdigo: 1 PROGRAM HolaMundo; 2 3 BEGN 4 write('Hola mundo!!!'); 5 END. Ustedes deben escribir eso en el DE, veamoslo detenidamente: Siempre la primera lnea de un programa debe comenzar con la palabra reservada P6/560 (detallaremos lo que significa que una palabra sea reservada ms adelante) seguida por un nombre para el programa (identi1icador), en este caso <olaundo (poda haber sido cualquier otra cosa). Luego de eso debe ir un punto y coma ( ; ) para finalizar la primera lnea. Los punto y coma funcionan como separadores y son los que indican que ha finalizado una sentencia (instruccin). Siempre luego de una instruccin va un punto " coma para 1inali)arla. En la segunda lnea no hemos escrito nada, esto es simplemente por una cuestin de legibilidad del cdigo. En la tercera lnea indicamos que comienza el cdigo del programa mediante la palabra reservada %#5IN. Esto no es una sentencia, por lo cual no debe finalizar con punto y coma, solo indica que a partir de all estarn las instrucciones que el programa debe seguir (en realidad quin las sigue es la CPU). En la cuarta lnea indicamos al programa mediante el procedimiento 8rite (que en ingls significa escribir) que imprima en la pantalla el texto ;;;<ola mundo===. Siempre luego de un procedimiento 8rite debe colocarse entre parntesis lo que queremos escribir en la pantalla, en este caso un te/to especB1ico. Siempre que queramos que un texto aparezca en pantalla tal cual nosotros lo escribimos en nuestro cdigo debemos indicarlo colocando dicho texto entre comillas simples como se ve en el ejemplo. Como 8rite implica una instruccin, luego de finalizada colocamos un punto y coma. Notar que dicha instruccin la hemos colocado ms hacia la derecha que el resto del cdigo. Esto no afecta en nada al programa, al igual que en la segunda lnea que qued vaca, sino que lo hace ms legible. A esta accin se la llama (ndentacin y es muy importante. Luego detallaremos este aspecto al trabajar con programas complejos y que llevan un cdigo ms largo. La quinta y ltima lnea indica la finalizacin del programa mediante la palabra reservada #N> seguida inmediatamente por un punto (.). Esa es la nica palabra que terminar con un punto indicando el fin de la aplicacin. Ahora debemos compilar nuestro programa. Para ello pueden ir al men Compile ..4 Compile o presionar 0lt?F@. Se les pedir un nombre para el archivo, el cual no podr contener espacios ni caracteres especiales y debe terminar con la extensin *pas. Luego de eso comenzar inmediatamente el proceso de compilacin. Si ustedes no han tenido errores de sintaxis, o sea, si han respetado el lugar adecuado para cada palabra Reservada y no olvidaron ningn punto y coma o no colocaron alguno donde no iba, aparecer un cartel con el mensaje Compile success$ul: Press anA 7eA. Esto habr creado un ejecutable (archivo de extensin exe, dicha extencin proviene de la palabra "executable que en ingls significa ejecutable) en el mismo directorio en el que han guardado el archivo *pas. Un archivo *pas contiene el cdigo fuente que ustedes han escrito. Por defecto el DE guarda un archivo en el directorio B:\$pc\2.2.2\bin\i&'(.8in&2 pero ustedes pueden especificar cualquier otro. Es conveniente que si hacen esto ninguna carpeta de su direccin posea ms de ocho caracteres como nombre ni tampoco caracteres especiales o de espacio. Ahora pueden abrir su archivo ejecutable haciendo doble clic sobre l. Tambin pueden ejecutar su programa mediante el meni] Run --> Run[/i] o presionando Ctrl?F@. En este ejemplo especfico, como en muchos otros que veremos, al correr su programa no llegarn ni a leer el texto que aparece ya que se cerrar inmediatamente. Esto no es ningn error, los programas que escribiremos finalizarn luego de terminar sus nstrucciones. Claro que aprenderemos a crear aplicaciones donde uno puede seleccionar cuando salir. Si lo ejecutaron desde el DE simplemente vayan al men >ebug ..4 User screen o presionen 0lt?FC. De este modo vern lo que apareci en la pantalla al ejecutar el programa. Luego presionen cualquier tecla para volver al DE. La otra opcin es ejecutar su programa desde la lnea de comandos: r al men Inicio ..4 #jecutar y escriban cmd para abrir la lnea de comandos. En ella deben escribir la direccin en la que est el ejecutable que han creado y escribir el nombre exacto del mismo, que ser idntico al que ustedes usaron al guardar el archivo *pas de cdigo fuente. En mi ejemplo yo guard mi cdigo fuente con el nombre >olaMundo*pas con lo cual habr creado un ejecutable >olaMundo*e/e. Para todo aquel que no lo sepa, al abrir la lnea de comandos aparece un directorio del sistema por defecto. Para cambiar de directorio en DOS se usa el comando cd (change directory) seguido de la direccin del nuevo directorio: Al presionar enter luego de escribir esa instruccin quedaremos posicionados en el directorio donde alojamos nuestro programa. Obviamente si nosotros creamos otro directorio para trabajar con nuestras aplicaciones pascal especificaremos la ruta de dicho directorio. Una vez estamos en el directorio correcto escribimos el nombre de nuestro programa y damos enter. Enseguida se ejecutar y podremos ver sus resultados: Otra forma es abrir la lnea de comandos como ya expliqu, y arrastrar el archivo ejecutable hacia ella y soltarlo all, de ese modo se escribir automticamente su direccin y al presionar ENTER lo ejecutaremos. Del mismo modo podemos compilar nuestros programas desde la lnea de comandos. Nos posicionamos en el directorio donde radica nuestro cdigo fuente y escribimos la instruccin $pc <olaundo.pas para este caso, de lo contrario la instruccin es 1pc +ombre?elArc#ivo*pas donde +ombre?elArc#ivo ser el nombre con el cual guardamos nuestro cdigo fuente. ----------------------------------------------------------------------------- Crite " Criteln% Ahora veremos un programa que imprimir dos frases de texto, una en una lnea y la otra debajo: Cdigo: 1 PROGRAM SalidaEstandar; 2 3 BEGN 4 writeLn('Hice mi primer programa en Pascal.'); 5 write('Logr el clsico "Hola mundo.') 6 END. Al igual que antes en la primera lnea escribimos PROGRAM seguido de un identificador para el programa, finalizando la lnea con un punto y coma. En la lnea 3 indicamos el inicio de las instrucciones mediante BEGN. En la cuarta lnea utilizamos el procedimiento 6riteLn para imprimir un texto en pantalla. Este procedimiento funciona exactamente igual que 6rite. La diferencia entre la una y la otra es que 8rite imprime algo en pantalla y deja el cursor justo al final de esa lnea y, de modo contrario, 8riteln imprime un texto y deja el cursor al inicio de la lnea siguiente (o sea, baja un rengln). As, con el ejemplo anterior obtenemos como salida: <ice mi primer programa en Pascal. DogrE el clsico F<ola mundoG. Noten que la ltima sentencia no finaliza con punto y coma. Esto es porque al final del programa cuando dictas la ltima instruccin no hace falta separarla de ninguna otra y es posible omitir el punto y coma, sin embargo no est mal si lo colocan. Como ya habrn notado, al ir escribiendo cdigo el DE ir coloreando las palabras. Aquellas que son reservadas sern de color blanco (8riteln y readln son reservadas pero no se colorean, lo mismo suceder con otras tantas), el texto que ser impreso tal cual, o sea, el que est entre comillas simples, se ve en celeste, lo dems se ve amarillo, y as suceder con otras cosas. Los procedimientos 8rite y 8riteln imprimen informacin en pantalla, en lo que llamamos salida estndar, o sea, la salida de la lnea de comandos. Llamamos salida ya que es informacin entregada por el programa. Del mismo modo la llamaremos entrada estndar cuando sea usada para ingresar informacin al programa. Pascal no es un lenguaje que diferencie entre maysculas o minsculas en su cdigo 1uente, por lo cual escribir writeln, WRTELN, WrtElN o como sea, es exactamente igual. Lo mismo sucede con los identificadores, si ustedes llaman a su programa SALDAESTANDAR, salidaestandar, SaliDaesTandar o como sea, da exactamente lo mismo. Esto se aplica para las dems palabras reservadas, o sea que es lo mismo escribir BEGN, Begin, BeGiN o como sea. Noten que si en un texto que se imprimir en pantalla ustedes cambian las maysculas y las minsculas s se vern las diferencias. ----------------------------------------------------------------------------- Con esto terminamos la segunda leccin. Como hemos aprendido solo a mostrar texto en pantalla no tengo ejercicios que dejarles, sin embargo pueden probar a escribir programas que muestren texto en varias lneas de cdigo y de distintas maneras. Programando desde $% $D' (denti1icadoresE variables " entrada estndar* En nuestra segunda leccin vimos como mostrar mensajes en pantalla (salida estndar) mediante los procedimientos 6rite y 6riteln mostrando la diferencia entre uno y otro. Si no comprendieron eso vuelvan a la segunda leccin y practiquen o pregunten hasta que se entienda. En esta leccin hablaremos principalmente de la entrada estndar, o sea, hablaremos de cmo introducir informacin a un programa. Esto es sumamente amplio por lo cual no es posible desarrollarlo en una sola leccin, al menos no de forma que quede claro, por eso solo mostrar lo bsico primero. De este modo debo introducir un primer concepto de variables y tipos primitivos de datos, lo cual nos lleva a hablar de lo que es un identi1icador. ------------------------------------------------------------------------------------- (denti1icadores Como habrn visto hice alusin a lo que es un identi1icador cuando en nuestra segunda leccin dije que luego de la palabra reservada PROGRAM debamos colocar un nombre para nuestro programa, sin embargo no expliqu ms nada por lo cual esa idea qued en el aire. Un identificador es un nombre que nosotros asignamos a algo en nuestro programa para luego reconocerlo y hacer alusin a eso mediante dicho nombre. Por ejemplo, le daremos nombre a las variables, a los tipos, a los subprogramas, a las constantes y a alguna otra cosa ms, todo siendo visto poco a poco en el curso. 9n identi1icador puede ser cual-uier cadena de caracteres al1anumricos o de subra"ado -ue comience al menos con una letra* +o puede contener espacios ni caracteres especiales asB como tampoco puede ser igual a una palabra reservada. De este modo, identificadores vlidos pueden ser: Abuela, ABuela2, Ejemplo_de_identificador, E2B214, etc. dentificadores invlidos podran ser: 1Abuela, Abuela 2, Ejemplo de dentificador, Abk$, Variable(), pascal, var, program, etc. NOTA: No podemos repetir identificadores, o sea, no puede haber dos o ms cosas con el mismo nombre. ------------------------------------------------------------------------------------- 0ariables Cuando nosotros queremos ingresar informacin a un programa o trabajar con valores dentro de l se hace necesario poder almacenar dichos valores y obtenerlos cuando queramos. All entran en juego las variables. De forma sencilla, una variable guarda informacin de un tipo especfico permitindonos luego trabajar con dicho valor y/o modificarlo. Los tipos de datos que puede almacenar una variable existen de forma predeterminada en pascal (tipos primitivos) y constan principalmente de nmeros y caracteres. Ms adelante aprenderemos a definir nuestros propios tipos, pero para eso falta bastante. En esta leccin veremos dos tipos bsicos de datos numricos en los ejemplos, con lo cual todo esto quedar mucho ms claro. ------------------------------------------------------------------------------------- Pascal nos provee de dos tipos de datos numricos muy tiles y sencillos de usar: enteros (integer) y reales (real). Un entero, matemticamente, es cualquier nmero que no tiene cifras luego de la coma, pudiendo este ser positivo, negativo o cero. Por ejemplo: 1, 2, 3 y 4 son nmeros enteros, -1, -2, -3 y -4 tambin lo son y como ya dije el 0 tambin lo es. Un nmero real, matemticamente, es cualquier nmero existente, cualquier nmero que se nos ocurra, sea entero o no. Sin embargo en pascal hay que tener cuidado con esto, lo digo por aquellos que entienden la matemtica. Veremos que hay mucha diferencia entre trabajar con enteros que con reales en pascal. Veamos un ejemplo en el que declarar una variable de tipo entero (integer) y luego le asignar el valor 10: Cdigo: 01 PROGRAM Primera_Variable; 02 03 VAR 04 numero: integer; 05 06 BEGN 07 numero:= 10; 08 END. La primera lnea de nuestro programa es igual que siempre, la palabra PROGRAM y luego un identificador seguido de un punto y coma. Luego dejo una lnea en blanco para que quede ms prolijo y en la lnea nmero tres ven la palabra reservada 0A3. 0A3 indica que luego de all se declararn todas las variables que usar nuestro programa. Esto se hace siempre antes de comenzar con el cdigo de instrucciones, o sea, antes de la palabra reservada BEGN. En este caso concreto luego de 0A3 he declarado una variable llamada numero del tipo integer, o sea que numero almacenar valores numricos enteros. Como pueden observar all, la declaracin de una variable es as: nombreFdeFlaFvariable% tipoFdeFdatosG o sea, le damos un nombre (identificador) a la variable, luego ponemos dos puntos y finalmente indicamos el tipo de datos que almacenar esa variable. Noten que luego de la palabra VAR no va punto y coma, eso es porque VAR no es una instruccin, solo indica que luego de all declararemos las variables, igual que sucede con BEGN. Sin embargo, cada declaracin de variable s lleva punto y coma. Este programa consta de una nica instruccin que lo nico que hace es asignarle a la variable numeroel valor 10. La asignacin de valores a una variable es una operacin muy comn y se hace as: nombreFdeFlaFvariable%H valorFaFasignarG Como pueden apreciar, hemos utilizado el identificador numero para hacer alusin a nuestra variable, ya que mediante esa palabra el programa la identifica. El smbolo (%H) es el smbolo de asignacin y solo se usar para dar un valor a algo. Esto sustituye el valor anterior, o sea, sobreescribe la variable; mucho cuidado con eso, una vez modificada una variable no es posible recuperar el valor anterior. ------------------------------------------------------------------------------------ Salida 7stndar% Mostrar contenido de una variable Ahora veamos el mismo programa pero esta vez mostraremos en pantalla el valor que contiene nuestra variable: Cdigo: 01 PROGRAM Primera_Variable; 02 03 VAR 04 numero: integer; 05 06 BEGN 07 numero:= 10; 08 writeln(numero); 09 END. Este programa es idntico al anterior salvo que agregamos una instruccin. Si ponemos el nombre de una variable dentro de un procedimiento 6rite o 6riteln le estamos diciendo al programa que muestre el valor de dicha variable en pantalla. Como ven, el identificador de una variable es nuestra forma de reconocerla y hacer alusin a ella. NOTA: No es lo mismo la instruccin 6ritelnInumeroJ que 6ritelnIKnumeroKJ. Cul es la diferencia? ------------------------------------------------------------------------------------ Ahora vean el siguiente programa: Cdigo: 01 PROGRAM Primera_Variable; 02 03 VAR 04 numero: integer; 05 06 BEGN 07 numero:= 10; 08 writeln(numero); 09 numero:= -10; 10 write(numero); 11 END. Cul ser la salida de este programa? Ahora trabajemos con dos variables para ver algunos ejemplos interesantes: Cdigo: 01 PROGRAM Primera_Variable; 02 03 VAR 04 numero, numero2: integer; 05 06 BEGN 07 numero:= 10; 08 numero2:= numero + 5; 09 writeln(numero2); 10 END. En este ejemplo he declarado dos variables del tipo integer. Como pueden observar, es posible declarar varias variables de un mismo tipo en una sola sentencia, simplemente declaramos a las variables separadas por coma y luego decimos de qu tipo sern. La forma general sera variable&E variableE *** E variable+% tipoG Tambin es posible declararlas por separado, quedara as Cdigo: VAR numero: integer; numero2: integer; Observen la lnea 8 de nuestro programa: a la variable numero2 le asignamos mediante el smbolo := el valor de la variable numero ms (+) el valor 5. De este modo, numero vale 15. El smbolo + es para la suma. Es posible asignar a una variable el resultado de una operacin, sea una suma, resta, producto o divisin, incluso operaciones combinadas. Esto lo veremos a medida que trabajemos con programas ms complejos. ----------------------------------------------------------------------------------- 7ntrada estndar Veamos ahora como ingresar informacin a un programa mediante la entrada estndar. La idea es la siguiente: el usuario ingresa un valor de un tipo especfico y este se almacena en una variable. En el siguiente ejemplo el programa le pedir al usuario que ingrese su nombre y lo saluda mediante dicho nombre: Cdigo: 1 PROGRAM EjemploVariable; 2 3 Var 4 nombre: String; 5 6 BEGN 7 write('ngresa tu nombre: '); 8 readln(nombre); 9 writeln('Hola ',nombre); 10 END. Hemos comenzado como siempre escribiendo PROGRAM seguido de un identificador para nuestro programa y un punto y coma. En la tercera lnea vemos la palabra reservada H06 y luego en la lnea siguiente hemos declarado una variable llamada nombre del tipo string. A diferencia de los tipos numricos, STRNG guarda cadenas de caracteres, o sea, cualquier cosa escrita con cualquier smbolo ser aceptada. 2tring es una palabra reservada de pascal y corresponde a un tipo primitivo del mismo. Nosotros no usaremos mucho este tipo en general ya que no resulta muy til a los efectos de este curso, pero an as sirve conocerlo, y servir para dar ejemplos prcticos antes de alguna implementacin compleja de lectura de datos. En la lnea 6 indicamos el inicio del programa. En la lnea 7 usamos 8rite para imprimir un mensaje al usuario y dejar el cursor a continuacin del mensaje, ya que all se escribir el nombre. En la octava lnea utilizamos el procedimiento readln para leer informacin de la entrada estndar e indicamos entre parntesis que dicha informacin debe ser almacenada en la variable nombre (la informacin se leer al presionar enter). Siempre luego del procedimiento read o readln se especifica entre parntesis la o las variables que guardarn la informacin leda, de lo contrario, el programa no guardar ningn registro de la informacin administrada por el usuario y continuar su curso. En la novena lnea utilizamos el procedimiento 6riteln al cual le pasamos dos campos de informacin esta vez, primero el texto que debe imprimir y luego, separado por una coma, el nombre de la variable cuya informacin queremos que aparezca en pantalla. Cuando uno necesita imprimir varias cosas con un solo procedimiento 6rite o 6riteln debe separar los campos con una coma. En este caso, un campo contiene el texto y el otro la variable nombre. En este caso la variable nombre guardar la palabra que nosotros escribamos y luego ser lo que aparezca en pantalla al imprimir su contenido. Ejemplo de ejecucin: Cdigo: ngresa tu nombre: Vladimir Hola Vladimir Al igual que con 6rite y 6riteln, la diferencia entre read y readln es que la primera lee informacin de la entrada estndar y deja el cursor al final de la lnea en que la informacin fue ingresada. La segunda deja el cursor justo al inicio de la lnea siguiente. Pueden probar a escribir el programa anterior intercambiando estas funciones para ver el resultado y comprenderlo mejor. Notas: No declarar una variable luego de la palabra VAR es un error de sintaxis. No usar los dos puntos ( : ) para luego indicar el tipo de la variable es un error de sintaxis. Dos variables no pueden llamarse de la misma manera ni tampoco pueden llamarse igual que el programa, dicho de otra manera, no pueden repetirse dos identificadores, eso es un error de sintaxis. ----Todo esto ya lo dije antes, pero no est de ms repetirlo--- ----------------------------------------------------------------------------------- 9n programa ms comple,o% En el siguiente ejemplo crearemos un programa que calcule el rea de un tringulo. Para quin no lo recuerde, el rea de un tringulo se calcula multiplicando el valor de la base por el de la altura y luego dividiendo ese valor entre 2. En este aso el usuario ingresar los valores y luego el programa mostrar el resultado: Cdigo: 1 PROGRAM AraTriangulo; 2 3 Var 4 base, altura: integer; 5 area: real; 6 7 BEGN 8 Write('ngresa la base: '); 9 Readln(base); 10 Write('ngresa la altura: '); 11 Readln(altura); 12 13 area:= base*altura/2; 14 15 Writeln('El rea del tringulo es: ',area:1:2); 16 END. Este programa utiliza tres variables: base, altura y area, para calcular el rea de un tringulo. La base y la altura del mismo son ingresadas por el usuario, y el valor de area se asigna dentro del programa. Esta vez tenemos dos variables del tipo integer, o sea que almacenarn nmeros enteros y una del tipo real, o sea que almacenar nmeros reales. En la lnea 8 imprimimos una instruccin para el usuario y en la lnea 9 indicamos al programa que lea de la entrada lo que el usuario ingrese y lo guarde dentro de la variable base. En la lnea 10 imprimimos otra instruccin al usuario y en la 11 leemos un valor y lo guardamos en la variable altura. En la lnea 13 de nuestro programa le asignamos a la variable area mediante el uso del smbolo de asignacin ( := ) el valor del resultado de multiplicar el valor de base por el valor de altura y dividirlo entre 2. O sea, estamos multiplicando ambas variables ya que contienen nmeros. El smbolo para multiplicar es el asterisco ( * ) y para la di3isiIn real la barra ( / ). En la lnea 15 usamos 6riteln a la cual le pasamos dos campos de informacin, uno con el texto a imprimir y otro con la variable cuyo valor debe mostrarse con modificadores de decimales (ya explicar esto). Este programa podra haberse hecho sin la variable area y la lnea 15 quedara as *riteln JK#l rea del tringulo es: KLbaseMalturaN2:::2O- Como ven, es posible colocar expresiones en los campos de 8rite y 8riteln. Los nmeros enteros no contienen cifras despus de la coma y los reales s pueden contenerlas. La variable area es del tipo real por lo cual al imprimir su contenido este se mostrar con valores decimales y exponente en base 10. Por ejemplo si su valor es 50, se imprimir as 5.00000000000000E+001. Esto equivale a 5x10^1. Los modificadores % &% indican en su primer valor el nmero mnimo de caracteres que toleraremos en el resultado (1) y el segundo valor indica cuantas cifras luego de la coma queremos que aparezcan (2). Con esto, el valor anterior se ver como 50.00. ------------------------------------------------------------------------------------- Leer ms de una variable a la ve)% El programa anterior podra haber sido escrito de la siguiente manera: Cdigo: 1 PROGRAM AraTriangulo; 2 3 Var 4 base, altura: integer; 5 area: real; 6 7 BEGN 8 Write('ngresa base y la altura separadas por un espacio: '); 9 Readln(base,altura); 10 11 area:= base*altura/2; 12 13 Writeln('El rea del tringulo es: ',area:1:2); 14 END. Como pueden observar bsicamente es lo mismo, con la nica diferencia crucial de que esta vez, en la lnea 9, indicamos al programa mediante el procedimiento readln que lea dos variables a la vez. Esto siempre es posible. Solo deben colocarse entre los parntesis los nombres de las variables a leer separados por comas. Pueden ser variables de distinto tipo. En este caso especfico ambas son integer. Cuando se ingresen los datos para la entrada estndar deben separarse por un espacio. Si el usuario ingresa solo un dato ste se asignar a la primera variable que aparezca dentro de los parntesis y el programa quedar esperando el siguiente valor. Del mismo modo pueden imprimirse varias variables a la vez ingresando los nombres de cada variable separados por comas dentro de los parntesis de un procedimiento 8rite o 8riteln. ------------------------------------------------------------------------------------- Seguro tendrn miles de preguntas, dudas, sugerencias y dems. As que a postear. Esta leccin ha sido larga y sumamente ms compleja que las anteriores. Daremos mucho tiempo para trabajar con todo esto. Les dejo un pequeo ejercicio de aplicacin. 7,ercicio% Realicen un programa que calcule el rea y el permetro de un rectngulo. Recuerden que el rea de un rectngulo se calcula como baseLaltura y su permetro como baseLMalturaL. El programa recibir de la entrada estndar la base y la altura y mostrar como salida un mensaje con el rea y otro, debajo, con el permetro. Estos mensajes deben estar separados al menos por una lnea en blanco de los mensajes de instrucciones para el usuario. Ejemplo de ejecucin: ngrese la base: 10 ngrese la altura: 6 El rea de rectngulo es: 60 El permetro del rectngulo es: 32 Deben ser capaces de realizar este ejercicio antes de continuar. Programando desde $% $N' 7rroresE tipos primitivosE operados " algo ms*** L7CC(8+ N% En esta leccin veremos casi todas las ltimas generalidades bsicas del lenguaje y de la programacin en s abarcando varios temas. De este modo, con la siguiente leccin a esta cerraremos lo que sera un cap!tulo del curso para posteriormente comenzar con el segundo en el cual nuestros programas se volvern bastante ms complejos y comenzarn los dolores de cabeza, pero todava falta un poquito. Como dato les cuento que este curso consta de seis capBtulos, algn que otro proyecto intermedio, y dos pro"ectos 1inales muy complejos, cada uno de los cuales les plantear hacer un pequeo juego. Esta leccin ser larga y les dar bastante que hacer. ------------------------------------------------------------------------------------- (ntroduccin 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 nmero entero N puede ser guardado en una variable del tipo real ya que automticamente el compilador transforma el entero N en el real N*$. Esto es totalmente posible porque el entero N y el real N*$ siguen siendo exactamente el mismo valor. A la inversa no es posible porque un real, por ejemplo, &* no puede ser pasado a entero sin modificar su valor, ya sea truncndolo (dejndolo en 1) o redondendolo de alguna manera. De este modo se pierde informacin y no existe un traspaso de real a integer automtico. En sus programas, si ustedes intentan ingresar un valor real, por ejemplo O*, vern 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 habra problema, si ustedes declaran todas sus variables como real e ingresan en la entrada estndar un valor integer pues no habr problema porque como ya dije, la conversin de integer a real es automtica y no afecta en nada los valores. Ahora, qu pasa si en la entrada de nuestros programas de clculo de rea y permetro el usuario ingresa una letra o una palabra? El programa se caer inevitablemente. Obviamente no existe compatibilidad entre tipos numricos y tipos de caracteres. Un buen programa debera, 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 captulo de nuestro curso, an 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 quin ingresa los datos y pues el sistema cae. Sin embargo, existen errores s predecibles por el compilador y que se nos advertirn al intentar compilar: Supongan que la variable area de mi programa del tringulo es del tipo integer, o sea que mi declaracin fue as: Cdigo: Var base, altura, area: integer; Al intentar compilar nuestro programa tendramos un error que nos sealara esta lnea: Cdigo: area:= base*altura/2; Por qu? Como dije antes, la operacin de divisin (P) representa la divisin real y devuelve como valor un nmero real. Por ejemplo, si altura vale D y base vale Q la operacin baseLalturaP da como resultado &$*O, lo cual es un real. Ahora, si base vale y altura vale D el resultado de baseLalturaP da D, pero como P devuelve un real en realidad el D es D*$. Como ven, la operacin P siempre devuelve un real sin importar los operandos. Al intentar asignar un valor involucrado con P 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: Cdigo: Var numero: real; palabra: string; maginen esta asignacin: Cdigo: numero:= palabra; Claramente hay una incompatibilidad de tipos, ya que estamos intentando asignar un valor 2tring a un 6eal. El compilador se dar cuenta y nos regaar. Sin embargo, si intentan asignar una variable entera a una real no habr regao, eso ya lo expliqu. Para sus programas anteriores, lo mejor sera declarar todas las variables del tipo real, lo cual solucionara los posibles problemas de incompatibilidad de nmeros, sin embargo, si nuestros usuarios ingresan otra cosa que no sean nmeros 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 ms difciles ya que es fcil que se nos pase por alto algn caso, y ms an cuando nuestro programa es muy complejo. A medida que avancemos veremos cmo enfrentar estas situaciones, o sea, como hacer que nuestros programas sepan qu esperar y qu mostrar en caso de que lo ingresado sea incorrecto. ------------------------------------------------------------------------------------ 7rrores en :iempo de 7,ecucin " errores en :iempo de Compilacin% Luego de escribir el cdigo 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 compilacin. 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 compilaciIn el compilador se detiene y nos indica el lugar donde encontr el error proporcionndonos adems alguna informacin acerca de por qu se produjo. Estos son los errores ms fciles 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 e,ecucin. Los errores en tiempo de ejecuciIn provocan que el programa se cuelgue, termine inesperadamente perdindose toda la informacin que tenamos o que muestre resultados inesperados. Estos errores son los menos deseados y los ms difciles de detectar ya que se deben a errores en nuestras instrucciones al programa, generalmente conocidos como errores lgicos. Con los ejemplos de hace un momento, nuestros programas sufriran errores en tiempo de ejecucin si el usuario ingresa valores inesperados en la entrada, sin embargo, puede suceder que el usuario haga todo bien y el programa an no funcione. Veamos un ejemplo sencillo, un programa que divide dos nmeros: Cdigo: 1 PROGRAM dividir; 2 3 Var 4 a, b: real; 5 6 BEGN 7 Write('ngrese un nmero: '); 8 Readln(a); 9 Write('ngresa otro nmero: '); 10 Readln(b); 11 12 Wtieln('El resultado de la divisin es: ',a/b:1:2); 13 END. Supongamos que sabemos que nuestros usuarios solo ingresarn nmeros a nuestro programa, o sea que no habr problemas con los tipos de datos. Cul sera el problema entonces? Si ustedes escriben ese cdigo e intentan compilarlo vern que funciona perfectamente. Si asumimos que solo se ingresan nmeros entonces no habra error posible, pero s lo hay. Antes de continuar, quiero que todos ustedes compilen y prueben ese programa, prubenlo muchas veces con valores diferentes, positivos y negativos a ver si son capaces de descubrir el problema. Luego continen leyendo ya que lo explicar aqu. Pues bien. Ese cdigo no tiene errores y el programa en s tampoco. En realidad, si asumimos que solo se ingresarn nmeros en la entrada estndar, de los infinitos casos de divisiones posibles existe solo una que es problemtica: Da di3isiIn entre 9. Qu pasa si el usuario ingresa como segundo valor el nmero 0? Supongan el siguiente ejemplo de ejecucin: Cdigo: ngrese un nmero: 5 ngrese otro nmero: 0 Qu debera mostrar nuestro programa? Al llegar a la lnea 12 he intentar la divisin de aPb, o sea OP$, no podr ya que la divisin entre 0 no est definida matemticamente y el programa producir un error y se terminar su ejecucin. Lo correcto sera 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 segn las condiciones que se dan. 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 mximo esto, existiendo equipos de trabajo solo encargados al test de programas (testing). ------------------------------------------------------------------------------------- Palabras reservadas% Las palabras reservadas por Pascal son aquellas que indican alguna funcin especfica del lenguaje, como por ejemplo, 6rite indica que algo se desplegar en pantalla y readln que el usuario ingresar alguna informacin. Que una palabra sea reservada indica que esta no puede utilizarse como identificador, o sea, uno no puede crear un programa llamado Criteln o 0ar, o una variable llamada 3eadln. 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 compilacin. He aqu una lista de casi todas las palabras reservadas en pascal, muchas de las cuales no tocaremos en este curso: ------------------------------------------------------------------------------------ :ipos de datos% Tipos Ordinales: Son aquellos que, dado un elemento, podemos saber cual es el siguiente y/o el anterior adems de que poseen una cantidad finita de elementos, o sea, hay uno que es el primero y por ende no tiene predecesor, y uno que es el ltimo y por ende no tiene sucesor. Por ejemplo dado un nmero entero sabemos que el siguiente es ese nmero ms 1 y el anterior es el nmero menos 1. Dado el 5 su predecesor es el 4 y su sucesor es el 6. (nteger --- Nmeros enteros, sin ninguna cifra decimal. C#ar --- Caracteres. 2oolean --- Valores lgicos, pueden valer Prue o False. 7numerados --- Definido por el programador. Subrango --- Definido por el programador. Todos ellos los veremos a medida que avancemos, no se preocupen. Para estos tipos llamados Ordinales tenemos tres funciones predefinidas por Pascal que suelen ser tiles: PredIvalorFdeFtipoFordinalJ---> Devuelve el predecesor para cualquier valor de tipo ordinal excepto si ste es el primero de todos. En este caso tenemos un error en tiempo de ejecucin. SuccIvalorFdeFtipoFordinalJ---> Devuelve el sucesor para cualquier valor de tipo ordinal excepto si ste es el ltimo de todos. En este caso tenemos un error en tiempo de ejecucin. 5rdIvalorFdeFtipoFordinalJ---> Devuelve el ordinal para cualquier valor de tipo ordinal. Ya hablaremos de esto ms tarde, al igual que de las dos funciones anteriores. ---------------------------- Tipos Reales: Solo tenemos el tipo real para esta categora. Las funciones anteriores no funcionan con valores de tipo real ya que es imposible saber, dado un real, cual es su sucesor o su predecesor. Por ejemplo, dado el 1.5 quin le sigue? quin est detrs? ----------------------------- Tipos Estructurados: Forman estructuras de datos, en general, bastante complejas. String --- Cadena de caracteres. Arra" --- Tablas de datos (String es un array de caracteres). 3ecord --- Registros de datos. .ile --- Secuencias de datos (No trabajaremos con este tipo). Set --- Conjuntos de datos (No trabajaremos con este tipo). ------------------------ Tipo Punteros: Hablaremos de ellos al final de este curso. Notas: El mayor entero posible es identificado por la palabra reservada MAXNT, la cual es una constante (hablaremos de estas ms adelante). Esos son todos los tipos existentes, ustedes solo han trabajado con tres de ellos, pero pronto veremos ms, y al final los habrn visto todos excepto set y 1ile. Existen ms tipos pero no nos importan en absoluto. ------------------------------------------------------------------------------------- 5peradores en pascal% Veamos los operadores aritmticos de Pascal, los cuales son usados para crear expresiones matemticas y realizar clculos, ustedes han visto algunos ya: ------------------------------------------------------------------------------------- Precedencia de operadores% Dada una expresin matemtica donde se combinen varios de estos operadores, al igual que en el lgebra comn, se realizarn primero los productos ( * ), las divisiones (div), (mod) y ( / ) y luego las sumas ( + ) y restas ( - ). Para quebrar esta precedencia de quin va primero que quin, se utilizan los parntesis. Ejemplo: AM2LC En este caso aparece primero la suma (+) y luego un producto (*). Sin embargo el producto tiene precedencia ante la suma y se evaluar primero 2LC para luego sumar ese resultado con A. Si se quisiera realizar primero la suma habra que utilizar parntesis y escribir aquella expresin como IAM2JLC. Ahora s se realizar primero la suma y luego el producto ya que los parntesis tienen la precedencia absoluta excepto si existen funciones que deben evaluarse entro. Si se llevan bien con las matemticas esto no supone novedad alguna. -------------------------------------------------------------------------------- .unciones matemticas de pascal% Pascal nos provee de varias funciones matemticas predefinidas para realizar algunos clculos comunes. En los siguientes ejemplos la letra / simbolizar un nmero o e/presin del tipo adecuado para la funcin en cuestin: o ABS(x) Calcula el valor absoluto de X. X debe ser integer o real. El resultado es del mismo tipo que X. o SQR(x) Calcula el cuadrado de X. X debe ser integer o real. El resultado es del mismo tipo que X. o SQRT(x) Calcula la raz cuadrada de X siendo X un real o entero mayor o igual que 0. El resultado es un del tipo real. o SN(x) Calcula el seno de X expresado en radianes. X debe ser integer o real. El resultado es del tipo real. o ARCTAN(x) Calcula el arco tangente de X. X debe ser integer o real. El resultado es del tipo real. o EXP(x) Calcula la exponencial de X (ex donde e= 2.7182818.). X debe ser integer o real. El resultado es del tipo real. o LN(x) Calcula el logaritmo neperiano (base e) de X siendo X mayor que cero. X debe ser integer o real. El resultado es del tipo real. o TRUNC(x) Suprime la parte decimal de X dejando solo el valor anterior a la coma. X debe ser real. El resultado es del tipo integer. o ROUND(x) Redondea el valor de X al entero ms prximo. X debe ser real. El resultado es del tipo integer. o ORD(x) Obtiene el nmero de orden de X dentro de un conjunto de valores definidos por su tipo. X debe ser de un tipo ordinal. El resultado es de tipo integer. o CHR(x) Devuelve el caracter cuyo nmero ordinal es X. El tipo de X debe ser integer. El resultado es de tipo char. ------------------------------------------------------------------------------------- 9n e,emplo del uso de ?(0 " M5?* (ntroduccin a los comentarios% Se nos plantea el siguiente problema. Dado un nmero entero de cuatro cifras que ser ledo desde la entrada estndar se nos pide que hagamos la suma de sus cifras. Por ejemplo, si el usuario ingresa el nmero ORNS el programa debe realizar la suma de OMRMNMS y mostrar el resultado. Se asume que el usuario ingresar efectivamente un nmero de cuatro cifras. Esto es complicado, as que preste atencin a toda la descripcin y pregunten todo lo que haga falta. Cdigo: 1 {El siguiente programa desglosar un nmero de cuatro cifras 2 en sus cuatro nmeros distintos, uno por cada cifra y realizar 3 la suma entre ellas} 4 PROGRAM SumaCifras; 5 6 Var 7 numero: integer; //El valor que ser ledo. 8 c1, c2, c3, c4: integer;//Una variable para cada cifra. 9 10 BEGN 11 write('ngresa un nmero de cuatro cifras: '); 12 readln(numero); //Leemos el nmero de 4 cifras. 13 14 (*Asignamos a cada variable el valor de la cifra que le corresponde*) 15 c1:= numero mod 10; 16 c2:= (numero mod 100) div 10; 17 c3:= (numero mod 1000) div 100; 18 c4:= numero div 1000; 19 20 //Mostramos el resultado al usuario. 21 write('El resultado de sumar ',c4,'+',c3,'+',c2,'+',c1,' es: ',c1+c2+c3+c4); 22 END. Este es nuestro primer programa en el que vemos el uso de comentarios. Los comentarios son anotaciones hechas por el propio programador para ir explicando lo que se va realizando en su cdigo. Esto es debido a que normalmente el software se desarrolla en equipo y resulta imprescindible que otros lean el cdigo que uno escribe y sean capaces de entenderlo. Los comentarios son omitidos por el compilador por lo cual no afectan en absoluto al funcionamiento del programa, solo son una documentacin explicativa. Existen dos tipos de comentarios, los comentarios multilBnea y los comentarios de 1in de lBnea. Los primeros pueden abrirse con T y cerrarse con U tal como se ve en las primeras tres lneas de nuestro programa, o abrirse con IL y cerrarse con LJ tal como se ve en la lnea 14 de nuestro programa. Un comentario multilnea puede ocupar una o ms lneas de cdigo, tantas como sea necesario. Los comentarios de fin de lnea se abren con PP y no requieren ningn smbolo de cierre ya que, como su nombre lo indica, finalizan al terminar la lnea en que aparecen. Podemos verlos en las lneas 7, 8, 12 y 20 de nuestro ejemplo. En el DE se vern de color gris. Como ya dije, todo lo que est en un comentario se omite por el compilador, por lo tanto puede escribir lo que se les antoje all, incluso palabras reservadas e identificadores. Ahora miremos un poco la lgica de nuestro programa, como usando mod y div solamente, puede desglosarse un nmero en sus respectivas cifras. En la lnea 12 leemos de la entrada estndar un valor y lo guardamos dentro de numero. Luego, en la lnea 15, mediante el smbolo de asignacin %H le damos a c& el valor de la primera cifra de nuestro nmero. Fjense que si uno tiene un nmero de ms de una cifra y lo divide entre 10, el resto de esa divisin ser la primera cifra si leemos de derecha a izquierda. Teniendo por ejemplo el 1456, si dividimos ese nmero entre 10 (divisin entera, sin llevarlo a decimales) obtenemos como resto el 6 y como resultado el 145. En la lnea 13 obtenemos el resto de dividir nuestro nmero entre 100, eso da como resultado el entero formado por las dos primeras cifras (de derecha a izquierda) y luego (notar que esta operacin est entre parntesis para que se realice primero) mediante div obtenemos el cociente de dividir ese nmero entre 10. Por ejemplo, si tenemos 1456 y lo dividimos entre 100, el resultado es 14 y el resto 56. Teniendo el resto, al dividirlo entre 10 tenemos como resultado el 5 y como resto el 6. De este modo en las lneas 17 y 18 obtenemos las ltimas dos cifras de nuestro nmero. Ahora las variables c1, c2, c3 y c4 contienen cada una los valores de una cifra de nuestro valor inicial. En la lnea nmero 21 mostramos mediante el procedimiento 6rite los resultados de nuestro programa. ----------------------------------------------------------------------------------- 7,ercicios% Les dejo un enlace a ejercicios de aplicacin de todo lo que hemos visto hasta ahora, tanto en esta leccin como en las anteriores. Hganlos todos. El nmero 14 puede ser complicado por lo que pueden omitirlo. Este link los lleva a la pgina de la Facultad de ngeniera de mi pas, por lo tanto los ejercicios all propuestos son pensados por profesores reales enfocados a una programacin poderosa. Dicho enlace est autorizado por nuestro administrador :esis, gracias a quin este curso es posible ya que me ha dado todo su apoyo. HAGAN CLC AQU PARA ACCEDER Tendrn mucho trabajo. Esta leccin les traer dudas y muchsimas preguntas. Trabajen tambin con las anteriores. Estaremos un tiempo con esto, hasta que logren hacer los ejercicios planteados Programando desde $% $O' ConstantesE booleanos e introduccin a la seleccin* L7CC(8+ O% ConstantesE booleanosE seleccin simple En esta leccin terminaremos con los aspectos bsicos del lenguaje, tales como lo han sido la salida y la entrada estndar. Veremos entonces lo que son las constantes y una descripcin un poco superflua de lo que es el tipo boolean y las expresiones boolean, ya que sern esenciales para el resto del curso. Luego de eso comenzaremos con lo que sera ya el segundo captulo: S7L7CC(8+ V 37P7:(C(8+, aunque en esta leccin solo veremos la seleccin bsica. Comencemos entonces. ------------------------------------------------------------------------------------- (ntroduccin a las constantes% Al igual que podemos definirnos variables, que son objetos cuyos valores van cambiando (variando) a lo largo del programa, tambin podemos definirnos constantes, que sern objetos cuyo valor no cambiar nunca a lo largo del programa. Veremos un ejemplo en el cual intentar hacerles entender la necesidad de las constantes. El siguiente programa pedir como entrada en reales el precio sin VA de cinco productos que estn a la venta en un almacn. Luego mostrar el precio de dichos productos con el VA agregado. Para quienes no lo saben, el VA es un porcentaje que se agrega al precio de los productos que compramos. Ese porcentaje es propio de cada pas. Por ejemplo, en mi pas el VA es un 23%, por lo tanto los comercios le agregan ese porcentaje al precio de cada producto y el total es lo que pagamos al comprarlo. Para que quede bien claro: supongan que un comercio obtiene cierto producto P a W&$$. El 23% de 100 es 23, por lo tanto nosotros compraremos el producto P a W&D. Veamos el programa entonces: Cdigo: 1 PROGRAM preciosVA; 2 3 Const 4 iva= 23; 5 6 Var 7 harina, leche, azucar, sal, arroz: real;//Precios de los productos. 8 porcentaje: real; //Para calcular cuanto se debe sumar al precio. 9 10 BEGN 11 12 //Mostramos mensajes al usuario y leemos los datos desde la entrada. 13 write('Precio HARNA : '); 14 readln(harina); 15 write('Precio LECHE : '); 16 readln(leche); 17 write('Precio AZUCAR : '); 18 readln(azucar); 19 write('Precio SAL : '); 20 readln(sal); 21 write('Presto ARRZ : '); 22 readln(arroz); 23 24 //Dejamos una lnea en blanco. 25 writeln; 26 27 //Calculamos el porcentaje de VA para harina. 28 porcentaje:= harina*iva/100; 29 //Mostramos el nuevo precio al usuario. 30 writeln('HARNA + VA : ',harina+porcentaje:2:2); 31 32 //Calculamos el porcentaje de VA para leche. 33 porcentaje:= leche*iva/100; 34 //Mostramos el nuevo precio al usuario. 35 writeln('LECHE + VA : ',leche+porcentaje:2:2); 36 37 //Calculamos el porcentaje de VA para azucar. 38 porcentaje:= azucar*iva/100; 39 //Mostramos el nuevo precio al usuario. 40 writeln('AZUCAR + VA : ',azucar+porcentaje:2:2); 41 42 //Calculamos el porcentaje de VA para sal. 43 porcentaje:= sal*iva/100; 44 //Mostramos el nuevo precio al usuario. 45 writeln('SAL + VA : ',sal+porcentaje:2:2); 46 47 //Calculamos el porcentaje de VA para arroz. 48 porcentaje:= arroz*iva/100; 49 //Mostramos el nuevo precio al usuario. 50 writeln('ARROZ + VA : ',arroz+porcentaje:2:2); 51 END. Bien, en la lnea 3 vemos la palabra reservada const, que indica que desde all se declararn constantes. La sintaxis para declaracin de constantes es +ombre?eLaConstanteH valorG donde valor representa un valor de algn tipo primitivo de pascal (integer, real, char, string entre algn otro). El nombre de la constante es un identi1icador. En este caso, en la lnea 4 del programa hemos declarado la constante iva y le hemos dado el valor D, que representa el 23% que vale el VA en mi pas. +otar -ue las constantes se declaran antes -ue las variables* A una constante no debemos declararle un tipo ya que este est implcito en el valor asignado a la misma. En este ejemplo le hemos dado a iva el valor D que es un entero, entonces iva es del tipo integer. Luego, en las lneas 7 y 8 declaramos las variables del programa, una para el precio de cada producto y una para calcular el porcentaje de VA que le corresponde al precio de cada producto para luego sumrselo al mismo. En las lneas 13 a 22 inclusive, mostramos mensajes al usuario y leemos los valores de las entradas para cada producto. Luego, en la lnea 25 indicamos mediante el procedimiento 6riteln que queremos dejar una lnea en blanco. Esto se hace llamando al procedimiento sin pasarle campos entre parntesis. Las soluciones a esto que haban dado antes ustedes constaban de escribir 6ritelnIK KJ, o sea, escribir un espacio y luego bajar de rengln. Eso es una solucin ficticia al problema de escribir una lnea en blanco. Pascal admite que escribamos el procedimiento 6ritelnG sin parntesis y dejar una lnea en blanco. Otra forma es escribir 6ritelnIJG sin pasarle campos entre los parntesis. En la lnea 28 calculamos el porcentaje de VA para la harina asignando este valor a la variable porcenta,e. Esta operacin es simple. Si uno tiene un valor y quiere saber un porcentaje de ese valor simplemente multiplica dicho valor por el porcentaje que quiere obtener y divide el resultado entre 100. Por ejemplo, si tenemos el nmero QS y queremos saber el &OX de ese nmero simplemente realizamos la operacin QSL&OP&$$ lo cual nos dara N&EQ. Ese valor corresponde al &OX de QS. De este modo calculamos el porcentaje de VA para cada producto multiplicando su precio por el valor de la constante iva y dividiendo entre 100. En la lnea 30 mostramos un mensaje al usuario y el precio de la harina ms el porcentaje de VA del mismo, en este caso ms un 23%. Repetimos esto hasta el final de la aplicacin. Notar que siempre usamos la variable porcenta,e para calcular el 23% de cada precio. El smbolo de asignacin ( := ) borra el contenido anterior de la variable y asigna el nuevo, o sea, la sobrescribe (ya lo dije en lecciones anteriores). Ahora veamos el mismo programa pero sin el uso de la constante iva: Cdigo: 1 PROGRAM preciosVA; 2 3 Var 4 harina, leche, azucar, sal, arroz: real;//Precios de los productos. 5 porcentaje: real; //Para calcular cuanto se debe sumar al precio. 6 7 BEGN 8 9 //Mostramos mensajes al usuario y leemos los datos desde la entrada. 10 write('Precio HARNA : '); 11 readln(harina); 12 write('Precio LECHE : '); 13 readln(leche); 14 write('Precio AZUCAR : '); 15 readln(azucar); 16 write('Precio SAL : '); 17 readln(sal); 18 write('Precio ARRZ : '); 19 readln(arroz); 20 21 //Dejamos una lnea en blanco. 22 writeln; 23 24 //Calculamos el porcentaje de VA para harina. 25 porcentaje:= harina*23/100; 26 //Mostramos el nuevo precio al usuario. 27 writeln('HARNA + VA : ',harina+porcentaje:2:2); 28 29 //Calculamos el porcentaje de VA para leche. 30 porcentaje:= leche*23/100; 31 //Mostramos el nuevo precio al usuario. 32 writeln('LECHE + VA : ',leche+porcentaje:2:2); 33 34 //Calculamos el porcentaje de VA para azucar. 35 porcentaje:= azucar*23/100; 36 //Mostramos el nuevo precio al usuario. 37 writeln('AZUCAR + VA : ',azucar+porcentaje:2:2); 38 39 //Calculamos el porcentaje de VA para sal. 40 porcentaje:= sal*23/100; 41 //Mostramos el nuevo precio al usuario. 42 writeln('SAL + VA : ',sal+porcentaje:2:2); 43 44 //Calculamos el porcentaje de VA para arroz. 45 porcentaje:= arroz*23/100; 46 //Mostramos el nuevo precio al usuario. 47 writeln('ARROZ + VA : ',arroz+porcentaje:2:2); 48 END. Esta versin funciona exactamente igual a la anterior, con la diferencia de que en el cdigo, donde antes tenamos el identificador iva ahora hay un 23. Ahora imaginen la siguiente situacin: el valor de VA cambia en un momento dado y se les pide que reestructuren su programa para el nuevo valor de VA. Si ustedes hicieron su programa tal como esta ltima versin debern buscar en su cdigo cada una de las veces en que usaron el 23 para calcular el porcentaje de VA y cambiarlo por el nuevo valor, mientras que en la versin con constante solo es ir a donde est declarada iva y modificar ah su valor con lo cual no sera necesario tocar ms nada del cdigo. Esta accin puede realizarla hasta alguien que no haya sido el propio programador, mientras que en el cdigo sin constante, si uno no fue quien program deber primero sentarse a leer y entender el cdigo hasta que pueda efectivamente hacer una bsqueda de los lugares donde se realiz el clculo del VA para poder modificarlos. En este ejemplo no resulta difcil modificar todos los 23 que hay, pero imaginen una base de datos de un supermercado en el cual hay miles de productos y precios diferentes. Sera mejor buscar y cambiar todos y cada uno de los valores en que usamos el 23, o sera mejor declarar una constante y solo cambiar un 23? Normalmente los cdigos son muy extensos y complicados, por lo cual una tarea de revisin total y bsqueda exhaustiva sera muy tediosa y difcil, adems de que es muy probable que se nos pase por alto alguna expresin a modificar. El uso de constantes es muy recomendable cuando se va a usar un mismo valor muchas veces. Nota: No puede usarse una constante a la izquierda de una asignacin. Por ejemplo sera errneo escribir iva%H &$ ya que iva no puede ser modificada. Esto es un error de sintaxis. --------------------------- Para terminar de comprender esto, podemos declarar constantes de cualquier tipo primitivo de pascal: Cdigo: Const letra= 'a'; palabra= 'Hola'; entero= 5; unReal= 4.5; booleano= true; La constante letra es del tipo c#ar (an no hemos trabajado con l) pero simplemente un valor c,ar es un caracter, en este ejemplo la letra a minscula. Vean que est entre comillas. La constante palabra es del tipo string porque contiene una cadena de caracteres. Si algo contiene ms de un caracter pasa de ser c#ar a ser string. La constante entero pues contienen el valor integer O, un3eal contienen el valor real N*O. Finalmente la variable booleano contiene el valor true. An no hemos hablado mucho del tipo boolean, pero vayan teniendo en mente que sus dos nicos valores son true o 1alse. ------------------------------------------------------------------------------------- 2ooleanos% El tipo boolean resulta muy extrao al principio. Solo contiene dos valores posibles: :rue y .alse. O sea, una variable del tipo boolean solo puede ser verdadera o falsa. Aunque en principio uno no puede imaginarse para qu puede servir una variable de este tipo, realmente resultarn muy tiles ms adelante, cuando tengamos que comenzar a darle condiciones a nuestro programa para que tome distintos caminos de ejecucin. No es posible hacer 6rite ni read de una variable boolean, esto incluye tambin a readln y 6riteln. Boolean tambin puede ser cualquier expresin que pueda ser verdadera o falsa. Por ejemplo: OY&$ ---> Esa expresin es verdadera, claramente 5 es menor que 10. OZ&$ ---> Es expresin es falsa, claramente 5 no es mayor que 10. Ms adelante veremos como utilizar este tipo de cosas. Vern como las expresiones booleanas se converitrn en los puntos principales de sus programas ya que mediante dichas expresiones ustedes le dirn a sus programas qu camino acciones tomar. --------------------------------------------------------------------------------- Algunas notas generales: El punto y coma acta como separador. Nosotros acostumbramos a escribir una instruccin por lnea por una cuestin de legibilidad del cdigo, sin embargo al compilador eso no le importa al igual que tampoco la sangra (indentacin) que dejemos. De este modo resultar lo mismo escribir Cdigo: Writeln('Hola mundo'); Readln(variable); que escribir Cdigo: writeln('Hola mundo'); readln(variable); Algo ms que se me pas por alto al momento de hablar de la entrada estndar, simplemente porque jams lo uso, es que ustedes pueden agregar, al igual que para los reales, un modificador de escritura para los strings. Por ejemplo: Cdigo: writeln('Hola':10) Como ven, he agregado un %&$ al final de la cadena. Esto indica que quiero que el ltimo caracter de la cadena ocupe la dcima columna de la salida, o sea, que la ltima letra ocupe el dcimo espacio de la pantalla. De este modo, el programa correr toda la palabra K>olaK para que eso pase. Si yo escribo 6ritelnIK>olaK%OJ vern que la palabra >ola parece un lugar ms adelante de lo que debera, eso es para que la a ocupe el espacio 5 de la salida. Sin embargo, si escribo 6ritelnIK>olaK%J no pasar nada, porque no hay modo de hacer que la ltima letra de mi palabra ocupe el segundo espacio de la salida, para eso debera recortar la palabra y pues, no se admite. Esto no dar error ninguno, simplemente no pasar nada al ejecutar el programa, se mostrar el string >ola como de costumbre y listo. Les hago esta aclaracin porque aparece en los siguientes ejercicios. Ahora, antes de continuar hagan los ejercicios que tenan que ver con constantes. Luego entren en este enlace, vern all un nuevo listado de ejercicios interactivos. ------------------------------------------------------------------------------------ S7L7CC(8+ 2[S(CA% 9na breve rese\a de la instruccin (.***:>7+% En la siguiente seccin del tutorial (y apenas en esta) aprenderemos a usar secuencias de seleccin para indicarle al programa qu camino ha de tomar en funcin de ciertas condiciones dadas as como tambin aprenderemos secuencias de repeticin para indicarle al programa que debe volver a ejecutar cierto fragmento de cdigo una cantidad de veces dada, o no. Es aqu donde la programacin comienza a complicarse un poco y comenzamos a tener verdaderos dolores de cabeza cuando nuestros programas no hacen lo que nosotros queremos. Es muy comn que, en las secuencias de repeticin, nunca se den las condiciones necesarias para finalizar la repeticin y nuestro programa entre en un bucle in1inito (conocido como loop) y quede colgado realizando la misma tarea hasta que nosotros lo cerremos o se bloquee el sistema. Tambin es muy comn que olvidemos alguna condicin necesaria para que el programa tome un camino especfico y por lo tanto funcione errneamente, o que ni se nos haya cruzado por la cabeza que el usuario podra haber ingresado tal o cual instruccin y esto genere muchos errores en la ejecucin de nuestro programa. Por estos motivos es que cuando uno crea un programa debe probarlo con la peor intencin posible para detectar la mayora de los errores que puedan aparecer. Dedicar una seccin entera para hablar de la prueba de programas. El ambiente de desarrollo DE de Free Pascal tiene incluido un depurador (debugger). Esta es una herramienta que nos permitir ver la ejecucin de nuestro programa paso a paso y visualizar en una pequea ventana los valores que nuestras variables van tomando para as, poder detectar errores que de otro modo seran imperceptibles. Aprenderemos a usar esta herramienta ms adelante, ser muy importante. ------------------------------------------------------------------------------------- Seleccin* (nstruccin (.]:>7+ e (.]:>7+]7LS7% Como ya hemos visto que se vuelve necesario tomar distintos caminos segn lo requieran las circunstancias. Por ejemplo, en nuestro programa que divida dos cifras haca falta mostrar un mensaje de error al usuario en caso de que este ingresara como segundo valor un $ ya que esto causara un error en tiempo de ejecucin, y en caso contrario simplemente mostrar el resultado de la divisin. Aqu entra en juego la instruccin de seleccin i1]t#en que en ingls significa (si.entonces). Su sintaxis es la siguiente: Cdigo: f condicin then nstruccin; Ahora solo les dar una simple resea, en la prxima leccin la ampliar muchsimo ms, o sea, la veremos por completo. Veamos un pequeo programa que lea un nmero de la entrada estndar y nos diga si dicho nmero es mayor que 50: Cdigo: 1 program Resenaf; 2 3 var 4 numero: real; 5 6 begin 7 write('ngresa un nmero: '); 8 readln(numero); 9 10 f numero>50 then 11 writeln('Es mayor que 50.'); 12 13 end. Bien, este programa no supone ninguna dificultad. Lo nuevo est en la instruccin F. Leemos un nmero de la entrada estndar y luego, en la lnea 10 tenemos Cdigo: f numero>50 then eso significa: Si numero es ma"or -ue O$ entonces. Como ven, he colocado una expresin booleana en la condicin del F. Esto siempre ser as, las condiciones siempre son booleanas, o sea, o se cumplen o no se cumplen. La lnea 11 de nuestro programa es parte del F, por tanto, se ejecutar s y solo s la condicin del F es verdadera (TRUE), en caso contrario ser omitida por completo. Lo que hace el programa en estos casos es evaluar la condicin dada y se fija si es TRUE o FALSE. Si es TRUE entonces ejecuta la instruccin del F. En este caso esa condicin es verdadera si el nmero ingresado es etrictamente mayor a 50; si no es as, la condicin es falsa y por lo tanto la lnea 11 no se ejecuta. Algo a notar es que luego del :>7+ no va un punto y coma (G), esto es porque (. condicin :>7+ no es una instruccin completa, o sea, lo que yo escrib de esta manera Cdigo: f numero>50 then writeln('Es mayor que 50.'); en realidad para el compilador es Cdigo: f numero>50 then writeln('Es mayor que 50.'); por eso el punto y coma va al final de la instruccin 6riteln. Se suele escribir tal como yo lo hice por una cuestin de legibilidad, ya que ms adelante veremos como ejecutar muchas instrucciones luego de un (.***:>7+ y no solo una como en este caso. Por eso, como dije, el punto y coma es el separador (;) y no los saltos de lnea (ENTER). Por ejemplo, si tenemos una variable a del tipo integer, esta asignacin Cdigo: a:= 1 + 3; es lo mismo que escribir Cdigo: a:= 1 + 3; o escribir Cdigo: a:= 1 + 3; o escribir Cdigo: a:= 1 + 3 ; Del mismo modo es lo mismo escribir Cdigo: writeln('Hola mundo'); que escribir Cdigo: writeln( 'Hola mundo'); o Cdigo: writeln ( 'hola mundo' ) ; Separador significa eso, finalizar una instruccin. El compilador buscar el punto y coma y est donde est para decirse a s mismo "Ah, aqu termina esta instruccin", omitiendo por completo todos nuestros espacios y saltos de lnea. Si quisieramos podemos escribir todo el cdigo en una sola lnea largusima que funcionar igualmente, solo que ser horrible para leer. Bien, terminemos con esto de las condiciones viendo unos pequeos ejemplos que pueden aplicarse a variables numricas: Si tenemos un nmero A y un nmero B, podemos preguntar si: A es mayor que B mediante AZ2. A es menor que B mediante AY2. A es igual que B mediante AH2. A es distinto de B mediante AYZ2. A es mayor o igual que B mediante AZH2. A es menor o igual que B mediante AYH2. Con esto an no pueden solucionar el problema de nuestro programa de divisin, pero es una simple muestra como incentivo. Programando desde $% $R' Condiciones booleanas " seleccin* L7CC(8+ R% Condiciones booleanas " Seleccin Ya tuvimos un vistazo de esto en la leccin anterior. Ahora volveremos a retomar el mismo tema. Comenzaremos a ver la instruccin F...THEN tal como ya lo hicimos, la cual sirve para elegir un camino en caso de que una condicin sea verdadera. Luego veremos como utilizar la instruccin F...THEN...ELSE que sirve para tomar un camino en caso de que una condicin sea verdadera u otro en caso contrario. Trabajaremos con la anidacin de estas instrucciones, o sea, con la composicin de las mismas. Esto es, usar varias instrucciones F juntas, para finalmente ver la instruccin CASE...ELSE que sirve para tomar distintos caminos segn las condiciones dadas. De este modo nuestros programas podrn hacer una cosa u otra, abriendo un abanico de posibilidades nuevas. Sin embargo, an estaremos muy limitados porque nos hace falta la repeticin, tema que se vendr en la leccin siguiente a esta. ---------------------------------------------------------------------------------- (nstruccin (.***:>7+% Vimos en la leccin anterior que la sintaxis genrica de esta instruccin es Cdigo: f condicion then instruccion; Vimos adems que la condicin es algo del tipo 2552L7A+, o sea, algo que puede ser verdadero o falso (TRUE, FALSE). Estas condiciones se vern generalmente con comparaciones tales como las que ejemplifiqu en la leccin anterior. Sin embargo, dichas pueden no ser numricas, o sea, est bien comparar si un numero es mayor que otro, menor o igual, pero podemos hacer lo mismo con los dems tipos de datos. Podemos ver si dos Strings son iguales o no, si dos caracteres son iguales o si uno es mayor que otro tal como los nmeros. Los caracteres estn en un cierto orden que para FreePascal est designado segn la Tabla Ascii, pero esto lo veremos ms adelante. Lo que dir ahora que las letras estn de menor a mayor o sea que KaK es menor que KbK que es menor que KcK, etc. De modo que es posible preguntar KaKYK,K lo cual dar :397 como resultado porque la KaK es menor que la K,K en el orden. Las letras maysculas estn antes que las minsculas y tambin respetan el orden alfabtico, por tanto KAKYK2KYKCK etc y adems KAKYKaK. De este modo, al igual que los nmero estn en este orden $ & D N O R Q S ^ &$ && & &D**** las letras estn en este A 2 C ? 7 . ; > ( ! _ L M + 5 P Q 3 S : 9 0 C ` V a a b c d e 1 g *** Siempre que nos referimos a caracteres debemos colocarlos entre comillas simples al igual que a los strings. Un caracter corresponde al tipo c#ar, cuando es ms de un caracter entonces pasa a ser string. KaK es del tipo c#ar al igual que K2K porque ambos son un solo caracter, pero Ka2K no porque son dos caracteres juntos, por tanto es un String. Veamos un ejemplo sencillo del uso del tipo c#ar, donde el usuario ingresar dos letras en la entrada y luego las comparamos. Cdigo: 1 PROGRAM Caracteres; 2 3 VAR 4 letra1, letra2: char; //Una variable para cada letra. 5 6 BEGN 7 Write('ngrese dos letras separadas por espacios: '); 8 Readln(letra1,letra2); //Leemos la entrada y la asignamos a las variables. 9 Writeln; //Dejamos una lnea en blanco. 10 11 f letra1<=letra2 then 12 writeln('La primera letra es menor o igual a la segunda'); 13 14 f letra1>=letra2 then 15 writeln('La primera letra es mayor o igual a la segunda'); 16 17 Readln; 18 END. Este programa es bien sencillo. Tenemos dos variables del tipo c#ar, letra& y letra. Las leemos tal como si fueran variables numricas. En la lnea 11 tenemos nuestra primera sentencia F, donde si la primera letra es menor o igual que la segunda escribimos el mensaje informativo. En la lnea 14 tenemos otra sentencia F con una condicin inversa a la primera, o sea, si letra& es mayor o igual a letra escribimos el mensaje. Prueben este programa ingresando letras. Si ingresan strings el programa se caer porque las variables son c#ar. Qu pasa si se ingresan letras iguales? Aparecern los dos mensajes en pantalla. Esto es porque las condiciones de ambos F contemplan la posibilidad de que las letras sean iguales, o sea KaKYHKaK es verdadero porque la letra a no es menor que la misma a pero s es igual. KaKZHKaK tambin es verdadero por la misma razn. ------------- Qu pasa si se ingresan nmeros de una cifra en la entrada? Se cae el programa? Pues no. Y ustedes dirn por qu no si los nmeros no son letras? El programa no caer porque el tipo char admite caracteres cualesquiera de la entrada o asignacin, entonces, hay que tener presente que no es lo mismo el nmero & que el caracter K&K. Si tengo una variable a del tipo integer y una variable b del tipo c#ar yo puedo hacer estas asignaciones: Cdigo: a:= 1; b:= '1'; Noten que para la variable b asign el & entre comillas simples, o sea, el caracter &, no el nmero. Un caracter es un smbolo y nada ms, tal como lo son las letras, los nmeros y todo otro caracter extrao que se les ocurra. Si yo hago 6riteIaMJ mostrar en pantalla el nmero entero D porque a vala &. Sin embargo, si hago 6riteIbMJ tengo un error en tiempo de compilacin porque no puedo sumarle el nmero al caracter K&K, es como intentar sumarle 2 a una letra. Tengan mucho ojo con esto. NOTA: Vean que al final de este programa he colocado una instruccin Cdigo: readln; sin parmetros ni nada. Normalmente read y readln se usan para leer un valor de la entrada y guardarlo en una variable, sin embargo si los usamos sin parmetros, el programa quedar a la espera de que se presione ENTER para continuar ya que lea lo que lea no lo guardar en ningn lado. De este modo el programa queda detenido al final permitindonos visualizar los resultados de una forma ms sencilla. Sin embargo no es correcto, por lo tanto, lo mejor es que usen esta sutileza solo mientras prueban sus programas y luego, cuando estan seguros de que anda bien, la borran. ------------------------------------------------------------------------------------- (nstruccin (.***:>7+***7LS7% Esta instruccin funciona casi igual que la F...THEN, pero con una diferencia crucial. La sentencia Cdigo: f condicion then instruccion; la instruccion se ejecutaba solo si la condicion era verdadera, o sea TRUE. En caso contrario no se ejecuta nada y el programa contina su curso. Sin embargo, la instruccin F...THEN...ELSE se ejutar siempre. Veamos, su sintaxis es as Cdigo: f condicion then instruccion1 Else instruccion2; Esto significa S( pasa tal cosa >Aa esta instruccionE S(+5 >Aa esta otra* O sea, si la condicion es verdadera se ejecuta la instruccion& tal y como ya han visto, y se omitir la instruccin luego del 7LS7. Si la condicin es falsa no se har la instruccion& y se har automticamente la instruccion. O sea, le estamos diciendo al F lo que debe hacer si su condicion es falsa. Antes solo le decamos que hacer si era verdadera, ahora tiene las dos opciones, por lo tanto, algo se ejecutar s o s. Noten que la instruccion& no termina en punto y coma (G). Nunca antes de un 7LS7 que forma parte de un (. debe ir un punto y coma porque el compilador creer que es un F comn como el que vimos al principio. Para el ejemplo anterior, teniendo las variables letra1 y letra2 puedo escribir esto Cdigo: f letra1<=letra2 then writeln('La primera letra es menor o igual que la segunda') Else writeln('La primera letra es mayor que la segunda'); Veamos un ejemplo, primero solo con F...THEN, donde se le pedir al usuario que ingrese su edad, asumiremos que se ingresarn nmeros enteros. Si la edad es mayor a 50 aos le decimos que es un viejo, en caso contrario le decimos que es joven: Cdigo: 1 PROGRAM viejo; 2 3 Var 4 edad: integer; //Variable para guardar la edad. 5 6 BEGN 7 //Mostramos mensaje y leemos la edad. 8 write('ngrese su edad: '); 9 readln(edad); 10 11 //Mostramos lo mismo que ya ingres. 12 writeln('Usted tiene ',edad,' aos.'); 13 14 //Si tiene ms de 50 aos le decimos viejo. 15 f edad>50 then 16 writeln('Usted es un viejo'); 17 18 //Si tiene menos de 50 o 50 justito, le decimos joven. 19 f edad<=50 then 20 writeln('Usted es joven'); 21 22 END. Hemos usado dos sentencias F, una contempla lo que la otra no, o sea que o se ejecuta una o la otra. Sin embargo, aunque esto se puede hacer, no es lo correcto porque en futuros programas mucho mas complejos se complicar, adems hace que el cdigo sea menos comprensible. Los dos f anteriores se resumen en este Cdigo: f edad>50 then writeln('Usted es un viejo') Else writeln('Usted es joven'); ------------------------------------------------------------------------------------ Anidacin de la instruccin (1]t#en% Es posible colocar un i1 dentro de otro i1. A esto se lo conoce como anidacin y se usa a muy menudo. Sin embargo hay que tener mucho cuidado de hacerlo bien o podra darse que nosotros creemos que el programa tomar cierto camino cuando en realidad no lo har. Veremos un ejemplo de eso luego del de a continuacin: Veamos un ejemplo en el que se nos pedir la edad dos veces. Si ingresamos una edad mayor a 50 y otra menor nos dir que somos viejos jvenes. Cdigo: 1 PROGRAM anidacion; 2 3 Var 4 edad1, edad2: integer; 5 6 BEGN 7 Write('ngresa tu edad: '); 8 Readln(edad1); 9 Write('ngresa tu edad nuevamente: '); 10 Readln(edad2); 11 12 f edad1>50 then 13 f edad2<50 then 14 Writeln('Eres un viejo joven'); 15 16 END. Como vemos, nuestro programa nos pide el ingreso de nmeros enteros que corresponden a nuestra edad. En la lnea 12 decimos si el valor en edad& es mayor a 50 entonces si el valor en edad es menor a 50 escribe b7res un vie,o ,ovenc. Ahora bien, si edad& es menor a 50 entonces no pasa nada, porque el segundo (1 est dentro del primero y por ende, si la condicin de este no se cumple no entraremos en l. ------------------------------------------------------------------------------------- Anidacin de un i1]t#en con un i1]t#en]else% Es posible hacer todas las anidaciones que se quieran, sin embargo como ya dije antes, debemos tener cuidado. Aqu dar un ejemplo de una anidacin que nosotros podramos interpretar de forma errnea. Cdigo: 1 PROGRAM anidacion2; 2 3 Var 4 edad1, edad2: integer; 5 6 BEGN 7 Write('ngresa tu edad: '); 8 Readln(edad1); 9 Write('ngresa nuevamente tu edad: '); 10 Readln(edad2); 11 12 f edad1>50 then 13 f edad1=edad2 then 14 Writeln('Eres un viejo') 15 else 16 Writeln('Eres joven'); 17 18 END. En este ejemplo uno podra interpretar que si tenemos ms de 50 aos y adems ingresamos las dos veces la misma edad aparecer el mensaje b7res un vie,oc, y si edad& era menor a 50 nos aparecer el mensaje b7res ,ovenc. Sin embargo no es as, esa instruccin se fijar si nuestra edad es mayor a 50 y solo si eso es cierto luego ver si ambas edades eran iguales, si es as aparecer el mensaje b7res un vie,oc y si no aparecer el mensaje b7res ,ovenc. La correcta indentacin de esa instruccin es la siguiente: Cdigo: f edad1>50 then f edad1=edad2 then Wirteln('Eres un viejo') else Writeln('Eres un joven'); Como ven, solo se ejecutar esto si edad&ZO$ resulta ser true. La forma correcta de escribir esta instruccin para obtener el resultado que interpretbamos anteriormente sera: Cdigo: f edad1>50 then begin f edad1=edad2 then Wirteln('Eres un viejo'); end else Writeln('Eres un joven'); Como ven, hemos encerrado entre begin y end la segunda instruccin i1. Esto hace que todo lo que est dentro del rea abarcada por esas dos palabras sea como una sola instruccin para el programa, a pesar de que all dentro podemos poner todas las que queramos. De no hacer esto, el else formara parte del segundo i1 y no del primero. Debemos recordar que un else cierra siempre al i1 que se encuentre ms prximo a l. Para quebrar esto debemos usar beginy end. Los delimitantes begin y end se usan para indicar que al tomar cierto flujo de ejecucin dada una condicin el programa debe efectuar muchas instrucciones. No servira de mucho que por cada i1 que usemos solo podamos dictar una instruccin. La sintaxis genrica sera la siguiente: Cdigo: f condicion then begin nstruccion1; nstruccion2; . . . nstruccionN; end else begin nstruccion1; nstruccion2; . . . nstruccionN; end; Vean que tambin es posible usar los delimitadores begin y end para la instruccin else del i1. Estos begin y end forman lo que llamamos blo-ues de instrucciones y difieren del begin y end principales ya que estos forman un nico bloque que es el programa completo. Luego de un end va enseguida un punto y coma que indica el final del bloque y no un punto como en el caso del end principal. +otar -ue el end anterior al else no 1inali)a con punto " coma. Esto se debe a lo que ya expliqu antes. 3ecordar -ue nuncaE antes de una instruccin else -ue 1orma parte de un i1 debe ir colocado un punto " coma* ------------------------------------------------------------------------------------ Condiciones compuestas% Hasta ahora hemos visto como dada una condicin especfica el programa tomar un camino u otro para realizar sus tareas. Sin embargo normalmente deben cumplirse varias condiciones para que un programa tome un camino u otro. Aqu entramos a componer condiciones, o sea, a decir cosas como: Si pasa tal cosa " tal otra has esta tarea o si pasa tal otra cosa has esta. Aprenderemos a usar los operadores booleanos para componer condiciones. Veamos un ejemplo parecido al anterior: Cdigo: 1 PROGRAM anidacion2; 2 3 Var 4 edad1, edad2: integer; 5 6 BEGN 7 Write('ngresa tu edad: '); 8 Readln(edad1); 9 Write('ngresa nuevamente tu edad: '); 10 Readln(edad2); 11 12 f (edad1>50) and (edad1=edad2) then 13 Writeln('Eres un viejo') 14 else 15 Writeln('O eres joven o mentiroso'); 16 17 END. Aqu vemos que en la instruccin F hay dos condiciones entre parntesis unidas por la palabra reservada A+?. Esto significa que se ejecutar la instruccin del F si ambas condiciones son verdaderas, o sea, si se cumple a la vez que edad&ZO$ y que edad&Hedad. Basta con que una de ellas sea falsa para que no se ejecute la instruccin del F y se pase a la del ELSE. En ese caso no sabremos si sucedi porque el usuario era joven o si era un mentiroso que ingres dos edades diferentes. Esta es una composicin de condiciones que forman una condicin total. El AND forma esta condicin evaluando las dos pequeas, entonces si ambas son verdaderas a la vez la condicin AND devuelve TRUE. Estas composiciones son evaluadas por Free Pascal con el mtodo conocido como circuito corto. Esto es que, si la primera condicin del AND es falsa, ya no se evaluar la segunda porque aunque esta fuera verdadera la condicin total resulta falsa. As nacen las tablas de verdad. A+? en ingls significa V. Si nosotros quisiramos haber dicho que se ejecute el F si la primera condicin la otra eran verdaderas deberamos haber usado el operador 53. Este es verdadero si al menos una de las condiciones es verdadera. Tambin se evala por circuito corto, o sea, si la primera condicin es verdadera ya no se evaluar la segunda porque aunque resulte falsa la condicin total OR ser verdadera. 0eamos las tablas de verdad% Existe tambin el operador booleano +5: que niega una condicin, o sea, da el valor opuesto a esta. En principio uno se pregunta para que servira algo como eso. Ms adelante cuando comencemos a trabajar con las variables boolean veremos el uso de este operador. Veamos su tabla: ------------------------------------------------------------------------------------- 5peradores relacionales% Son los que comparan dos expresiones, tal y como hemos venido haciendo hasta ahora: ------------------------------------------------------------------------------------- 9n e,emplo matemtico% Bien. Haremos un programa en el cual aplicaremos casi todo lo dado hasta ahora. Se nos pide realizar un programa que calcule las races de polinomios de segundo grado cuyos coeficientes sern ingresados por el usuario, y muestre en pantalla los mensajes correspondientes. Por si alguno de ustedes no est bien familiarizado con polinomios explicar brevemente lo que es uno de segundo grado: Un polinomio es una funcin matemtica con una nica incgnita ` la cual est elevada a distintos exponentes en los diferentes trminos de la ecuacin. Para que se vea mejor, un polinomio de segundo grado tiene la forma a`d M b` M c donde a, b y c son nmeros reales. Por ejemplo, un polinomio podra ser `d M N` M . Los nmeros que acompaan a las ` (a, b y c) son llamados coe1icientes. Las races de un polinomio son aquellos valores de ` que hacen que la ecuacin sea nula, o sea, que valga $. En el ejemplo que tenemos all, una raz de ese polinomio es '&. Si cambiamos la incgnita ` por '& efectivamente vemos que todo se anula: 2*(-1)^2 + 4*(-1) + 2 H 2*1 4 + 2 H 2 4 + 2= -2 + 2 H 0. Dado un polinomio de segundo grado puede suceder que tenga dos races diferentes, una nica raz (llamada raz doble) o que no tenga raz. Para hallar las races de un polinomio a`d M b` M c se usa la conocida frmula de Bascaras: El trmino bajo la raz cuadrada (bd'NLaLc) es llamado discriminante ya que de l depende si el polinomio tiene dos races, una sola o no tiene. Si el discriminante es ma"or -ue $ efectivamente tendremos dos races distintas ya que por la forma de la frmula tenemos un e que divide la frmula en dos partes, por un lado resolvemos la ecuacin con el signo de M luego de fb, y despus resolvemos la frmula con el signo de f luego del fb: Esto dar dos resultados diferentes, cada uno correspondiendo a una raz. Si el discriminante es nulo, o sea igual a 0, la raz cuadrada de 0 es igual a 0, por tanto sera estpido separar en dos la ecuacin ya que hacer fbM$ o fb'$ da exactamente igual, por lo cual el resultado ser nico. En este caso tenemos una nica raz doble. Si el discriminante es menor que 0 no podremos hallar su raz cuadrada ya que no existe raz de un nmero negativo. En este caso la frmula no puede resolverse y decimos que no existen races reales. En este caso pueden hallarse races complejas, pero eso no lo haremos ahora ya que tiene sentido solo para aquellos que se lleven bien con las matemticas. Muy bien, teniendo cierto conocimiento sobre el problema comencemos a plantearnos como lo resolveremos para programarlo. El usuario ingresar en la entrada estndar los coeficientes a, b y c de nuestro polinomio. Teniendo esos valores primero debemos verificar que el valor a sea distinto de $ ya que de ser as no estaramos enfrentndonos a un polinomio de segundo grado sino a uno de grado uno o cero. Adems, por la forma de la frmula de Bascaras, si a vale 0 entonces La tambin, y est trmino es el divisor; al no poder dividir por 0 estaramos enfrentndonos aun problema. Luego deberemos evaluar el discriminante y segn lo que este d cmo resultado tomaremos tres caminos distintos para mostrar los resultados al usuario. He aqu el cdigo: Cdigo: 1 PROGRAM polinomio; 2 3 Var 4 a, b, c: real; //Los coeficientes del polinomio. 5 discriminante: real; //El discriminante. 6 raiz1, raiz2: real; //Las races del polinomio. 7 8 BEGN 9 //Pedimos al usuario el ingreso de datos y leemos los mismos. 10 write('ngrese los coeficientes separados por espacio: '); 11 readln(a,b,c); 12 13 //Verificamos que el coeficiente a sea no nulo. 14 f a=0 then 15 writeln('Usted no ha ingresado un polinomio de segundo grado.') 16 else 17 begin 18 //Calculamos el discriminante. 19 discriminante:= sqr(b)-4*a*c; 20 21 //Tomaremos los tres caminos segn el valor discriminante. 22 f discriminante=0 then 23 begin 24 //El polinomio tiene una nica raz. 25 raiz1:= -b/(2*a); 26 writeln('El polinomio tiene una raz doble: ',raiz1:2:2); 27 end 28 else 29 f discriminante>0 then 30 begin 31 //El polinomio tiene dos races. 32 raiz1:=(-b+sqrt(discriminante))/(2*a); 33 raiz2:=(-b-sqrt(discriminante))/(2*a); 34 35 writeln('El polinomio tiene dos races reales: ',raiz1:2:2,' y ',raiz2:2:2); 36 end 37 else 38 writeln('No existen races reales.'); 39 end; //Fin de la instruccin ELSE del F principal. 40 END. Muy bien, como primera cosa les dir que a pesar de la explicacin que yo pueda dar aqu ser conveniente que ustedes mismos estudien este programa para comprenderlo bien. No es para nada complicado pero puede resultar confuso gracias a las anidaciones que se han hecho de las funciones F.THEN.ELSE. En las lneas 4, 5 y 6 declaramos todas las variables necesarias para que nuestro programa funcione correctamente. En la lnea nmero 11 leemos los tres coeficientes a la vez. Luego tenemos un F.THEN. ELSE principal que, si el coeficiente a es igual a $ mostrar un mensaje de error al usuario y solo en caso contrario pasar a realizar todas las dems tareas en su instruccin ELSE, la cual es un enorme bloque de instrucciones encerradas entre begin y end. En ese caso calculamos primero el discriminante ya que de l dependern los caminos a tomar. Observar que al hacerlo (en la lnea 19) usamos la funcin s-r que calcula el cuadrado de un nmero. En vez de eso podramos haber puesto bLb que es lo mismo. Si el discriminante es igual a 0 mostraremos al usuario la raz doble, sino, si el discriminante es mayor que 0 calculamos y mostramos ambas races, y en caso contrario le diremos al usuario que no existen races reales. Es importante que entiendan el uso de los begin y end en este programa. Recuerden que estos delimitan bloques de programa los cuales son vistos como una nica instruccin. Si escribiera el cdigo anterior a partir del primer F de modo que en cada sentencia tuviramos una nica instruccin quedara as: Cdigo: f condicion1 then nstruccion1 Else Begin //Aqu debera estar el clculo del discriminante. f condicion2 then nstruccion2 Else f condicion3 then nstruccion3 Else nstruccion4; End; Esto, si tomramos todo lo que est entre el BEGN y el END que vemos all como una nica instruccin quedara simplemente como Cdigo: f condicion1 then nstruccion1 Else nstruccion2; donde la (nstruccion sera todo el enorme bloque entre el BEGN y END. ------------------------------------------------------------------------------------- (nstruccin de seleccin CAS7]7LS7% La instruccin CASE que veremos a continuacin podra considerarse como la forma correcta de escribir una enorme cantidad de F anidados. Veamos primero un ejemplo anidando F en el cual el programa despliega al usuario varias opciones y dependiendo de lo que ste seleccione ser lo que har: Cdigo: 1 PROGRAM menu; 2 3 Var 4 opcion: char; 5 numero: integer; 6 7 BEGN 8 writeln('1--> Muestra un mensaje en pantalla'); 9 writeln('2--> ngresar un nmero'); 10 writeln('3--> ngresar un caracter'); 11 12 write('ngrese una opcion y presione ENTER: '); 13 readln(opcion); 14 15 writeln; 16 17 f opcion='1' then 18 writeln('MENSAJE DESPLEGADO') 19 else 20 if opcion='2' then 21 begin 22 write('ngrese un nmero entero: '); 23 readln(numero); 24 writeln('Ha ingresado ',numero,'.'); 25 end 26 else 27 if opcion='3' then 29 begin 30 write('ngrese un caracter: '); 31 readln(opcion); 32 writeln('Ha ingresado ',opcion); 33 end 34 else 35 writeln('ERROR. No existe la opcin ',opcion); 36 END. En este ejemplo volvemos a trabajar con una variable del tipo c,ar, o sea que contendr caracteres, no una cadena como el tipo string sino uno solo. Esto es por un simple motivo. Al ser del tipo c#ar cualquier smbolo que ingresemos ser ledo sin problemas. Nosotros mostramos las opciones del men con nmeros, entonces uno podra decir que para leer la opcin que el usuario ingrese podramos haber declarado una variable integer o real, sin embargo de hacerlo as, si el usuario en vez de ingresar un nmero ingresa una letra el programa dar un error en tiempo de ejecucin al intentar almacenar una letra en una variable numrica y se cerrar. Sin embargo, al ser del tipo c,ar, si el usuario ingresa una letra esta se leer sin problemas y podremos desplegar al usuario un mensaje de error que indique que ha seleccionado una opcin incorrecta, y de ser posible pedirle que lo intente de nuevo. Notar como en las condiciones de los F comparamos el carcter ledo en la variable opcion con un carcter escribiendo este explsitamente entre comillas simples. Es importante saber que si el usuario ingresa un 1 en su entrada, nosotros leeremos el carcter 1 y +5 el nmero 1. El carcter 1 es como una letra o un smbolo, no es un nmero que se puede sumar o restar, es un smbolo (ya lo dije antes). Del mismo modo que uno no puede sumar letras, aMb por ejemplo, no se pueden sumar caracteres numricos. No es lo mismo & que b&c. El primero es un nmero y el otro un carcter. b&cMcc equivale a la cadena b&c, y &M es igual a D. Esta diferencia resulta esencial, es importante que lo comprendan. No he puesto comentarios en este programa apropsito para que ustedes lo lean y entiendan por s solos. Bsicamente decimos, si el usuario ingresa el : muestra un mensajeL sinoL si el usuario ingresa el 2 pide que ingrese un numero A muEstraseloL sinoL si el usuario ingresa el & p!dele que ingrese un carcter A muEstraseloL sino dile que lo que ,a ingresado no es una opciIn correcta. Ahora veamos el mismo programa usando la instruccin CASE: Cdigo: 1 PROGRAM menu; 2 3 Var 4 opcion: char; 5 numero: integer; 6 7 BEGN 8 writeln('1--> Muestra un mensaje en pantalla'); 9 writeln('2--> ngresar un nmero'); 10 writeln('3--> ngresar un caracter'); 11 12 write('ngrese una opcion y presione ENTER: '); 13 readln(opcion); 14 15 writeln; 16 17 Case opcion of 18 '1': writeln('MENSAJE DESPLEGADO'); 19 '2': begin 20 write('ngrese un nmero entero: '); 21 readln(numero); 22 writeln('Ha ingresado ',numero,'.'); 23 end; 24 '3': begin 25 write('ngrese un caracter: '); 26 readln(opcion); 27 writeln('Ha ingresado ',opcion); 28 end; 29 else 30 writeln('ERROR. No existe la opcin ',opcion); 31 end; //De la instruccin CASE. 32 END. Hasta la lnea 16 nuestros ejemplos son exactamente iguales. Ahora, en la lnea 17 en vez de tener un F tenemos la declaracin de la instruccin CASE. Su sintaxis es la siguiente: Cdigo: Case variable of Etiqueta1: instruccion1; Etiqueta2: instruccion2; ... EtiquetaN: instruccinN; Else ntruccion_por_defecto; End; Esta instruccin se fijar en el valor de la variable colocada entre la palabra CASE y la palabra OF, en nuestro ejemplo se trata de la variable opcion. Luego tomar el camino en el cual el valor de la variable sea igual al de la etiqueta. El ELSE al final indica lo que se debe hacer si la variable no corresponde con ninguna de las etiquetas anteriores. Este ELSE puede ir o no, es opcional. Si no est no se ejecutar nada y se continuar con lo que haya debajo en el cdigo, pero no habr error. En este caso hemos usado el ELSE par decir al usuario que no ingres nada de lo esperado. Notar que antes de este ELSE s debe ir un punto y coma que cierre la instruccin anterior, no como en el caso de los ELSE que se usan en una instruccin F. Siempre al final de la instruccin CASE debe ir un END que finalice en punto y coma para indicar el final de esta instruccin. No colocarlo es un error de sintaxis. Notar que las instrucciones para cada etiqueta pueden ser bloques de instrucciones delimitados por sus respectivos BEGN y END. Es importante saber que las etiquetas representan los valores que debe tomar la variable del encabezado del CASE para que el programa tome tal o cual camino. Es posible indicar ms de un valor a la vez en una misma etiqueta, simplemente separando cada valor por una coma: Cdigo: Case variable of Valor1, valor2: instruccion1; Valor3, valor4, valor5: instruccion2; . . . Valor, valorN: instruccionJ; End; (MP53:A+:7: La variable del encabezado del CASE debe ser de un tipo ORDNAL, o sea integer, c,ar, enumerado, boolean o subrango. ------------------------------------------------------------------------------------- 7,ercicio: Este es un simple ejercicio para que usen CASE. Quiero que en un solo programa junten los siguientes ejemplos que vimos hasta ahora: el programa >olaMundo, el del [rea de un :ringulo, el que dividBa dos ci1ras #abindolo modi1icado para -ue muestre un error si se ingresa la segunda ci1ra igual a $, y el programa -ue desglosaba un nmero de cuatro ci1ras modificado para que muestre un error si el usuario ingresa un nmero invlido, o sea, uno que sea menor a 1000 o mayor a 9999. Su programa debe mostrar un men como el siguiente: &J >ola Mundo J Calcular el [rea de un :ringulo DJ ?ividir dos nmeros reales NJ Sumar los dBgitos de un nmero de cuatro ci1ras Seleccin% Cuando el usuario elija una opcin su programa habr de realizar las tareas pertinentes y en caso contrario notificar el error. +o continen #asta no lograr #acer esto* ------------------------------------------------------------------------------------ Adems ingresen en ESTE ENLACE para realizar todos los ejercicios all propuestos, los cuales tratan todo lo dado especficamente en esta leccin. Espero que todo haya sido claro. Esperar sus comentarios y sus dudas Programando desde $% $Q' Secuencia de repeticin .53* Leccin Q% Secuencia de repeticin .53% (ntroduccin% Antes que nada les dir que intentar hacer estas lecciones un tanto menos densas que las anteriores porque se que han sido largas y esto puede desanimar un poco. Sin embargo, ir tirando temas que no se terminen de dar no es mi estilo porque sino el conocimiento no se termina de arraigar. Lo mejor es, dado un tema, comenzarlo y terminarlo de entrada, excepto si este est constituido por muchos temas diferentes, en ese caso es mejor dar cada temita por separado para luego unir lo que haga falta. En esta leccin tratamos el tema 6epeticiIn, sin embargo este abarca tres estructuras, en esta leccin solo veremos una de ellas. Hemos visto hasta ahora lo bsico de la programacin, como los tipos, las variables, las constantes y dems. Todos estos, aspectos necesarios para hacer funcionar un cdigo. Ahora bien, lo que nos falta es controlar ese cdigo a nuestro gusto, pudiendo optar por distintos caminos, ir y venir, etc. La seleccin nos permite elegir un camino u otro en base a condiciones booleanas (verdaderas o faltas), las cuales pueden ser sumamente complejas. Esto lo permite la sentencia F en todas sus variantes. Sin embargo no basta con solo elegir un camino u otro, sino que a veces necesitamos repetir tareas, entrando entonces en la repeticin. Por ejemplo, en nuestro programa -ue resuelve polinomios de segundo grado sera conveniente que si el usuario ingresa el coeficiente a nulo, adems de mostrar el mensaje de error, el programa vuelva a pedir que se ingresen los coeficientes, o si en nuestro programa de la instruccin CAS7 el usuario ingresara una opcin que no est en el men adems de notificrselo sera correcto volver a pedir que ingrese una. Estas repeticiones son indefinidas, o sea, no sabemos cuando terminaremos de repetir lo mismo una y otra vez porque no sabemos cuantas veces se equivocarn los usuarios. Para ser un poco ms claro, una repeticin consta justamente de repetir la ejecucin de cierta parte de nuestro cdigo fuente, o de todo el mismo. O sea, si nuestro programa debe volver a hacer exactamente lo mismo que ya hizo por qu no usar el cdigo ya escrito? Aqu entramos entonces en los bucles de repeticin. Un bucle es un bloque de cdigo que, por lo general, delimitamos entre 2egin y 7nd tal como ya he explicado. Estos bloques de cdigo estn pensados para ejecutarse ms de una vez para la realizacin de ciertas tareas que lo requieren. Existen tres estructuras de repeticin; la que vamos a ver a continuacin llamada .53, y otras dos que veremos luego llamadas C>(L7]?5 y 37P7A:]9+:(L. ------------------------------------------------------------------------------------- Sentencia .53% En los ejemplos que d, como ya dije, habl de repeticiones indefinidas, o sea que no sabamos a priori cuntas veces debamos repetir una misma tarea. Un ejemplo ms comn es este: Un telfono celular normalmente contiene un cdigo PN de 4 dgitos, el cual se ingresa al encender el telfono. Por lo general tenemos 3 intentos posibles de ingreso del PN, o sea, podemos equivocarnos un mximo de tres veces. Si eso sucede el chip SM se bloquea y nos solicita el cdigo PUK que es largusimo y adems rara vez funciona, pero eso no nos importa. Centrmonos en el hecho del ingreso sel PN. Si lo ingresamos bien de entrada, el telfono inicia su sistema y listo. Si nos equivocamos, vuelve a solicitar el PN adems demostrarnos los intentos restantes que nos quedan. Si lo ingresamos bien, se inicia el sistema y sino, vuelve a solicitar. Esta es un claro ejemplo de repeticin indefinida, porque podemos repetir la misma tarea un mximo de 4 veces o ninguna. Entonces hay dos condiciones de salida: O ingresamos bien el cdigo, o fallamos todas las veces posibles. Este tipo de repeticiones es muy til pero no la veremos todava. FOR (que en ingls significa PARA o POR) repite una tarea una cantidad especfica de veces, ni mas ni menos. O sea que, una vez iniciada, repetir el cdigo tantas veces como se le haya estipulado, no pudiendo salirse antes. Entonces, esta estructura no sirve para el ingreso del PN. Veamos un ejemplo donde escribiremos en pantalla el nmero 1 diez veces seguidas, primero sin FOR, y luego con: Cdigo: PROGRAM sinFOR; BEGN write(1); write(1); write(1); write(1); write(1); write(1); write(1); write(1); write(1); write(1); readln; END. Este es un programa super bsico, casi tan bsico como el "Hola mundo". He agregado al final un procedimiento readlnG para que el programa quede a la espera de un ENTER, as vemos el resultado de su salida. Aqu hemos repetido lo mismo 10 veces. Entonces, veamos como utilizar FOR para lograrlo: Cdigo: PROGRAM conFOR; VAR i: integer; BEGN For i:=1 to 10 do write(1); readln; END. Como pueden ver, lo primero que hice a diferencia del ejemplo anterior ha sido declarar una variable i. Ahora veamos la siguiente lnea Cdigo: For i:=1 to 10 do Esto es lo que llamamos encabe)ado del .53. Comenzamos con la palabra reservada .53. Luego indicamos una variable que debe estar declarada junto con todas las dems. Esta variable debe de ser de un tipo ordinal, por ejemplo, integer o c,ar. Luego le asignamos el valor inicial desde el cual comenzaremos a contar las repeticiones a realizar, en este caso es el nmero entero 1 porque i es del tipo integer. Luego va la palabra reservada :5 y luego el valor final de la variable que usamos antes. En este caso el entero 10. Finalmente va la palabra reservada ?5 seguida de la instruccin a realizar. La variable i comenzar valiendo 1 (as lo asignamos nosotros), luego aumentar su valor a 2, luego a 3, a 4, y as hasta llegar a 10, donde terminar la ejecucin del .53. Esta variable es llamada variable de control justamente porque controla al FOR indicando el tiempo de vida del mismo. Cada vez que la variable de control modifica su valor se sucede lo que se conoce como iteracin. En cada iteracin el FOR realiza la instruccin que est luego de su encabezado (luego de ?5), en este caso, 6riteI&JG Noten que luego de la palabra DO no va punto y coma ya que esto quebrara el FOR y el compilador chillara por no encontrar una instruccin a realizar. Entonces, dado el FOR tal como lo escrib en este ejemplo: Cdigo: For i:=1 to 10 do write(1); la ejecucin se sucede as: Primero i comienza valiendo 1, entonces el FOR mira su instruccin y la realiza, en este caso, imprime un 1 en la salida. Hecho esto el FOR vuelve a su encabezado y aumenta el valor de la variable de control en 1, o sea que ahora i vale 2. Se realiza nuevamente la instruccin, o sea, volvemos a imprimir un 1 en pantalla. Volvemos al encabezado y el FOR aumenta en 1 la variable de control, o sea que ahora i vale 3. Realizamos la instruccin y repetimos esto. Cuando i valga 10, el FOR terminar de iterar y pues, el programa continuar su curso. La sintaxis general de un FOR es la siguiente: Cdigo: FOR variable:= valor_inicial TO valor_final DO nstruccin; Por ejemplo, si quisiramos imprimir la letra A unas 10 veces la declaracin del FOR sera algo as: Cdigo: For i:=1 to 10 do Write('A'); En este caso veramos una salida como esta: AAAAAAAAAA NOTA: El valor final del encabezado del FOR debe ser del mismo tipo que el inicial, o sea, del mismo tipo que la variable de control (por ejemplo puede ser 1or i%H bac to b)c do). Resulta realmente til poder repetir solo una nica instruccin? Realmente NO, por lo tanto, si dentro de un FOR queremos realizar ms de una cosa, debemos delimitar el bloque por 2egin y 7nd. De este modo, la verdadera forma general de un FOR sera as: Cdigo: FOR variable:= valor_inicial TO valor_final DO Begin nstruccion1; nstruccion2; . . . nstruccionN; End; ------------------------------------------------------------------------------------- 9so de la variable de control% Como he explicado, en cada iteracin la variable de control va tomando valores, por lo tanto, muchas veces (y en general) se utiliza esta variable para realizar tareas dentro de un FOR, no solo para aumentar o disminuir. Veremos un ejemplo entonces donde, usando la variable de control del FOR imprimimos en pantalla los nmeros del 1 al 10 separados por un espacio: Cdigo: PROGRAM Del1al10; VAR i: integer; BEGN FOR i:= 1 to 10 DO write(i,' '); readln; END. Se entiende? Esto no es nada complicado. Podemos usar la variable de control dentro del FOR para realizar cualquier tarea, incluso modificar su valor, sin embargo les dir esto ===+9+CA M5?(.(CA3 LA 0A3(A2L7 ?7 C5+:35L ?7 9+ .53@@@ Si me hacen caso, se ahorrarn cientos de miles de dolores de cabeza. Ahora veamos un ejemplo en el que imprimimos en pantalla los 10 primeros nmeros pares. Por si no lo saben, decimos que un nmero es par si es divisible entre 2, o sea, si el resto de la divisin entera es igual a 0, lo que en Pascal equivale a decir que 0AL53 M5? H $. mprimiremos en pantalla los 10 primeros nmero pares a partir del 0 sin incluir a este: Cdigo: 1 PROGRAM pares; 2 3 Var 4 i: integer; 5 6 BEGN 7 write('Los 10 primeros pares son: '); 8 9 For i:=1 to 20 do 10 f i mod 2= 0 then 11 write(i,' '); 12 END. En la lnea 7 mostramos al usuario un mensaje. En la novena lnea comienza la declaracin del FOR donde inicializamos i en 1 y continuaremos hasta que valga 20. El F en la lnea 10 se encarga de ver si el valor actual de i es par, o sea si el resto de dividirlo entre 2 es igual a 0. En ese caso imprimimos su valor y un espacio, sino no hacemos nada y esperamos la siguiente iteracin. Vuelvo a repetirles que al proceso de repetir varias veces un mismo segmento de cdigo se lo llama iteracin. Nuestro FOR iterar 20 veces. Es importante jams modificar la variable de control mientras se est ejecutando el FOR, o sea, no hacer por ejemplo i%H &$ dentro del FOR ya que eso produce errores muy inesperados y dependen mucho del compilador usado para crear el programa. Puede usarse el valor de la variable de control para todo lo que se necesite, incluso incluirlo en expresiones y condiciones tal como en nuestro ejemplo, pero nunca modificarlo (se los tengo que gritar nuevamente jeje?. Ahora veamos el mismo programa, pero solo que esta vez le pediremos al usuario que ingrese cuantos nmeros pares quiere visualizar: Cdigo: 1 PROGRAM PrimerosPares; 2 3 Var 4 i, pares: integer; 6 BEGN 7 8 write('Cuantos pares quieres visualizar? '); 9 readln(pares); 10 11 writeln; 12 write('Los primeros ',pares,' pares son: '); 13 14 pares:= pares*2; 15 16 For i:=1 to pares do 17 f i mod 2= 0 then 18 write(i,' '); 19 END. En la lnea 8 mostramos el mensaje al usuario para, en la siguiente lnea, pedirle que ingrese cuntos pares desea ver. En la lnea 11 usamos el procedimiento 6riteln sin parmetros para que imprima una lnea en blanco. En la lnea 12 mostramos un mensaje al usuario. En la lnea 14 hay algo nuevo. A la variable pares le asignamos su propio valor multiplicado por 2 ya que si el usuario desea ver, por ejemplo, los diez primeros pares nosotros deberamos iterar del 1 al 20. Esto de asignar a una variable un valor que depende de su valor anterior es muy comn en la programacin. A dichas variables se las conoce como acumuladores. Esto lo veremos en ms detalle cuando trabajemos con WHLE y REPEAT. En la lnea 16 cambiamos el valor final del encabezado del FOR por la variable pares. Esto es lo ms comn en el uso de esta instruccin. No hace falta indicar un valor nosotros mismos, sino que podemos colocar nombres de variables, constantes o incluso expresiones matemticas siempre y cuando el tipo de la variable de control y el del valor final sean el mismo y a su vez estos sean ordinales. ---------------- Veamos otro ejemplo sencillo, solo que ahora le diremos al usuario que indique el rango de nmeros entre los cuales desea ver los pares, o sea, por ejemplo, si quiere ver los pares entre el 10 y el 30, que lo indique l mismo: Cdigo: 1 PROGRAM RangoDePares; 2 3 Var 4 i, inico, fin: integer; 6 BEGN 7 8 write('ngrese el rango numrico para visualizar pares: '); 9 readln(inicio,fin); 10 11 writeln; 12 write('Los pares en el rango del ',inicio,' al ',fin,' son: '); 13 14 For i:=inicio to fin do 15 f i mod 2= 0 then 16 write(i,' '); 17 18 radln; 19 END. En este caso vemos que hemos puesto variables como valorFinicial y como valorF1inal. Es posible colocar funciones, expresiones y dems. ------------------------------------------------------------------------------------- Anidacin de .53% Veamos un ejemplo donde el usuario ingresar un nmero que indicar el largo del lado de un cuadrado y dibujaremos este con el carcter L (asterisco): Cdigo: 1 PROGRAM Cuadrado; 2 3 Const 4 caracter= '*'; 5 6 Var 7 i, j, lado: integer; 8 9 BEGN 10 write('ngresa el largo del lado: '); 11 readln(lado); 12 13 writeln; 14 15 For i:=1 to lado do 16 begin 17 For j:=1 to lado do 18 write(caracter); 19 20 writeln; 21 end; 22END. Lo interesante en este programa es analizar lo que sucede desde la lnea 15 en adelante. Tenemos dos FOR, uno dentro de otro. Lo primero a resaltar es el uso de dos variables de control di1erentes, una para cada FOR. Si usramos la misma variable para ambos uno modificara la del otro y se ocasionara un caos. Si quieren prueben este programa as como est y luego con la misma variable de control. Es probable que el compilador los regae por eso y se produzca un error en tiempo de compilacin. Veamos, cuando i vale 1 entramos al FOR principal. All tenemos otro FOR el cual se ejecutar hasta el final antes de volver al primer FOR. Cuando , vale 1 imprimimos un L (est definido en la constante caracter). Luego , vale 2 y se imprime un segundo L en la misma lnea ya que estamos usando un procedimiento 6rite. As continuamos hasta que se imprimen tantos L en una lnea como lo indique la variable largo. Ahora pasamos a la lnea 20 del programa donde est 6riteln para escribir una lnea en blanco, o sea, para bajar un rengln. Hemos vuelto al encabezado del FOR principal, ahora i vale 2. Volvemos a entrar en el FOR principal y el FOR de dentro vuelve a comenzar con , en 1. mprime los L, se baja un rengln y as hasta que i sea igual al valor de la variable lado. Notar que la instruccin 6riteln de la lnea 20 est dentro del FOR principal pero no forma parte del FOR interno. ------------------------------------------------------------------------------------- .53 decreciente% Otra forma del FOR es la siguiente: Cdigo: For variable:=valor_inicial downto valor_final do nstruccin; Esto funciona exactamente igual a la forma anterior del FOR con la diferencia de que valorFinicial es mayor que valorF1inal. O sea que la variable de control ir decreciendo en vez de aumentando. Por ejemplo: Cdigo: For i:=20 downto 1 do nstruccion; En este caso i comenzar valiendo 20, luego 19, luego 18, y as hasta llegar al 1. NOTAS: Nunca asuman el valor que tendr la variable de control una vez finalizado el FOR. En este ejemplo de FOR que va de 20 a 1 uno podra decir que i vale 1 al final, pero esto puede no ser as, depende del compilador. Si van a volver a usar esta variable debern iniciali)arla ustedes mismos con el valor apropiado* A continuacin les planteo una serie de ejercicios de aplicacin del FOR y algunos temas ya vistos. Por favor, no continen si no son capaces de resolver estos ejercicios. Todas las dudas postenlas aqu. P.D: Dganme si estoy yendo muy rpido. ------------------------------------------------------------------------------------- 7,ercicio &% Determinen cules de los siguientes fragmentos de cdigo producen la misma salida: a) Cdigo: FOR i:=1 TO 3 DO FOR j:= i+1 TO 3 DO write(i,j) b) Cdigo: FOR i:=1 TO 3 DO write (i, i+1) c) Cdigo: FOR i:=1 TO 4 DO F (i=1) OR (i=4) THEN write(i) ELSE write(i,i) ---------------------------------------------------------------- 7,ercicio : Escriban un programa que lea desde el teclado un valor entero n. A continuacin, el programa deber leer n enteros y luego desplegar el mayor y el menor de ellos. Ejemplo de entrada: n=8 Ingrese ' enteros: C :2 &( Q 2: @C :2 :' Ejemplo de salida: #l maAor entero ingresado es: @C #l menor entero ingresado es: Q ---------------------------------------------------------------- 7,ercicio D% Escriban un programa que lea de la entrada estndar 5 valores positivos, todos menores que 60 y produzca una grfica de barras horizontales similar a la que se muestra en el ejemplo para estos datos: Ejemplo de entrada: Ingrese C 3alores: C :2 :R &C ' Ejemplo de salida: MMMMM MMMMMMMMMMMM MMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMM ---------------------------------------------------------------- 7,ercicio N: Escriban un programa que lea de la entrada estndar un carcter c y un entero n. El programa debe desplegar un tringulo de n lneas formado por el carcter c segn se muestra en el siguiente ejemplo: Ejemplo de entrada: nS' cST Ejemplo de salida: TTTTTTTT TTTTTTT TTTTTT TTTTT TTTT TTT TT T Programando desde $% $S' +meros aleatorios '' 3epeticin condicional con C>(L7***?5* L7CC(8+ S% 3epeticin condicional con C>(L7***?5 Hemos visto la sentencia FOR, la cual sirve para repetir bloques de cdigo un nmero especfico de veces. Resultar muy til para ciertas tareas, sin embargo, sabemos que no siempre servir. En la leccin anterior les di el ejemplo del PN de un celular. Como ejemplo ms sencillo podramos imaginar un programa que nos haga adivinar un nmero en diez intentos. Nosotros ingresamos un nmero y el programa nos dice si acertamos o no. En caso de acertar ganamos el juego y el programa termina, sino acertamos seguimos intentando hasta gastar nuestros diez intentos, en cuyo caso perdemos. Un programa como este puede finalizar por dos condiciones: **Acertamos el nmero. **Gastamos el nmero de intentos sin lograr acertar. Claramente un FOR no servira para algo como esto porque iterara 10 veces, acertemos o no. Entonces cmo hacemos para decirle al programa que repita algo mientras se den ciertas condiciones y que se detenga si estas no se dan? Aqu entra la sentencia WHLE de la que hablaremos en esta leccin. Sin embargo, antes de abordar ese tema veremos como obtener nmeros aleatorios en Pascal ya que eso resultar til para muchas cosas. ------------------------------------------------------------------------------------- ;enerar nmeros aleatorios% Para obtener un nmero al azar se utiliza la funcin random. Su sintaxis es la siguiente: 3andomI/J donde ` es un entero (integer) que marca el nmero mximo que se puede generar. 3andomI/J devolver un nmero aleatorio entre $ y `'&. Por ejemplo, si escribimos randomIO$J obtendremos un nmero al azar entre $ y N^ inclusive. Si nosotros queremos obtener un nmero entre & y `, entonces tenemos que ser sutiles: Cdigo: WriteLn(Random(10)); nos mostrar en pantalla un nmero entre $ y ^. Cdigo: WriteLn(Random(10) + 1); nos mostrar en pantalla un nmero entre & y &$. Explicar esto a continuacin. Veamos un ejemplo sencillo en el que el usuario ingresa cul es el tope y el programa le devolver un nmero aleatorio entre & y el nmero ingresado. Asumimos que el usuario ingresar un entero mayor que 1: Cdigo: 1 PROGRAM funcion_random; 2 3 Var 4 x, valor_aleatorio: integer; 5 6 BEGN 7 randomize; 8 9 write('ngrese un valor: '); 10 readln(x); 11 12 valor_aleatorio:= random(x) + 1; 14 writeln('El nmero obtenido entre 1 y ',x,' es: ',valor_aleatorio); 15 END. Bien, este programa es bien sencillo de entender. Tenemos dos variables, / y valorFaleatorio. La primera ser leda desde la entrada estndar y guardar el valor ingresado por el usuario. La segunda guardar el nmero al azar obtenido por la funcin random. Lo primero a notar es que en la lnea 7 hacemos una llamada al procedimiento randomi)e. Este no lleva parmetro alguno, simplemente indica que luego en algn momento del programa ser utilizada la funcin random. Si no hacen esto no podrn usar esta funcin y tendrn un error en tiempo de compilacin. En la lnea 10 obtenemos el valor de `. En la lnea 12 asignamos a valorFaleatorio el valor obtenido por randomI/J ms &. Por qu ms 1? Si randomI/J genera un nmero aleatorio entre $ y `'& pero nosotros queremos uno entre & y ` solo basta sumar & al resultado. Por ejemplo, si hiciramos randomI&$J podramos obtener los nmeros 0, 1, 2, 3, 4, 5, 6, 7, 8 o 9. Si quisiramos un nmero entre 1 y 10 basta sumar 1 al valor sorteado. Si sale el 0, al sumar 1 obtenemos el 1. Si sale 9, al sumar 1 obtenemos el 10, o sea, corremos todo el intervalo un lugar a la derecha. ------------------------------------------------------------------------------------- Secuencia de repeticin C>(L7]?5% Comencemos entonces con WHLE. Esta instruccin nos permitir definir las condiciones que harn que un bloque de cdigo se repita. Por lo tanto estas repeticiones sern distintas en cada ejecucin del programa, no como sucede con FOR. WHLE...DO significa MENTRAS.HAZ. Veamos antes que nada su sintaxis general: Cdigo: While condicion do nstruccin; Esto significa, mientras se cumpla la condicin e,ecuta tu instruccin. Una vez hecha la instruccin, WHLE regresar a su encabezado y volver a verificar la condicin. Si esta sigue siendo verdadera volver a ejecutarse. En caso contrario saltear la instruccin y el programa continuar su curso. No est de ms decir que la condicin puede ser compuesta y que la instruccin puede ser un bloque de instrucciones delimitado por BEGN y END. De este modo la forma ms genrica de WHLE sera as Cdigo: WHLE condicion DO BEGN ntruccion1; nstruccion2; . . . nstruccionN; END; Veremos primero el ejemplo del que habl hace poco, un programa que nos har adivinar un nmero. Generaremos un nmero al azar entre 1 y 30 y tendremos 10 intentos para adivinarlo. Aqu usaremos RANDOM. Cdigo: PROGRAM AdivinadorSimple; CONST MAX_NTENTOS= 10; //El nmero mximo de intentos. TOPE= 30; //El nmero ms alto que se puede generar. VAR numero_a_adivinar, numero_leido: NTEGER; adivinado: BOOLEAN; (*La variable adivinado ser TRUE cuando el usuario acierte, y FALSE mientras esto no suceda.*) intento_actual: NTEGER; //Un contador que nos dir en qu intento vamos. BEGN randomize; //Decimos al programa que utilizaremos random en algn lado. numero_a_adivinar:= Random(TOPE) + 1; adivinado:= FALSE; //La inicializamos en FALSE porque an no adivinamos nada. intento_actual:= 0; //An no hemos intentado adivinar nada. WriteLn('ngrese nmeros para intentar adivinar:'); WriteLn; WHLE (NOT adivinado) AND (intento_actual< MAX_NTENTOS) DO (*Vean este encabezado. El WHLE se repetir mientras la variable adivinado sea FALSE porque tiene el operador NOT, y mientras a su vez el nmero de intentos sea menor que el mximo de intentos posibles. Si estas condiciones no se cumplen ambas a la vez, la condicin AND vale FALSE y el WHLE termina.*) BEGN intento_actual:= intento_actual + 1; //Sumamos 1 al nmero de intentos. Write(intento_actual,' --> '); //Mostramos el intento actual. ReadLn(numero_leido); //Leemos el nmero que el usuario ingresa. (*Si el nmero es correcto, la variable adivinado se vuelve TRUE, en caso contrario seguir valiendo FALSE tal como al inicio.*) F numero_leido= numero_a_adivinar THEN adivinado:= TRUE; END; (*El WHLE puede haber terminado por dos cosas, o adivinamos o perdimos. Si adivinamos entonces la variable adivinado ser TRUE, en caso contrario ser FALSE. Usamos eso para distinguir qu mensajes mostrar al usuario.*) F adivinado THEN WriteLn('Felicitaciones GANASTE!!!') ELSE WriteLn('Lamentablemente has perdido.'); ReadLn; //Simplemente para visualizar lo que el programa nos muestra. END. Este programa est totalmente comentado, por lo cual deberan entenderlo completamente. Les dejo aqu, la versin sin comentarios para que el cdigo resulte ms entendible: Cdigo: PROGRAM AdivinadorSimple; CONST MAX_NTENTOS= 10; TOPE= 30; VAR numero_a_adivinar, numero_leido: NTEGER; adivinado: BOOLEAN; intento_actual: NTEGER; BEGN randomize; numero_a_adivinar:= Random(TOPE) + 1; adivinado:= FALSE; intento_actual:= 0; WriteLn('ngrese nmeros para intentar adivinar:'); WriteLn; WHLE (NOT adivinado) AND (intento_actual< MAX_NTENTOS) DO BEGN intento_actual:= intento_actual + 1; Write(intento_actual,' --> '); ReadLn(numero_leido); F numero_leido= numero_a_adivinar THEN adivinado:= TRUE; END; F adivinado THEN WriteLn('Felicitaciones GANASTE!!!') ELSE WriteLn('Lamentablemente has perdido.'); ReadLn; END. Como pueden ver uso dos constantes en este programa, MAX_NTENTOS y TOPE. Simplemente son para que el cdigo sea ms entendible y fcilmente modificable. Si yo quiero que ahora mi programa genere nmeros entre 1 y 100 solo voy y modifico el valor de TOPE. Si quiero que el nmero mximo de intentos sea 20 y no 10, modifico el valor de MAX_NTENTOS y listo. En este ejemplo vemos por primera vez uno de los usos de las variables booblean. En este caso declar una adivinado que indicar el momento en el cual el usuario adivine el nmero. Comenzamos generndonos un nmero al azar y asignando ese valor a la variable numeroFaFadivinar , para luego inicializar nuestro booleano con el valor 1alse ya que el usuario no ha adivinado nada todava porque ni siquiera ha intentado. Tambin inicializamos la variable intentoFactual con el valor $ ya que el usuario an no ha comenzado. Es importante siempre inicializar las variables con los valores apropiados y no asumir que ya lo tienen. Es comn que uno suponga que el valor de intentoFactual sea $ al inicio ya que no se le asign nada hasta el momento, pero esto no es as, depende mucho del compilador que se use. Cuando uno declara una variable de algn tipo, esta puede tomar un valor cualquiera al azar que es desconocido por el usuario (basura). Hay compiladores que las inicializan con algn valor especfico. Sin embargo, al crear un software, nunca sabemos en el futuro cuando deberemos modificarlo o si debemos pasarle nuestro cdigo a algn otro programador para que l trabaje con l. Si la otra persona usa un compilador diferente entonces el programa probablemente no funcione como debe. ===S(7MP37 (+(C(AL(aA3 LAS 0A3(A2L7S@@@ Veamos el encabezado del WHLE ya que all las condiciones estn dadas por el booleano y por una comparacin. Cdigo: WHLE (NOT adivinado) AND (intento_actual< MAX_NTENTOS) DO es equivalente a decir Cdigo: WHLE (adivino=FALSE) AND (intento_actual< MAX_NTENTOS) DO Aqu vemos por primera vez el uso del operador NOT. Vean que lo que hace es preguntar por la falsedad de una variable booleana, o sea, la condicin es verdadera mientras el valor de la variable sea FALSE. Si no se antepone el operador NOT y solo aparece el nombre de la variable booleana, estamos preguntando por la veracidad de la misma, o sea, si esta vale TRUE. Notar que la condicin es una condicin compuesta y que ser verdadera en tanto ambas condiciones comprendidas entre el operador AND sean verdaderas, o sea, la condicin es verdadera si el booleano es FALSO y la variable intentoFactual es menor que MAX_NTENTOS. Si falla alguna de estas cosas el AND es FALSO y el WHLE terminar su iteracin. Usar el nombre de un booleano en una condicin ya es preguntar por si es TRUE. Del mismo modo si uno quiere preguntar por si es FALSE, como en nuestro programa, debe anteponer el operador NOT antes del nombre del booleano. Por ejemplo: Cdigo: F adivinado THEN nstruccion; Es lo mismo que decir Cdigo: F adivinado=TRUE THEN nstruccion; Ya saben que si ponen NOT es justamente lo contrario. Bien, nuestro WHLE funcionar en tanto se cumplan las condiciones dadas, basta que una falle para que no se ejecute el WHLE. Como nosotros inicializamos nuestro booleano en FALSE y le dimos a intentoFactual el valor 0, sabemos que la primera vez que el programa llegue al WHLE su condicin AND ser verdadera y por tanto se ejecutar al menos una vez. Esto es porque nosotros hemos dado a propsito las condiciones necesarias. Lo primero que hacemos dentro del bloque del WHLE es la asignacin: Cdigo: intento_actual:= intento_actual + 1; o sea, estamos asignando a una variable su valor anterior ms 1. Esto se conoce como acumulador porque es una variable que acumula valores y va aumentando. Se dan cuenta de eso? En la primera ejecucin del WHLE intentoFactual pasa a valer 1. En cada iteracin del WHLE estaremos aumentando esta variable en 1, por lo tanto nos aseguramos de que en algn momento alcanzar el nmero mximo de intentos disponibles. Luego leemos el nmero que el usuario ingresa para pasar a esta instruccin: Cdigo: F numero_leido= numero_a_adivinar THEN adivinado:= TRUE; Lo que hace este F es cambiar el valor de adivinado a TRUE si el usuario a adivinado el nmero. Si esto sucede, cuando el WHLE vuelva a mirar su encabezado se encontrar conque el booleano es TRUE y por lo tanto ya no iterar ms y seguiremos de largo. Esta asignacin con F, se puede hacer as: Cdigo: adivinado:= numero_leido= numero_a_adivinar; Como ven, es posible asignar a un booleano la condicin que debe cumplirse para que sea TRUE, si esto no sucede se le asigna el valor FALSE. Esa sera la forma ms correcta en vez de hacerlo con F. Yo lo hice as primero para que a ustedes les quede bien claro lo que se est haciendo. El uso que dimos aqu de la variable booleana es conocido como 2andera 2ooleana ya que nuestra variable se encender cuando se cumpla alguna condicin y nos avisar algo. Sera como levantar una bandera para indicarle algo a alguien. El uso de banderas booleanas es muy comn aunque en principio uno no lo crea. A medida que la prctica en programar es mayor se comprende mejor a los booleanos y su uso aumenta. Yo en particular hago mucho uso de ellos, llegando incluso a abusarme un poco, cosa que no es aconsejable ya que el cdigo puede volverse muy confuso. Una vez fuera del WHLE debemos verificar por qu es que salimos de l. Eso hace el ltimo F, si salimos porque adivinado se volvi TRUE entonces ser porque el usuario gan, en caso contrario salimos porque el usuario se pas de intentos posibles y perdi. Muy bien, ahora que ya conocen el uso de WHLE es hora de darle prctica. Quiero que modifiquen el programa del tringulo para que cuando el usuario ingrese base o altura con un valor nulo o negativo el programa le notifique su error y vuelva a pedrselo. Asuman que el usuario siempre ingresa nmeros reales en la entrada, no se preocupen todava por si ingresa otros caracteres. Tambin modifiquen el programa que efectuaba una divisin entre dos nmeros de modo que si el usuario ingresa el valor del cociente como 0 el programa se lo indique y vuelva a pedrselo. Hagan lo mismo con el programa que desglosaba un nmero de cuatro cifras. Si el usuario ingresa un nmero invlido vuelvan a pedrselo hasta que sea vlido. =============================================== 9n pe-ue\o ,uego% Los tres ejercicios anteriores corresponden a modificar cdigos ya hechos por m y a remodificar lo que ya haban hecho en los ejercicios anteriores, que aunque no es del todo fcil es ms sencillo que disear un programa desde 0. Ahora les plantear un pequeo juego para que lo hagan. Piensen en esto como en su primer proyecto de programacin. Podrn usar todo lo que hemos visto hasta el momento. Este juego se centrar en el uso del WHLE. El problema es el siguiente: Un jugador deber adivinar en un mximo de 15 intentos un nmero entre 1 y 100. Si el jugador adivina, el programa se lo notificar y terminar su ejecucin, en caso contrario el jugador recibir una pista para volver a intentar adivinar. El juego le dir si el nmero que debe adivinar es mayor o menor que el que ha ingresado y el jugador volver intentarlo. En cada caso el juego deber mostrar al jugador el nmero de intento actual y cuantos restantes le quedan. Cuando el usuario pierda, el programa deber mostrar cul era el nmero que deba adivinar. Siempre asumiremos que recibiremos un entero desde la entrada estndar. El nmero a ser adivinado ser generado al azar por el juego. 7,emplos de e,ecucin% 7,emplo &% >ispones de :C intentos para adi3inar. :O..4 @' ;;;uA bien=== ;;;<as adi3inado=== 7,emplo % >ispones de :C intentos para adi3inar. :O..4 @@ Do sientoL no ,as acertado. #l nUmero que debes adi3inar es menor. >ispones de :Q intentos para adi3inar. 2O..4 '9 Do sientoL no ,as acertado. #l nUmero que debes adi3inar es maAor. >ispones de :& intentos para adi3inar. &O..4 'C ;;;uA bien=== ;;;<as adi3inado=== 7,emplo D% >ispones de :C intentos para adi3inar. :O..4 (9 Do sientoL no ,as acertado. #l nUmero que debes adi3inar es menor. . . . >ispones de : intentos para adi3inar. :CO..4 :& Do sientoL no ,as acertado. Damentablemente ,as perdido. #l nUmero era :9. Mucha suerte. Espero que esto les guste. Un saludo, y como siempre, estar a las rdenes. Les dejo aqu un enlace para descargar este programa ya compilado como ejemplo para que vean como debe funcionar. Est en una versin para Windows, si alguien necesita una para Linux no dude en pedirla: Programa Adivinador Programando desde $% $^' 9n tema e/tra% 7l depurador de .ree Pascal* desde $% ^' Leccin e/tra% 7l ?7P93A?53* Bien, antes de continuar aprenderemos a utilizar el ?729;73 (depurador). Esta es una herramienta del compilador especialmente pensada para detectar errores lgicos en nuestros cdigos y que, si la aprendemos a utilizar bien, resultar super til. En ingls bug significa insecto o gusano. En programacin, se le atribuye el trmino bug a los errores lgicos que un programa pueda tener. Es comn, cuando se lanzan las $ases beta (fases de prueba) de un gran programa, encontrarse con bugs que luego sern corregidos hasta que se lancen las versiones completas ($ull). El gran problema de los bugs es que son especialmente difciles de detectar. Por ejemplo, en nuestro programa que divida dos nmeros todo funcionaba bien hasta que alguien ingresara como denominador el nmero $, con lo cual nuestro programa caera. Si al momento de crear dicho programa no nos dbamos cuenta de que justo en ese caso fallara, habra un bug. Tal vez, un usuario se dara cuenta de eso ms tarde y pues, el programa podra corregirse. En un programa sencillo es bien fcil detectar los posibles bugs que se podran generar y pues, depurarlo a tal punto de que quede perfecto y funcione bien para cualquier caso de entrada. Sin embargo, a medida que la complejidad aumenta, los posibles problemas tambin y se vuelve imposible literalmente hacer que el programa quede perfecto. Sin embargo, lo que se hace es analizar la mayora de los posibles casos y corregir al mximo de modo que los errores sufridos sean los mnimos posibles. A su vez se incluyen sistemas de guardado automtico y dems para que, aunque el programa se caiga, no se pierda la informacin. Por ejemplo, yo utilizo 5ppen511ice*org Criter para escribir estas lecciones, digamos que es la competencia del Microso1t Cord. Ambos son procesadores de texto muy potentes y con muchsimas cosas incluidas, lo cual hace que no sean perfectos y que alguna vez puedan trancarse o cerrarse. Sin embargo, cualquiera de ellos tienen implementados sistemas de recuperacin de archivos, de modo que aunque nosotros mismos no hayamos guardado la informacin, el programa s lo hace en una copia temporal que es posible abrir en caso de fallas; esto se hace automticamente. Bien, pero todo esto es muy avanzado an para nosotros. Sin embargo tenemos una herramienta que nos ayuda a detectar los bugs, ms an cuando nuestros programas no hacen lo que queremos y no podemos darnos cuenta de por qu. Es comn que en los bloques de un WHLE o un REPEAT (lo veremos pronto), no se cumplan nunca condiciones de finalizacin y pues, el bucle se repita infinitamente quedando nuestro programa colgado. Veamos un ejemplo en el que nuestro WHLE funcione bien en algunos casos y en otros se quede colgado. El ejemplo que mostrar a continuacin esperar como entrada un nmero entero positivo menor que 50. El programa har la suma de todos los nmeros comprendidos entre el nmero ingresado y 50. Por ejemplo, si ingresamos el nmero 30 el programa calcular 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 38 + 39 + . + 50. Si ustedes ejecutan ese programa e ingresan nmeros mayores o iguales a 25 todo funcionar bien, pero qu pasa si ingresan un nmero menor que 25? Hagan la prueba. Cdigo: PROGRAM WHLEinfinito; VAR x, suma: NTEGER; BEGN Write('ngrese un nmero entero positivo menor que 50: '); ReadLn(x); WriteLn; suma:= 0; WHLE (x<=50) DO BEGN suma:= suma + x; x:= x+1; F x=25 THEN BEGN x:= 0; suma:= 0; END; END; Write('La suma es: ',suma); ReadLn; END. Veremos este programa con el Depurador. Esta herramienta nos permite ejecutar el programa paso por paso e ir viendo lo que hace a cada momento, incluso los valores que van tomando las variables. Primero debemos acondicionar las ventanas de modo que veamos todo como funciona a la vez. Nuestro compilador nos permite trabajar con varias ventanas a la vez, pues veamos como hacerlo para usar el depurador. Bsicamente necesitaremos tres ventanas: *La del cdigo fuente. *La del usuario (que muestra la entrada y salida del programa). *La del visor de variables. La del cdigo fuente ya la tenemos a la vista. Hagamos aparecer al visor de variables, para eso vamos al men ?ebug g Catc#es* Con lo que tendremos una pantalla como esta: En la cual pueden ver tanto la ventana Catc#es como la venta del cdigo 1uente. Es posible cambiar los tamaos de estas ventanas, simplemente hacemos clic sobre una para que quede activa, por ejemplo la del cdigo fuente, y luego vamos al men Cindo6 g Si)ePMove o presionamos Ctrl M .O. Con eso vern que los bordes de la ventana se hacen verdes, lo cual indica que est activada para modificar tanto su tamao como su posicin. Si ustedes presionan las teclas de direccin vern que mueven la ventana, y si presionan S#i1t M :eclas de direccin cambiarn su tamao. Dejen algo parecido a la imagen. Cuando estn conformes con el tamao y la posicin simplemente presionan 7+:73. Ya tenemos en nuestra vista dos ventanas. Ahora aadiremos la tercera que necesitamos. Tengan en cuenta que podemos usar el Debuger no hace falta tener todas estas ventanas, una cosa es independiente de la otra, yo les enseo esto para aprovechar al mximo el potencial de esta herramienta. Necesitamos la pantalla de salida y entrada, ayudar mucho para algunos casos. Para activarla vamos al men ?ebug g 5utput Ahora veremos la pantalla de la consola pero dentro del compilador. Sin embargo ser tan grande que tapar todo, entonces presionan Ctrl M .O y modifiquen su tamao y posicin hasta que quede algo parecido a la imagen. Mi pantalla 9ser screen aparece vaca, la suya puede aparecer llena de texto. Si en algn momento queren quitar una ventana solo la cierran presionando el botoncito verde en la esquina superior izquierda de la misma. Para maximizarla presionan la flecha en la esquina superior derecha, y para restaurarla lo mismo. Las ventanas estn numeradas, como ven, en mi ejemplo la ventana del cdigo tiene el nmero 1, la del viso tiene el nmero 2 y la del usuario el nmero 3. Ahora tenemos que aadir las variables que queremos visualizar en el visor. En este programa solo hay dos, as que las visualizaremos a ambas. Para eso vamos a ?ebug g Add Catc# o presionan Ctrl M .Q. Aparecer un cuadrito de dilogo donde deben escribir el nmero de una variable a visualizar, por ejemplo suma. Presionen 7+:73 y vern que la variable aparece en la ventana Catc#es con un mensaje que dice 9n4no6n value lo que significa "Valor desconocido. Repitan esto y agreguen a / tambin. Ahora correremos el programa paso a paso. Para eso vamos a 3un g Step over o presionamos .S. El programa se recompilar y veremos que el compilador se posar sobre la lnea del BEGN. Ahora veremos paso a paso como es que se realiza una ejecucin. Si ustedes hubieran ejecutado este programa de forma normal, esto se hara instantneamente, sin embargo, ahora el compilador est esperando a que le digamos que avance. Hay dos formas de hacerlo, presionando .S o presionando .Q. Ahora nos quedaremos con .S. La diferencia con la .Q es que esta entrar a los subprogrmas y .S no lo har, pero como an no vimos ese tema no habr diferencia entre una y otra. Al presionar alguna de esas teclas vern que el cdigo avanzar una lnea y har lo que tiene que hacer. Cuando se pare sobre la lnea del Crite, y ustedes presionen F8 o F7, vern aparecer el mensaje en la pantalla del usuario. Cuando presionen .S sobre la lnea del 3eadLnI/J vern que el compilador desaparece para mostrar la consola, esperar que ustedes ingresen la entrada esperada y presionen ENTER, con lo cual volveremos a la pantalla anterior. ngresen un valor mayor a 25 y menor a 50, por ejemplo 45. Ahora vern que / se pone en rojo y su valor se modifica por la entrada ingresada. La variable suma vale 0 porque el compilador as la inicializ, pero nosotros nunca nos fiaremos de eso. Sigan presionando .S para ver el avance del cdigo y vern como se van modificando las variables. De este modo vern como termina el programa. Al finalizar les aparecer un mensaje con el cdigo de salida 0, lo cual indica que todo anduvo bien. Si ustedes quieren terminar la ejecucin antes de lo esperado van a 3un g Program 3eset o presionan Ctrl M .&. Corran de nuevo el depurador pero esta vez ingresen el nmero 20 como entrada a ver que pasa. Saludos a todos, y espero que esto les sea de utilidad de aqu en mas. No lo ense antes porque no tena sentido para los programas que venamos haciendo. Programando desde $% &$' 3epeticin condicional con 37P7A:***9+:(L LECCN 10: Repeticin condicional con REPEAT...UNTL La sentencia REPEAT funciona igual que WHLE y sirve para lo mismo, entonces cul es la diferencia? Escencialmente WHLE repite algo mientras una condicin es verdadera, en contraparte REPEAT lo hace #asta -ue la condicin sea verdadera, o sea, mientras la condicin es 1alsa. Qu ventaja tiene esto? Uno tiende a preguntarse a veces para qu sirve REPEAT ya que, si se repite mientras una condicin es falsa podramos simplemente utilizar WHLE con el operador NOT en su condicin y listo. Sin embargo esto no es tan sencillo. Otra diferencia es que WHLE verifica su condicin antes de entrar en su bloque de instrucciones, REPEAT lo hace al final. Qu significa esto? Veamos un cdigo simple hecho con WHLE: Este programa har aumentar una variable desde 0 hasta 10 mostrando su valor en pantalla y terminar cuando eso suceda: Cdigo: PROGRAM WhileVSRpeat; VAR i: NTEGER; BEGN i:= 0; //nicializamos la variable en 0. WHLE i<10 DO Begin i:= i+1; //Aumentamos el valor de i en 1. Write(i,' '); //mprimimos el valor de i y un espacio de separacin. End; ReadLn; END. Como podrn observar este es un programa bien sencillo. Mientras i sea menor que 10 se repetir el bloque dentro del WHLE. Cuando i valga 10 el WHLE verificar eso y pues no entrar en su bloque y la iteracin terminar. Ahora veamos exactamente el mismo programa en su versin con REPEAT. Esto servir tambin para ver la sintaxis de esta nueva sentencia: Cdigo: PROGRAM WhileVSRpeat2; VAR i: NTEGER; BEGN i:= 0; //nicializamos la variable en 0. REPEAT i:= i+1; //Aumentamos el valor de i en 1. Write(i,' '); //mprimimos el valor de i y un espacio de separacin. UNTL i=10;; ReadLn; END. Este programa hace exactamente lo mismo, solo que ahora en vez de repetirse mientras iY&$, se repite hasta que iH&$. Como ven, la condicin del WHLE es opuesta a la de REPEAT y viceversa. Dado este ejemplo pueden observar que si hay que repetir ms de una instruccin (en este caso eran solo dos), en un WHLE hay que utilizar BEGN y END para delimitar su bloque, pero REPEAT no lleva esta delimitacin ya que se limita por s mismo entre REPEAT y UNTL. De este modo, mientras la sintaxis genrica de un WHLE es Cdigo: WHLE condicion_es_verdadera DO Begin nstruccin1; nstruccin2; . . . nstruccinN; End; la de un REPEAT es Cdigo: REPEAT nstruccin1; nstruccin2; . . . nstruccinN; UNTL condicion_sea_falsa; Con WHLE... DO queramos decir "Mientras... Haz", con REPEAT... UNTL estamos diciendo "Repite... Hasta que". ----- Como ya dije, WHLE verifica su condicin antes de entrar en su bloque de instrucciones, por lo tanto podra suceder que a la primera la condicin fuera FALSE con lo cual WHLE no entrarBa nunca en su cdigo " no se e,ecutarBa nunca. REPEAT verifica su condicin al final, por lo tanto, sabemos siempre -ue esta sentencia se e,ecutar al menos una ve), ya que entrar en su cdigo, har lo que tenga que hacer, y luego mirar la condicin. Esto es lo que nos marca la diferencia esencial entre una sentencia y la otra. La gente tiende a preguntarse cundo usar REPEAT y cuando usar WHLE. Pues bien, la respuesta es: Cuando s -ue una lista de instrucciones debe e,ecutarse al menos una ve) como mBnimoE entonces uso 37P7A:* Si sabemos -ue es admisible -ue la lista de instrucciones pueda +5 e,ecutarse nuncaE entonces usamos C>(L7* Es correcto o incorrecto no discriminar estos casos? Pues si el programa hace lo que tiene que hacer, podramos decir que cada uno puede usar la sentencia con la que mejor se lleve, sin embargo, hacerlo como he descrito ayuda a una mayor legibilidad del cdigo fuente ya que al ver un REPEAT sabemos que lo que sea que este haga debe hacerse al menos una vez. 7,emplo% Veamos un programa en el que se le pedir al usuario ingresar un nmero entero. Si este nmero es menor que 20, iteraremos hasta dejarlo en 20, mostrando siempre los nmeros en pantalla: 0ersin C>(L7% Cdigo: PROGRAM WhileVSRepeat3; VAR num: NTEGER; BEGN Write('ngresa un nmero entero: '); ReadLn(num); WHLE num<20 DO Begin num:= num + 1; Write(num,' '); End; ReadLn; END. Como ven, en este programa, si el usuario ingresa de entrada un nmero mayor o igual que 20 el WHLE no se ejecutar en absoluto, en caso contrario s lo har y se repetir tantas veces como sea necesario. 0ersin 37P7A:% Cdigo: PROGRAM WhileVSRepeat4; VAR num: NTEGER; BEGN Write('ngresa un nmero entero: '); ReadLn(num); REPEAT num:= num + 1; Write(num,' '); UNTL num>=20; ReadLn; END. Cul es la diferencia entre este programa y el anterior? Pues si en el anterior programa el usuario ingresaba el nmero 20 el WHLE no se ejecutaba y la variable no aumentaba su valor. En este programa, aunque REPEAT se repetir hasta que la variable valga 20, si el usuario ingresa justo ese nmero el bloque del REPEAT se ejecutar igual porque esta sentencia verificar el valor de num justo al final de su bloque. ncluso se ejecutar aunque el usuario ingrese un nmero ms alto que 20 comprenden? ----- Para el programa del Adivinador que les fue solicitado en la Leccin 8 Qu conviene ms utilizar? WHLE o REPEAT? Yo les dira que REPEAT, porque saben que el usuario intentar adivinar al menos una vez pudiendo adivinar o no. Si adivina, pues genial, si no adivina se seguir repitiendo. Con WHLE ustedes estarn obligados a hacer que las condiciones sean falsas para que entre en el bloque al menos una vez. ------------------------------------------------------------------------------------- Centinela: Veremos ahora, aunque sin usar REPEAT un ejemplo de iteracin por centinela. Un centinela es un valor que tomar nuestra variable para indicar el fin de la iteracin, algo as como una bandera booleana, pero aplicado a otras variables. Vemoslo para comprenderlo mejor. El siguiente programa ir leyendo de la entrada estndar una serie de nmeros enteros positivos y realizando su suma hasta que se ingrese un negativo. En ese caso ya no se leern ms nmeros y luego se mostrar la suma de todos los nmeros ingresados (excepto el negativo): Cdigo: 1 PROGRAM centinela; 2 3 Var 4 numero, suma : integer; 5 6 BEGN 7 (* lectura inicial *) 8 ReadLn(numero); 9 10 (* inicializacin *) 11 suma:= 0; 12 13 WHLE numero > 0 DO 14 Begin 15 (* acumulacin *) 16 suma:= suma + numero; 17 (* siguiente lectura *) 18 ReadLn(numero); 19 End; 20 21 (* mostrar resultado *) 22 WriteLn('La suma de los nmeros es: ', suma); 23 END. Bien, en la lnea 8 leemos el primer valor que debemos sumar. En la lnea 10 inicializamos la variable suma con el valor $ ya que an no ha sumado nada. En la lnea 13 comienza el WHLE solo si el nmero que ingresamos es mayor que 0, en caso contrario no se ejecutar. Aqu vemos por qu es mejor utilizar un WHLE que un REPEAT, ya que si el usuario ingresa como primer valor un nmero negativo ya no habr nada para sumar. En caso de entrar en el WHLE aumentamos el valor de la variable suma sumando su valor anterior al valor del nmero ledo, o sea, al valor de numero. En la lnea 18 volvemos a leer un nmero y el WHLE volver a su encabezado. Si el nuevo nmero ledo es menor que 0 ya no habr iteracin y en caso contrario s. Luego de haber salido del WHLE mostramos al usuario el resultado de la suma. Bien, esto era para mostrar la idea de centinela. En este caso nuestro centinela es cualquier nmero negativo ingresado por el usuario ya que ste ser el que detenga la iteracin del WHLE. Veremos muchos ms ejemplos de centinelas de aqu en adelante. 7,ercicio% Si #an #ec#o el programa del Adivinador con C>(L7E a#ora #ganlo con 37P7A:* ------------------------------------------------------------------------------------- 9n e,emplo ms comple,o% Contador de palabras% Ahora veremos un ejemplo de programa que cuente la cantidad de palabras en una lnea de texto que ser ingresada por el usuario. Dicho texto debe terminar con un espacio y un punto s o s (centinelas). Cmo funcionar el programa? Leeremos todo caracter a caracter, nada de usar Strings. Consideraremos palabra todo aquello que no es un espacio, por lo tanto, letras sueltas tambin son palabras. Como en primera instancia el usuario puede escribir un texto que comience con espacios en blanco, usaremos un REPEAT para ir leyendo todos esos espacios hasta encontrar otra cosa. Luego de eso entraremos en un bucle principal dominado por un WHLE, esto es porque nuestro centinela es el punto (.) y puede suceder que el usuario ingrese un punto como inicio del texto o un punto luego de los espacios iniciales; en cualquiera de esos casos WHLE no entrar en su cdigo. Mientras no encontremos ese punto (.), leeremos los caracteres hasta hallar un nuevo espacio con lo cual habremos consumido una palabra, luego volvemos a usar, dentro de WHLE esta vez, un REPEAT para consumir espacios en blanco ya que entre una palabra y otra el usuario puede poner varios espacios consecutivos: Cdigo: 1 PROGRAM cuenta_palabras; 2 3 Const 4 ESPACO= ' '; 5 FN= '.'; 6 7 Var 8 caracter: char; //Caracter ledo. 9 cantidadPalabras: integer;//Cantidad de palabras contadas. 10 11 BEGN 12 //Salteamos todos los espacios al inicio del texto. 13 Repeat 14 read(caracter) 15 Until caracter <> ESPACO; 16 17 //En cada iteracin consumiremos una palabra. 18 While caracter <> FN do 19 begin 20 //Leemos caracteres hasta encontrar un espacio. 21 Repeat 22 read(caracter); 23 Until caracter = ESPACO; 24 25 //Aumentamos en 1 el contador. 26 cantidadPalabras:= cantidadPalabras + 1; 27 28 //Salteamos los espacios que separan las palabras. 29 Repeat 30 read(caracter) 31 Until caracter <> ESPACO; 32 end; //Del While. 33 34 35 writeln('La cantidad de palabras en el texto es: ',cantidadPalabras); 36 END. Les dejar como tarea que estudien este cdigo hasta que lo entiendan completamente. Fjense como implementamos distintos REAPEAT dentro de un WHLE y como usamos el procedimiento READ para siempre ir leyendo sobre la misma lnea. No olviden las constantes declaradas al inicio del programa. Los comentarios son su gran gua y eso es algo muy importante para un programador. Si deben trabajar con el cdigo de su compaero de trabajo debern ser capaces de entender sus cdigos basados en que saben la tarea que desempea su programa, las variables que declaro tienen nombres mnemotcnicos y sus comentarios indican bien cada accin aunque sin extenderse o abusar de ellos. Todo esto es realmente muy importante que aprendan a implementarlo. Por si alguno de ustedes no lo sabe, un nombre mnemotcnico es aquel que ayuda a saber el propsito de una variable, por ejemplo, en este programa la variable que guarda el valor de cuantas palabras se cuentan se llama cantidadPalabras. Bien poda haberse llamado cont que es una abreviacin de contador o podra haber tenido cualquier otro nombre. Usen nombres mnemotcnicos aunque sean largos, esto ayuda a prescindir un poco de los comentarios y a que el cdigo sea ms entendible. ------------------------------------------------------------------------------------- 7,emplo de captura de error% En el siguiente ejemplo veremos un programa simple que le pedir al usuario que ingrese un valor entero. En esta ocasin veremos como leer estos valores como caracteres y luego si son correctos pasarlos a enteros tal como debera ser. Primero veamos algo que debera haber nombrado ya hace bastante pero sin embargo decid aplazarlo hasta ahora. En algunas partes de este curso nombr algo as como Vel ordinal de un elementoV o Vtipos ordinalesV y dije que estos eran los tipos que tenan finita cantidad de elementos y que adems, dado un elemento, podamos saber cul le segua (sucesor) y cual estaba detrs (predecesor). Los tipos ordinales de Pascal son aquellos que estn acotados, o sea, que tienen un inicio y un final. Tal es el caso del tipo (+:7;73, que est acotado inferiormente por el valor 'DQRS y superiormente por MA`(+: que vale DQRQ. Ninguna variable del tipo integer puede exceder estos valores. Si han activado el range c#ec4ing tal como se los indiqu al inicio del curso deberan recibir un error en tiempo de compilacin al intentar guardar en una variable entera algn valor fuera del intervalo h'DQRSE DQRQi, de lo contrario el error lo obtendrn en tiempo de ejecucin. Adems de esto, el tipo dado un elemento del tipo NTEGER podemos saber quin est detrs y quin delante, por ejemplo, dado el nmero entero 5 sabemos que detrs est el 4 y delante el 6. Para el nmero -32768 no existe predecesor porque es el primer entero existente para pascal, al igual que para MAXNT, que no existe sucesor porque es el entero ms grande que pascal puede representar. Tenemos el tipo C>A3, que contiene todos los caracteres existentes. Obviamente este tipo es acotado ya que tiene una cantidad finita de elementos y adems, dado un caracter podemos saber cul es su predecesor y su sucesor. El tipo 37AL no es acotado ya que posee una cantidad infinita de elementos. Nunca se puede determinar el siguiente a un real. Cul nmero es el siguiente a 1.5? Tal vez el 1.6? No porque antes est el 1.55, pero antes de ese est el 1.51, pero antes est el 1.501, y as podramos continuar infinitamente. Siempre entre dos nmeros reales cualesquiera hay infinitos reales. Esto en matemticas es llamado densidad de los reales. Lo importante aqu es hablar del ordinal de un carcter. Los caracteres estn todos incluidos, para Free Pascal (existen otras tablas), en una tabla llamada :abla Ascii. Esta tabla le asigna a cada carcter un valor numrico segn su posicin. Para ver la tabla Ascii en el DE simplemente vayan al men :ool ''Z Ascii table. src="http://i30.servimg.com/u/f30/16/10/20/71/aprend29.jpg" border="0" alt="" En esa imagen el cursor est posicionado sobre el smbolo j. Como vemos, a este carcter le corresponde el valor RN. Ese valor es el ordinal de j. Si nosotros tenemos un carcter cualquiera y queremos saber su ordinal debemos usar la funcin 53?. Por ejemplo si escribiramos 53?IjJ obtendramos el entero RN como resultado. A la inversa tenemos la funcin C>3 que dado un entero nos devuelve su correspondiente carcter en la tabla. Si escribiramos C>3IRNJ obtendramos como valor devuelto el carcter j. La funcin C>3 dado un elemento del tipo nteger devuelve uno del tipo CHAR. La funcin 53? transforma un carcter en entero, o sea, de un tipo c,ar obtenemos un tipo integer. Esto es lo que usaremos para, dado un carcter numrico, obtener el entero de ese carcter, o sea, dado el carcter b&c obtener el nmero &. Sin embargo no es tan fcil, observen ustedes en la tabla que al carcter b$c le corresponde el entero NS ya que est en la posicin 49 de la tabla (la primera posicin es la 00). Al carcter b&c le corresponde el entero 49 y as sucesivamente. Por lo tanto si nosotros leyramos un carcter de la entrada estndar, suponiendo que el usuario ingres el b&c, al hacer 53?Ib&cJ obtendramos el nmero 49 y no el nmero 1. A alguno de ustedes se les ocurre como, dado un carcter numrico, obtener su valor en entero? O sea, si me dan el bc obtener el , si me dan el bSc obtener el S, y as. Como pueden observar, los lugares de la tabla estn ordenados ascendentemente, por lo cual si al b$c le corresponde el NS, al b&c le corresponde el N^, al bc el O$ y as hasta el b^c que le corresponde el OQ. Entonces que pasa si al ordinal de cualquier carcter numrico le resto el ordinal de b$c? Por ejemplo, si me dan el b$c, resto ese ordinal con el ordinal de b$c: 5rdIb$cJ ' 5rdIb$cJH NS f NSH $. Obtuve el entero 0. Ahora si me dieran el carcter b&c y a su ordinal le resto el ordinal de b$c: 5rdIb&cJ ' 5rdIb$cJH N^ f NSH &. Obtuve el entero 1. De tener el b^c y restarle a su ordinal el ordinal de K$K tendra: 5rdIb^cJ ' 5rdIb$cJH OQ f NSH ^. Obtuve el entero 9. NOTA: El ordinal de un entero es el mismo entero: Ord(57)= 57. El ordinal de un boolean es 1 para TRUE y 0 para FALSE. ------------------------- Vayamos al ejemplo entonces. Le pediremos al usuario que ingrese un entero, pero lo leeremos como caracter, o sea, como un elemento del tipo CHAR. Si los caracteres ledos difieren de los numricos le diremos al usuario que hay error, sino, transformaremos los caracteres a enteros. Para este programa usaremos la funcin 75L+ que es TRUE cuando el cursor de la entrada estndar est en el fin de la lnea y FALSE en caso contrario. Esta funcin es primitiva de Pascal, o sea, la tenemos siempre disponible. Como pueden ver, es una funcin booleana ya que nos dar un valor TRUE o un valor FALSE. Veamos el ejemplo: Cdigo: 1 PROGRAM enteros; 2 3 Var 4 car: char; //Caracter ledo. 5 entero: integer; //Guardar el valor del caracter pero en NTEGER. 6 error: boolean; //TRUE si el usuario no ingresa un entero. 7 8 9 BEGN 10 11 12 //Mostramos un mensaje al usuario y leemos la entrada. 13 write('ngrese un entero: '); 14 read(car); 15 //Damos la condicin de error. 16 error:= (ord(car)<48) or (ord(car)>57); 17 18 f not error then 19 entero:= ord(car)-ord('0'); 20 21 //Leemos hasta el fin de lnea o hasta que haya error. 22 while (not eoln) and (not error) do 23 begin 24 //Leemos el siguiente caracter. 25 read(car); 26 27 //Verificamos que el caracter sea uno numrico. 28 error:= (ord(car)<48) or (ord(car)>57); 29 30 f not error then 31 entero:= (entero*10)+(ord(car)-ord('0')); 32 end; 33 34 f not error then 35 writeln('El entero ingresado es: ',entero) 36 else 37 writeln('No ha introducido un entero.'); 38 39 END. En este programa se pide un entero, pero el si el usuario ingresa cualquier otra cosa, el programa no caer, sino que mostrar un mensaje de error. Como primer ejercicio tienen que entender este programa y modificarlo para que funcione con REPEAT. ------------------------------------------------------------------------------------- 7,ercicios% No continen hasta no ser capaces de resolver todos estos ejercicios. 7,ercicio% Determinen cules de los siguientes segmentos de cdigo producen la misma salida al ser ejecutados: aJ Cdigo: i := 1; j := 2; REPEAT Write(i, j); i := i + 1; j := j + 1 UNTL j <= 3; bJ Cdigo: i := 1; j := 1; WHLE (i <= 3) AND (j <= 2) DO BEGN Write(i, j + 1); i := i + 1; j := j + 1 END; cJ Cdigo: i := 1; REPEAT Write(i, i + 1); i := i + 1 UNTL i <= 3; ----------------------------------------------------------------- 7,ercicioD: Se desea tener un programa que calcule el saldo de una cuenta. Supongan que los datos son ledos de la entrada estndar y que constan de renglones, cada uno de los cuales contiene una letra en la primera columna, seguida de un valor real. El ltimo rengln contiene nicamente la letra X en la columna uno. El primer rengln contiene la letra A y el saldo anterior de una cuenta de cheques. Los dems renglones contienen la letra D y el importe de un depsito o la letra R y el importe de un retiro. Escriban un programa que determine el saldo exacto de la cuenta despus de procesar las transacciones. Asumimos que las entradas sern siempre correctas. Ejemplo: A 1200.35 D 64.12 R 390.00 R 289.67 D 13.02 R 51.07 X El saldo final es 546.75 ----------------------------------------------------------------- 7,ercicioN: Dado un fragmento de texto que debe ser ledo de la entrada estndar, todo en una lnea, y terminado por el caracter $ (centinela), determine y exhiba las consonantes y vocales que aparecen duplicadas en forma contigua. Por ejemplo, el texto "llama al chico que lee$ tiene una consonante doble (ll) y una vocal doble (ee) y se debera desplegar: "ll ee. (Todas las letras son minsculas). ----------------------------------------------------------------- 7,ercicioO: Realicen las funciones de una calculadora simple. Los datos de entrada sern una secuencia de dgitos enteros y los operadores +, *, / y -, seguida de un signo =. Hagan caso omiso de los espacios en blanco. Los operadores se aplican en el orden en que aparecen en los datos de entrada, o sea que olvdense de la precedencia, y producen resultados enteros, o sea, si bien se ingresa el operador de la divisin con el smbolo /, el comportamiento es el de DV. Asuman que se ingresa al menos un nmero. Ej. de entrada: 4 + 3 / 2 * 8 - 4 = Ej. de salida: 20 Como ven, las operaciones se fueron realizando en el orden en el que aparecan. Primero 4+3 que es 7, eso lo dividimos entre 2 (div) que es 3, luego eso multiplicado por 8 que es 24 y luego eso menos 4 que es 20. Una verdadera calculadora habra hecho primero 3/2 que con DV da 1 y luego eso por 8 que da 8. Luego hara 4+8-4 que es igual a 8. Sin embargo programar eso requiere ms herramientas de las que poseen. ----------------------------------------------------------------- 7,ercicioR I?(.(C(LJ: Escriban un programa que lea una letra y una oracin de la entrada estndar (de una sola lnea), y calcule la cantidad de palabras que terminan con la letra y estn en la oracin dada. Asuman que la oracin siempre terminar con un punto y que las palabras estarn separadas solo por espacios (no habr comas ni nada de eso). Asuman tambin que la oracin tendr siempre al menos una palabra. Ejemplos: Letra: s Oracin: La cualidad indispensable para un buen cocinero es la puntualidad pero es tambin la de los invitados. Salida: 4 Letra: r Oracin: Un discpulo de quien jams se pide nada que no pueda hacer nunca hace todo lo que puede. Salida: 1 Letra: o Oracin: No basta tener buen ingenio lo principal es aplicarlo bien. Salida: 4 Modifiquen su programa para que cuente las palabras que comienzan con la letra dada. Este es un ejercicio que los har pensar y luchar mucho. ntenten hacerlo bajo todos los medios posibles. Todo lo dado hasta ahora basta y sobra para lograrlo. Si no logran realizar esto posteen aqu y los ir guiando, no les dar el cdigo as de entrada porque no tiene caso leer un programa ya hecho si ustedes no intentan realizarlo primero poniendo todas las ganas de aprender. Este curso es para ustedes y requiere todo su esfuerzo. No hay otro medio para aprender a programar. Mi esfuerzo fue escribir esto, ustedes practiquen y practiquen, pregntenme sus dudas y sigan intentando, o bien posteen aqu. Los frutos se vern al final. Mucha suerte. ------------------- Con esto hemos terminado la segunda parte del curso. En la tercera parte del curso aprenderemos a definirnos nuestros propios tipos de datos, o sea, como crear un tipo a nuestro antojo y luego declarar variables de ese tipo. Esto complicar un poquito ms las cosas, pero tambin les dar muchas posibilidades a la hora de programar, ya que con los tipos primitivos de pascal no podemos hacer mucho ms. Programando desde $% &&' Subrangos " Arreglos lineales* ntroduccin a los TPOS definidos por el programador Leccin 11: Subrangos y Arreglos lineales (ntroduccin% Hasta ahora hemos visto como crear programas que puedan hacer una cosa u otra en funcin de ciertas condiciones, como hacer que repitan ciertas instrucciones tambin de forma condicional, entre otras cosas. En todos esos programas hemos usado variables de distintos tipos, sin embargo siempre han sido tipos primitivos de Pascal, o sea, los que ya estn predefinidos por el lenguaje, tales como REAL, STRNG, CHAR, NTEGER, etc. Sin embargo es posible que el programador defina tipos propios que pueden contener datos ms complejos que simples nmeros, caracteres o cadenas. Obviamente esto no es totalmente libre porque seguir dependiendo de los tipos primitivos, pero dada nuestra imaginacin podemos crear tipos realmente muy complejos y que contengan mucha informacin. Los posibles tipos que podemos definir nosotros mismos son: o Subrangos o Arreglos o Conjuntos o Enumerados o Registros o Punteros Todos excepto Punteros, al igual que los tipos primitivos, corresponden a tipos estticos de Pascal. Esto significa que declarada una variable de uno de esos tipos se asignar de la memoria el espacio suficiente para albergar el mayor valor posible. Este espacio de memoria estar en uso aunque nosotros no usemos la variable declarada o aunque usemos solo una parte de la informacin que esta pueda guardar. Este espacio de memoria se asigna ya al compilar el programa, o sea, en tiempo de compilaciIn. Esto no significa que al compilar el programa estemos ocupando nuestra RAM con las variables que el programa use, sino que al compilarlo se agregan las instrucciones que harn que el programa solicite esa memoria ya al ser ejecutado y la mantendr siempre en uso hasta que se cierre. Los Punteros corresponden a un tipo dinmico. Esto es que, podremos pedir memoria cuando la necesitemos y devolverla cuando ya no la usemos, todo en tiempo de e,ecucin, pero este ser el ltimo tema de este curso. ------------------------------------------------------------------------------------- Subrangos% Muy bien, el primer tipo a definir por el usuario que veremos es llamado subrango. Este es el tipo ms sencillo de declarar. Consiste en crear un Subrango de uno de los tipos primitivos ordinales de Pascal. Por ejemplo, un Subrango de los enteros podran ser los naturales, ya que estos son lo enteros de 0 en adelante (algunos los toman de 1 en adelante). Los tipos a definir se declaran antes que las variables pero luego que las constantes. Para ello debemos indicar mediante la palabra reservada :VP7 que haremos declaracin de tipos. Veamos un ejemplo de declaracin de subrangos: Cdigo: Type Naturales= 0..MAXNT; Mes= 1..12; Decimal= 0..9; Minusculas= 'a'..'z'; Digito= '0'..'9'; Mayusculas= 'A'..'Z'; Aqu hemos declarado seis tipos Subrangos diferentes. Como ven la sintaxis es bien sencilla, luego de la palabra TYPE se declaran todos los tipos necesarios de esta manera: (denti1icadorH valorFinicial**valorF1inalG En este ejemplo tenemos el tipo +aturales que contendr valores enteros entre 0 y MAXNT. Luego est el tipo Mes que contendr enteros entre 1 y 12. ?ecimal contendr valores entre 0 y 9. Luego vemos tres subrangos de caracteres: Minusculas que contendr los caracteres de la a a la ). Esto es porque las letras estn ordenadas segn la :abla Ascii ascendentemente y sabemos que bacYc)c. ?igito contendr los caracteres del '0' al '9'. Notar que ?igito contiene los caracteres numricos y ?ecimal los valores enteros de esos nmeros. +5 7S L5 M(SM5. Finalmente tenemos el tipo Ma"usculas que contiene caracteres de la A a la Z. Dado que estos son tipos, para usarlos debemos declarar variables de ese tipo: Cdigo: Type Naturales= 0..MAXNT; Mes= 1..12; Decimal= 0..9; Minusculas= 'a'..'z'; Digito= '0'..'9'; Mayusculas= 'A'..'Z';
Var letraMin: Minusculas; numero: Naturales; letraMay: Mayusculas; Como ven es la misma sintaxis que para declarar una variable de tipo primitivo, le damos un identificador, dos puntos y luego el nombre del tipo. Esto significa que la variable letraMin podr tomar valores de la a a la ) ya que es del tipo Minusculas. Como el Subrango Minusculas corresponde a un Subrango de caracteres, letraMin se comportar como una variable c,ar con la diferencia de que no podr tomar valores fuera del rango indicado por Minusculas. Si esto sucede tendremos un error en tiempo de ejecucin. Si han activado 3ange c#ec4ing como se los indiqu al inicio del tutorial, el compilador verificar esto en la medida de lo posible y se los advertir, pero no siempre podr hacerlo. Por ejemplo, si ustedes hacen readIletraMinJ el compilador no podr asumir que el usuario puede ingresar un carcter fuera del rango y por tanto compilar correctamente, pero si hacen, letraMin%H bAc les advertir su error. Hay ms casos de esto, pero lo vern en la prctica. Lo mismo sucede para los subrangos ?ecimal, Mes y +aturales, que son subrangos de integer. Las variables de estos tipos funcionarn como variables enteras con la diferencia de que deben tomar valores dentro de los rangos establecidos. Visto de esta manera no puedo incentivarlos mucho con el uso de los subrangos, sin embargo veremos que resultan tiles para definir Arreglos, que es el tema que viene a continuacin. Lo que puedo decirles es que al definir un Subrango ustedes podrn estar seguros de que sus variables tendrn los valores adecuados, mas all de que sean ustedes mismos quienes deban controlar esos valores. ------------------------------------------------------------------------------------- Arreglos% >eclaraciIn: Muy bien, ahora s se viene algo ms interesante. Este es un tema muy importante y debern aprenderlo bien, ya que los arreglos son estructuras usadas para casi todo y en la mayora de los lenguajes. Un arreglo es una tabla compuesta por celdas que contienen, todas, valores de un mismo tipo. Ese es un ejemplo de un arreglo de enteros compuesto por nueve celdas. Cada celda tiene un valor distinto (pueden no serlo) y cada una es independiente de las dems. Como pueden ver todas las celdas estn numeradas del 1 al 9. Estos valores son llamados subndices y son los que usaremos para dirigirnos a una celda especfica. Veamos primero cmo se declara un arreglo: (denti1icadorH arra"hSubrangoi o1 tipoG Debemos indicar un nombre para el arreglo (identificador), luego, al igual que para los subrangos va un signo de igual ( = ) y la palabra reservada arra" (arreglo en ingls) seguida inmediatamente por un Subrango entre parntesis rectos hi el cual indicar la dimensin del arreglo (cuantas celdas tendr). Luego colocamos la palabra reservada o1 y un tipo para los valores que habr en cada celda. Este tipo puede ser uno primitivo de Pascal o uno definido anteriormente por el programador. Veamos algunos ejemplos: El arreglo dibujado arriba podra estar declarado como: Cdigo: Arreglo1= array[1..9] of integer; En este ejemplo le dimos el nombre Arreglo&. Declaramos directamente entre los parntesis rectos un Subrango. La dimensin de ese Subrango indica la dimensin del arreglo, en este caso el Subrango va de 1 a 9 por tanto contiene 9 elementos. Esto indica que el arreglo tendr nueve celdas. Es importante notar que esto indica solo la dimensin del arreglo y no el tipo de datos que contendr, o sea, Arreglo& no contendr datos que solo vayan de 1 a 9 sino que contendr cualquier entero en sus celdas ya que su tipo est declarado luego de o1 y es integer. El Subrango entre parntesis rectos, adems de indicar cuntas celdas tendr el arreglo, tambin indica cmo se numeran. Arreglo& tendr 9 celdas numeradas del uno al nueve, sin embargo, de haberse declarado Cdigo: Arreglo1= array[10..19] of integer; sera igual al anterior solo que sus nueve celdas estaran numeradas del 10 al 19, o de haberse declarado de esta manera Cdigo: Arreglo1= array['a'..'i'] of integer; seguira teniendo nueve celdas solo que estaran identificadas de la a a la i. Lo ms comn es numerarlas del 1 en adelante y es lo recomendable. Tal como hemos declarado esos arreglos estamos declarando sus dimensiones con subrangos annimos, o sea, declarando estos justo dentro de los parntesis rectos sin darles nombre alguno. Sin embargo tambin es posible colocar dentro de estos parntesis un Subrango ya declarado anteriormente. Por ejemplo: Cdigo: Type Decimal= 0..9; Arreglo1= array[Decimal] of integer; Como ven, teniendo declarado antes el Subrango ?ecimal es posible utilizarlo para definir la dimensin y numeracin del arreglo. En este caso Arreglo& tendr 10 celdas numeradas del 0 al 9. Tambin es posible hacer esto Cdigo: Type Decimal= 0..9; Arreglo1= array[Decimal] of Decimal; En este caso, el arreglo tiene 10 celdas numeradas del 0 al 9 y cada una puede contener datos del tipo ?ecimal. Siempre es posible utilizar algn tipo para definir otro s y solo s el tipo a utilizar est definido anteriormente. No sera posible utilizar ?ecimal para definir el arreglo si declarramos este Subrango ms abajo que el arreglo. Un arreglo es un tipo y por tanto va declarado luego de la palabra :"pe tal como se ve en estos dos ejemplos. Veamos ahora ms ejemplos de arreglos: Cdigo: Type rango = 33..90; arr1 = array [char] of integer; (* 256 celdas *) arr2 = array [33..90] of real; arr3 = array [integer] of char; (* demasiado grande! *) arr4 = array [rango] of boolean; Tenemos un Subrango de enteros que va de 33 a 90. Luego tenemos arr& que es un arreglo de 256 celdas (cantidad total de caracteres) cuyos ndices segn la Tabla Ascii van del ' ' a ' ' (del primer elemento de la tabla hasta el ltimo) donde cada cela puede contener cualquier entero. arr que es un arreglo de 57 celdas numeradas del 33 al 90 donde cada una puede contener cualquier real. Luego tenemos arrD que pretendera ser un arreglo de unas 65536 celdas numeradas desde el -32768 hasta el 32767 donde cada una podra contener caracteres. Este es un arreglo exorbitantemente grande, ocupara muchsima memoria y provocara muchos problemas. Adems no es para nada tico crear este tipo de estructuras. Finalmente tenemos arrN que tiene 57 celdas numeradas del 33 al 90 donde cada una es un booleano que puede valer TRUE o FALSE. ------------------------------------------------------------------------------------- 9tili)acin de arreglos% Hasta ahora solo hemos visto como se declara un arreglo y lo que significan las distintas declaraciones, sin embargo hace falta trabajar con ellos, y su sintaxis es un poco distinta a lo que venimos acostumbrados. Veremos un primer ejemplo donde crearemos un arreglo de enteros de 10 celdas cuyos ndices van del 1 al 10 y a cada celda le daremos el mismo valor que su ndice, o sea, a la primera le daremos el valor 1, a la segunda el 2 y as sucesivamente: Cdigo: 1 PROGRAM arreglos; 2 3 Type 4 arr= array[1..10] of integer; 5 6 Var 7 arreglo1: arr; 8 9 BEGN 10 arreglo1[1]:= 1; 11 arreglo1[2]:= 2; 12 arreglo1[3]:= 3; 13 arreglo1[4]:= 4; 14 arreglo1[5]:= 5; 15 arreglo1[6]:= 6; 16 arreglo1[7]:= 7; 17 arreglo1[8]:= 8; 18 arreglo1[9]:= 9; 19 arreglo1[10]:= 10; 20 END. En la lnea 3 indicamos que comenzar la declaracin de tipos para, luego, en la lnea 4 declarar el tipo arr que ser un arreglo de 10 celdas numeradas del 1 al 10 del tipo entero. Como arr es un tipo su propsito es declarar variables de ese tipo, por lo tanto en la lnea 7 declaramos la variable arreglo& del tipo arr. Podemos, al igual que con los tipos primitivos, declarar tantas variables como queramos de cualquier tipo que nosotros mismos definamos; en este caso tenemos solo una, pero podra tener ms y cada una sera independiente. Bien, en la lnea 9 comienza nuestro programa, el cual consta de diez lneas de asignacin donde en cada una le damos un valor a cada celda del arreglo. Veamos esto con detalle, es bien sencillo. Cada celda del arreglo 1unciona como una variable independiente, por tanto, en ese arreglo tenemos diez variables del tipo integer. Para referirnos a una celda debemos dar el nombre de nuestro arreglo (no el nombre del tipo sino el de la variable de ese tipo) seguido por el ndice entre parntesis rectos de la celda a la que queremos ir. De este modo, en la lnea 10, al escribir arreglo&h&i%H & estamos diciendo que vaya a la primera celda de arreglo& y le asigne el valor 1. La sintaxis genrica sera 0ariableFdelFtipoFarreglohindiceFdeFlaFceldai con lo cual nos referiramos a cualquier celda. Recordar que cada una es una variable independiente, por tanto esa declaracin es como si fuera el nombre de la variable y funciona igual que cualquier otra variable, valga la redundancia. Todo lo que sigue del programa es asignar a las celdas restantes el valor que queremos y termina nuestro programa. Sin embargo no es muy til tener que escribir instruccin por instruccin para dar un valor a cada celda. maginen un arreglo de 1000 celdas, tendramos un programa de 1000 lneas solo en asignaciones. Veamos el mismo programa pero asignando los mismos valores a cada celda de una forma ms inteligente: Cdigo: 1 PROGRAM arreglos; 2 3 Type 4 arr= array[1..10] of integer; 5 6 Var 7 arreglo1: arr; 8 i: integer; 9 10 BEGN 11 For i:=1 to 10 do 12 arreglo1[i]:= i; 13 END. Hemos sustituido las 10 lneas de asignacin por una instruccin FOR que va de 1 a 10. Fjense que hemos colocado la variable de control i dentro los parntesis rectos que indican el ndice de nuestras celdas. De este modo, cuando i valga 1 estaremos hablando de la primera celda, cuando i pase a valer 2 estaremos hablando de la segunda celda, y as sucesivamente hasta 10. En este caso hemos asignado a cada celda el mismo valor de su ndice, pero esto podra no ser as. Este arreglo dibujado sera: Ahora veamos lo mismo pero asignando el doble del ndice a cada celda: Cdigo: 1 PROGRAM arreglos; 2 3 Type 4 arr= array[1..10] of integer; 5 6 Var 7 arreglo1: arr; 8 i: integer; 9 10 BEGN 11 For i:=1 to 10 do 12 arreglo1[i]:= i*2; 13 END. De este modo arreglo& ahora quedara as: Dentro de los parntesis rectos que indican el ndice del arreglo es posible, como hemos visto ya, colocar el valor del ndice, una variable del tipo correcto o, como no hemos visto an, una expresin que d cmo resultado un valor del tipo correcto y que est dentro del rango de ndices posibles. Es muy importante que lo que est dentro de los parntesis rectos nunca exceda el rango en que est numerado el arreglo. Si en este ejemplo nosotros escribiramos Cdigo: For i:=1 to 11 do arreglo1[i]:= i*2; se producira un error cuando i alcanzara el valor 11 y el programa se cerrara abruptamente ya que la celda 11 no existe. Si han activado 3ange c#ec4ing lo ms probable es que el compilador les avise antes, pero esto no es siempre seguro ya que no siempre es detectable que podemos estar salindonos del arreglo. Veamos un nuevo ejemplo del mismo programa, solo que ahora los ndices sern caracteres y a cada celda le asignamos el valor del ordinal de su ndice. No olviden que el arreglo es de enteros. Cdigo: 1 PROGRAM arreglos; 2 3 Type 4 arr= array['a'..'j'] of integer; 5 6 Var 7 arreglo1: arr; 8 i: char; 9 10 BEGN 11 For i:='a' to 'j' do 12 arreglo1[i]:= ord(i); 13 END. De este modo nuestro arreglo quedara as: ------------------------------------------------------------------------------------- >acer C3(:7 " 37A? de un arreglo% Si quisiramos desplegar un arreglo en la pantalla, o sea, que se nos muestren todos sus valores, debemos escribir celda por celda. En el ejemplo anterior tenamos el arreglo llamado arreglo&. Como primer impulso para escribirlo en pantalla uno tendera a hacer algo como esto Cdigo: write(arreglo1); y sin embargo eso no es posible. De hacerlo tendrn un error en tiempo de compilacin en el cual el compilador se les quejar por no poder escribir o leer variables de ese tipo. Esto es porque un arreglo es una estructura de datos y no un valor especfico. Por este motivo es que debemos escribir celda por celda. No se olviden que cada celda es como una variable ms y funciona del mismo modo. Veamos entonces como mostrar el arreglo de nuestro ejemplo anterior: Cdigo: 1 PROGRAM arreglos; 2 3 Type 4 arr= array['a'..'j'] of integer; 5 6 Var 7 arreglo1: arr; 8 i: char; 9 10 BEGN 11 For i:='a' to 'j' do 12 arreglo1[i]:= ord(i); 13 14 For i:='a' to 'j' do 15 Write(arreglo1[i],' '); 16 END. La nica diferencia entre este programa y el anterior es que agregamos un FOR que en cada iteracin escribe el valor de una de las celdas. Verifiquen esto ustedes mismos. 7,ercicio% Modifiquen este programa para que con un solo FOR asigne los valores al arreglo y lo muestre en pantalla. Del mismo modo, si quisiramos hacer read de un arreglo para que el usuario ingrese los valores de cada celda debemos hacerlo para cada una por separado. 7,ercicio: Realicen un programa en el cual exista un arreglo de enteros de cinco celdas de modo que el usuario sea quin ingrese los valores para cada celda. Deben utilizar una instruccin FOR para ello. =============================================== ?eclaracin annima de un arreglo% Los arreglos que hemos visto hasta ahora los hemos declarado como tipos de modo que podemos declarar muchas variables de ese tipo. Sin embargo, a veces sucede que sabemos que vamos a usar un nico arreglo en nuestro programa y nada ms. Dado este caso no es necesario declarar el arreglo como tipo sino hacerlo de forma annima, directamente como variable. Veamos esto con el programa anterior ya que tenemos un nico arreglo en este: Cdigo: 1 PROGRAM arreglos; 2 3 Var 4 arreglo1: array['a'..'j'] of integer; 5 i: char; 6 7 BEGN 8 For i:='a' to 'j' do 9 arreglo1[i]:= ord(i); 10 11 For i:='a' to 'j' do 12 Write(arreglo1[i],' '); 13 END. Como ven este programa es igual al anterior solo que hemos quitado la declaracin de tipos y hemos declarado el arreglo directamente como variable. De este modo solo se usar como arreglo& y no como tipo por lo cual no podremos declarar variables como en los casos anteriores. No est mal si declaran siempre los arreglos como tipo, pero tengan en cuenta que un arreglo como tipo ocupa ms memoria que uno declarado annimamente. Si han declarado un tipo array el programa guardar memoria para "recordar que existe un tipo definido por ustedes y qu datos puede contener y luego tambin guardar memoria para cada variable que declaren de ese tipo. Si lo hacen de forma annima solo guardar memoria para esa variable y punto. Un programa que utiliza mucha memoria es menos eficiente, al igual que uno que realiza demasiadas instrucciones o tareas. Siempre es importante tratar de que el programa haga el menor trabajo posible para que sea ms veloz y requiera menos recursos de la computadora para trabajar. Yo no voy a dedicarme ahora a ensearles acerca de la eficiencia de los programas ya que esta parte del curso est dirigida a personas que recin estn aprendiendo, pero ya vayan teniendo en cuenta que este es un aspecto muy importante. De todos modos en algunos casos nombrar la mejor forma de realizar una tarea eficientemente. ------------------------------------------------------------------------------------- 3ecorriendo arreglos% Ya sabemos como crear un arreglo y acceder a sus celdas para asignarles valores, leer estos desde la entrada o escribirlos. Tambin sabemos que cada celda funciona como una variable independiente y que siempre podemos acceder a la que queramos si sabemos como estn numeradas las celdas. Es por esto que conviene siempre que los ndices vayan de 1..N, o sea de 1 hasta N donde N es la cantidad de celdas del arreglo. Esto ayuda a evitar confusiones y hace todo mucho ms entendible. Sin embargo pueden hacerlo de otra manera si consideran que para cierto caso les resulta ms til. Muchas veces resulta necesario recorrer un arreglo, ya sea para buscar un elemento de l o para trabajar de algn modo con los valores de sus celdas, de otro modo para qu lo habramos creado entonces? Aunque les dej esto como ejercicio, espero lo hayan hecho antes de llegar aqu, veremos un ejemplo donde el usuario ingresa 10 valores enteros para un arreglo y luego nosotros desplegaremos stos para mostrrselos y adems le mostraremos la suma de ellos: Cdigo: 1 PROGRAM sumaCeldas; 2 3 Const 4 N= 10; //Dimensin del arreglo. 5 6 Type 7 arr= array[1..N] of integer; 8 9 Var 10 arreglo1: arr; 11 i, suma: integer; 12 13 BEGN 14 //Mensaje para el usuario. 15 write('ngresa ',N,' enteros: '); 16 17 //Leemos un valor para cada celda. 18 For i:=1 to N do 19 read(arreglo1[i]); 20 21 //Dejamos una lnea en blanco. 22 writeln; 23 24 //Mensaje al usuario. Mostramos su ingreso. 25 write('Usted ha ingresado: '); 26 For i:=1 to N do 27 write(arreglo1[i],' '); 28 29 //niciamos suma en 0 ya que an no hemos sumado nada. 30 suma:=0; 31 32 //Recorremos todo el arreglo sumando los valores a suma. 33 For i:=1 to N do 34 suma:= suma + arreglo1[i]; 35 36 //Mostramos el resultado al usuario. 37 writeln; 38 writeln('La suma de los valores es: ',suma); 39 END. Lo primero a destacar en este ejemplo es el uso de la constante N cuyo valor es 10. Es simplemente la que usaremos para declarar el Subrango que declara la dimensin del arreglo. De este modo la usaremos tambin en las iteraciones FOR para recorrer todas las celdas del arreglo. Si luego debiramos modificar nuestro programa para que el usuario ingrese 20 valores en vez de 10 solo debemos cambiar el valor de N en su declaracin de la lnea 4 y todo funcionar perfectamente. De lo contrario deberamos cambiar un 10 por un 20 cada vez que iterramos con el arreglo, al declararlo, etc. En la lnea 17 tenemos un FOR que leer un valor para cada celda del arreglo. Dada esa declaracin el usuario puede ingresar de a un valor he ir presionando enter, o ingresar los 10 valores separados por espacio en una misma lnea y presionar enter al final. Esto es posible ya que hemos usado el procedimiento read que lee un valor y deja el cursor en la misma lnea. De haber usado readln deberamos ingresar un valor por lnea. Les dejo el resto del programa a ustedes. Ahora veremos un ejemplo donde el usuario ingresa 10 valores enteros en un arreglo y el programa le mostrar el mayor de todos ellos: Cdigo: 1 PROGRAM arreglos; 2 3 Const 4 N= 10; //Dimensin del arreglo. 5 6 Type 7 arr= array[1..N] of integer; 8 9 Var 10 arreglo1: arr; 11 i, mayor: integer; 12 13 BEGN 14 //Mensaje para el usuario. 15 write('ngresa ',N,' enteros: '); 16 17 //Leemos un valor para cada celda. 18 For i:=1 to N do 19 read(arreglo1[i]); 20 21 //Dejamos una lnea en blanco. 22 writeln; 23 24 //En un principio el mayor valor es el primero. 25 mayor:= arreglo1[1]; 26 27//Ahora recorremos el resto del arreglo buscando el mayor valor. 28 For i:=2 to N do 29 begin 30 f arreglo1[i]>mayor then 31 mayor:= arreglo1[i]; 32 end; 33 34 //nformamos al usuario. 35 writeln('El mayor valor ingresado es: ',mayor); 36 END. Lean ustedes mismos este cdigo. Seguro son capaces de entenderlo muy bien. ------------------------------------------------------------------------------------- 2s-ueda de un elemento% En este ejemplo veremos un programa en el que el usuario ingresa 10 enteros que guardaremos en el arreglo y luego le pediremos que ingrese otro valor. Buscaremos ese valor en el arreglo. Si est ah lo notificaremos y en caso contrario notificaremos que no est: Cdigo: 1 PROGRAM BusquedaArreglo; 2 3 Const 4 N= 10; //Dimensin del arreglo. 5 6 Type 7 arr= array[1..N] of integer; 8 9 Var 10 arreglo1: arr; 11 i, valorBuscado: integer; 12 exito: boolean; 13 14 BEGN 15 //Mensaje para el usuario. 16 write('ngresa ',N,' enteros: '); 17 18 //Leemos un valor para cada celda. 19 For i:=1 to N do 20 read(arreglo1[i]); 21 22 //Dejamos una lnea en blanco. 23 writeln; 24 25 //Leemos el valor a buscar en el arreglo. 26 write('ngresa el valor que deseas buscar: '); 27 readln(valorBuscado); 28 29 //nicializamos nuestra variable ndice en 0. 30 i:=0; 31 {teramos hasta encontrar el valor o hasta 32 recorrer todo el arreglo sin hallarlo} 33 Repeat 34 //Aumentamos un ndice. 35 i:= i + 1; 36 exito:= arreglo1[i]=valorBuscado; 37 Until (exito) or (i=N); 38 39 writeln; 40 41 //Mostramos el mensaje correspondiente. 42 f exito then 43 writeln('El valor est en el arreglo.') 44 else 45 writeln('El valor no est en el arreglo.'); 46 END. Lo importante aqu est a partir de la lnea 30 donde inicializamos i en 0 ya que ser nuestro ndice. En la lnea 33 declaramos un REPEAT que aumentar nuestro ndice de bsqueda y luego se fijar si el valor buscado es igual al de la celda en que estamos posicionados. En ese caso e/ito ser true y la iteracin terminar. En caso contrario volveremos a aumentar i en 1 y nos fijaremos en la nueva posicin. La iteracin terminar al encontrar el elemento o al recorrer todo el arreglo sin hallarlo. Es importante destacar el uso del REPEAT aqu. Como primera cosa sabemos que iteraremos al menos una vez ya que debemos fijarnos al menos en la primera celda del arreglo, por eso us un REPEAT y no un WHLE. Alguno podr preguntarse y por qu no usaste un FOR para recorrer el arreglo como has hecho hasta ahora? Bien, veamos como quedara ese trozo de cdigo sin es vez de REPEAT fuera FOR Cdigo: For i:=1 to N do exito:= arreglo1[i]=valorBuscado; f exito then Writeln('El valor est en el arreglo.') Else Writeln('El valor no est en el arreglo.'); Con el FOR recorreremos todo el arreglo siempre. La bandera booleana se volver true al hallar el elemento. Funciona perfectamente al igual que el REPEAT, ahora piensen esto. maginen que tenemos un arreglo de 500 celdas y el valor que buscbamos estaba en la celda nmero 86. Con el REPEAT recorreremos solo las primeras 86 celdas del arreglo y nos detendremos ya que al encontrar el elemento no nos interesa lo dems. Con el FOR, al encontrar el elemento la bandera ser true pero an as recorreremos las 500 celdas. Esto hace al programa trabajar de ms cuando no es necesario y le resta mucha eficiencia. Piensen en un arreglo de miles y miles de celdas, por ejemplo, una base de datos de Google en donde estn guardadas casi todas las webs del mundo. Sera mejor recorrer la base de datos hasta encontrar el elemento o recorrerla toda siempre? Es importante que comprendan esto. Aunque ya les dije que no les hara mucho hincapi con esto de la eficiencia, tambin dije que en ciertas ocasiones mencionara el modo de realizar ciertas tareas de la forma ms eficiente posible. Deben notar que el programa anterior se detendr ante el primer encuentro con el valor buscado sin interesarse en si se repite luego. Ahora les dejo una serie de ejercicios. No continen con el tutorial hasta que sean capaces de realizarlos todos, o de lo contrario, no podrn con las lecciones que vendrn a continuacin. ------------------------------------------------------------------------------------- 7,ercicios% 7,ercicio&: Escriban un programa que lea diez enteros de la entrada estndar y guarde estos en un arreglo. El programa debe indicar el mayor de ellos y el ndice de la posicin en la que aparece, as como tambin, el menor de ellos y su posicin. En caso de que se repita un valor mostrarn el ndice de la primera celda en que aparezca. Asumimos que siempre se ingresan enteros en la entrada estndar. Ejemplo1: Cdigo: ngrese 10 enteros: 2 3 1 4 5 10 6 7 8 9 El mayor entero es 10 en la posicin 6 El menor entero es 1 en la posicin 3 Ejemplo2: Cdigo: ngrese 10 enteros: 2 3 2 20 5 20 6 7 8 9 El mayor entero es 20 en la posicin 4 El menor entero es 2 en la posicin 1 --------------------------------------------------------------------- 7,ercicio: Este ejercicio conlleva cierta dificultad, sobretodo porque trabajarn con dos arreglos a la vez, cada uno de distinto tamao. Dada la definicin de tipo para representar cadenas de caracteres de largo M y N : Cdigo: CONST N = . . .; M = . . .; { M < N } . . . TYPE CadenaM = ARRAY[1..M] Of Char; CadenaN = ARRAY[1..N] Of Char; mplementen un programa que lea dos cadenas de la entrada estndar de largo M y N respectivamente, y determine si la primer cadena ocurre como parte de la segunda cadena. El programa debe funcionar para cualquier valor positivo que puedan tomar M y N, considerando la restriccin M < N. Ustedes mismos definan los valores de las constantes. Ejemplo de entrada para N=6, M=3: tor totora Ejemplo de salida: 7l te/to KtorK se encuentra dentro del te/to KtotoraK* Ejemplo de entrada: tos totora Ejemplo de salida: 7l te/to KtosK no se encuentra dentro del te/to KtotoraK* --------------------------------------------------------------------- 7,ercicioD: Tiene una dificultad similar al anterior. Dada la definicin de tipo para representar cadenas de caracteres de largo N y M: Cdigo: CONST N = . . .; M = . . .; . . . TYPE CadenaM = ARRAY[1..M] Of Char; CadenaN = ARRAY[1..N] Of Char; &. Escriban un programa que lea dos cadenas de largo M y N respectivamente, e imprima un mensaje en la salida estndar indicando si alguna letra en la primera palabra ocurre en la segunda. . Escriban un programa que lea dos cadenas de largo M y N respectivamente, y determine si todas las letras en la primera palabra ocurren en la segunda. Como ya saben, siempre que un ejercicio les de verdaderos problemas no tienen ms que preguntar. Siempre intenten todo lo que puedan y prueben bien sus programas antes de dar por terminado un ejercicio. Suerte, espero que comenten lo que les va pareciendo hasta ahora Programando desde $% &' Arreglos multidimensonales ' Algo sobre C3:* Leccin 12: Arreglos multidimensionales: Espero que comenten en esta leccin como llevan el curso hasta ahora, qu les ha parecido las explicaciones dadas, si creen que se entiende bien a pesar de la complejidad creciente, etc. De verdad eso es un estmulo para continuar con este trabajo. Los arreglos que hemos visto hasta ahora son unidimensionales (lineales), o sea, de una nica dimensin. Se dice esto ya que se requiere una nica coordenada (ndice) para ubicar una celda del mismo. Sin embargo es posible definir arreglos de dos dimensiones (2D), de tres dimensiones (3D) y ms. Aqu veremos ejemplos de arreglos de hasta tres dimensiones ya que no requerimos de ms para trabajar, sin embargo muchos programas usan arreglos de N dimensiones. Como nosotros existimos en un espacio de dimensin 3 solo podemos ver grficamente arreglos de dimensin 3 o menor, pero visualizar un arreglo de dimensin 4 o ms se hace difcil y no compete a este curso. Arreglos bidimensionales% Comencemos por ver arreglos de dos dimensiones. Estos dibujarn una tabla de datos del mismo tipo, tambin conocidas matemticamente como matrices. Hay dos maneras de declarar arreglos bidimensionales, una es declarar un arreglo de un arreglo, o sea, un arreglo cuyas celdas sean tambin arreglos. Esta es la forma ms fea de hacerlo y la que menos recomiendo, pero existe. Vemoslo en un ejemplo: Cdigo: 1 PROGRAM BDMENSONAL; 2 3 Type 4 arr1= array[1..5] of integer; 5 Tabla= array[1..7] of arr1; 6 7 Var 8 i, j: integer; 9 matriz: Tabla; 10 11 BEGN 12 For i:= 1 to 7 do 13 For j:= 1 to 5 do 14 matriz[i,j]:= 0; 15 END. En la lnea 4 vemos un tipo arr& que es un arreglo de 5 celdas de enteros. En la lnea 5 vemos el tipo :abla que es un arreglo de 7 celdas del tipo arr&, o sea que cada celda es un arreglo de 5 celdas. Si dibujramos Tabla al igual que lo hicimos antes tendramos 7 celdas del 1 al 7, esto estara indicando cuantas filas tiene nuestra tabla. Si desplegamos cada celda de :abla estaramos abriendo hacia la derecha 5 lugares con lo cual estaramos indicando las columnas de nuestra tabla. Ese sera el dibujo de :abla, como ven hay 7 filas (lneas horizontales) y 5 columnas (lneas verticales). El 0 corresponde a la posicin (3,3) de la tabla ya que est en la fila 3 y en la columna 3. Siempre para una tabla se especificarn las coordenadas de una celda nombrando primero el nmero de filas y luego el de columnas. En la lnea 9 del ejemplo declaramos la variable matriz del tipo Tabla. El trabajo con los arreglos bidimensionales es idntico al de los arreglos unidimensionales. Cada celda es una variable independiente y para acceder a cada una simplemente nombramos nuestro arreglo y damos entre parntesis rectos las coordenadas de nuestra celda separadas por comas. La forma genrica sera as: 0ariableFarregloh1ilaEcolumnai de este modo, si quisiramos ir a la celda que est en la fila 7 y en la columna 4 deberamos escribir matri)hQENi. En nuestro programa de ejemplo asignamos a cada celda el valor 0. Como ven debemos usar dos FOR anidados para recorrer una tabla, uno para recorrer las filas y otro para las columnas. Vean que el subrango en arr& indica cuntas columnas tendr la matriz y en subrango en :abla indica cuntas filas. Una sintaxis alterna para acceder a una celda de nuestra tabla es la siguiente: 0ariableFarregloh1ilaihcolumnai y por tanto si, usando esta sintaxis, quisiramos acceder a la fila 7 y la columna 4 deberamos escribir matriz[7][4]. No recomiendo esta sintaxis. Veamos ahora la segunda forma de declarar un arreglo bidimensional, la cual es la que yo recomiendo que usen: Cdigo: 1 PROGRAM BDMENSONAL; 2 3 Type 4 Tabla= array[1..7,1..5] of integer; 5 6 Var 7 i, j: integer; 8 matriz: Tabla; 9 10 BEGN 11 For i:= 1 to 7 do 12 For j:= 1 to 5 do 13 matriz[i,j]:= 0; 14 END. Como ven en la lnea 4 hemos declarado el tipo :abla en el cual hemos incluido dos subrangos entre los parntesis rectos separados por coma. El primer subrango (1..7) indica la cantidad de filas y el segundo (1..5) la cantidad de columnas que tendr la matriz. Esto siempre es as. Como ven, de este modo queda todo mucho ms claro. NOTA: La cantidad de celdas de un arreglo bidimensional es igual al resultado de multiplicar la cantidad de filas por la cantidad de columnas. Como ejercicio quiero que modifiquen ese programa para que despliegue en la salida estndar la matriz. En este caso aparecer una tabla de 0 como esta: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Esto no es muy difcil y radica explcitamente en el uso de FOR. ------------------------------------------------------------------------------------- 7,ercicios% 7,ercicio: Modifiquen los programas anteriores para que, si el usuario no ingresa un entero, notifiquen el error y vuelvan a pedir el valor correcto. ----------------------------------------------------------------- 7,ercicioD: Se llama matriz cuadrada a toda aquella matriz que tiene tantas filas como columnas, o sea, si tiene 5 filas tiene 5 columnas. La transpuesta de una matriz cuadrada es aquella matriz que tiene como columnas lo que antes eran filas. O sea, si tenemos una matriz cuadrada A, una matriz cuadrada B es transpuesta de A si las columnas de B son iguales a las filas de A, o sea, si se satisface que B[i,j]=A[j,i] para todos los valores posibles de i y j. Ejemplo. Sea A de 5 filas y 5 columnas como se muestra en la figura, veamos como sera su transpuesta B: A 1 2 3 4 5 0 0 0 0 0 1 1 1 1 1 5 4 3 2 1 2 2 2 2 2 2 1 0 1 5 2 2 0 1 4 2 3 0 1 3 2 4 0 1 2 2 5 0 1 1 2 Como ven, lo que en A eran filas, en B son columnas. La primera fila de A que contiene los valores 1, 2, 3, 4 y 5 es la primera columna de B 1, 2, 3, 4 y 5, y as sucesivamente. Escriban un programa que calcule la transpuesta de un arreglo de nmeros reales con cinco renglones y cinco columnas. Los valores de la matriz se leen desde la entrada estndar. El resultado se debe imprimir en la salida estndar. Recuerden la relacin B[i,j]=A[j,i] para que sean transpuestas. Este ejercicio no es muy complicado. Tal vez lo peor de esto es que trabaja con una propiedad matemtica de las matrices y para aquellos que no lo han estudiado puede resultar difcil de comprender. An as creo que no deberan tener problemas, sin embargo se trata de comprender el lgebra Lineal y eso no es lo que quiero en este curso. ------------------------------------------------------------------------------------- Arreglos tridimensionales% Esto es bsicamente lo mismo. Se declaran exactamente igual solo que ahora habr tres subrangos entre parntesis rectos y por ende deberemos colocar tres coordenadas para indicar cual celda deseamos ver (una coordenada para la fila (altura), otra para la columna (largo) y otra para el eje (ancho)). Hago esta aclaracin porque si bien un arreglo bidimensional dibuja una tabla, uno tridimensional dibuja un prisma y por tanto debemos decir cuan a lo alto, largo y ancho queremos posicionarnos. Esto es un arreglo bidimensional de 5 filas y 8 columnas. Visto de este modo es un rectngulo donde la cantidad de filas son su altura y la cantidad de columnas su largo. Este es un arreglo de 5x8. As podramos visualizar un arreglo tridimensional de 5x8x6. Como ven es un arreglo de tablas que estaran todas bien pegadas formando un prisma. Nosotros debemos indicar en qu fila y columna est nuestra celda y en cual tabla de todas. Siempre indicamos [fila, columna, tabla]. Esto es un intento de que puedan visualizar un arreglo tridimensional. El punto rojo correspondera a la posicin [4,8,3] por estar en la cuarta fila, octava columna de la tercera tabla. El azul correspondera a la posicin [1,3,6]. Hasta aqu llegamos con arreglos, en la siguiente leccin les propondr un proyecto llamado Master Mind enfocado para el uso de arreglos, pero necesito que me comenten que tal la llevan hasta ahora, qu les parece todo y si creen que vale la pena continuar de esta manera. ------------------------------------------------------------------------------------- LibrerBa C3:% Limpiar la pantalla% Muchas veces puede resultar muy conveniente el hecho de borrar el contenido de la pantalla para mostrar uno nuevo y no que lo anterior se desplace hacia arriba. Ustedes mismos habrn visto que al ejecutar mediante el DE varias veces un programa, todo lo que se muestra en la pantalla va quedando all, lo cual hace que se vea feo o confuso en varios casos. Para lograr limpiar la pantalla utilizaremos una librerBa de pascal. Esto no se corresponde con el cometido de este curso por lo que solo explicar cmo limpiar la pantalla. El uso de libreras lo veremos ms adelante cuando abordemos la programacin en Modula ; si no manejan bien todos los conceptos que hay aqu pues simplemente no tiene sentido seguir con cosas ms complejas. Qu es una librera? Bsicamente es una unidad de programa que consta de funciones y procedimientos (lo veremos ms adelante) que alguien program y puso a nuestra disposicin para que podamos utilizarlos. Dicho de manera sencilla para que se entienda ahora, una librera consta de un cdigo fuente ya compilado pero que no crea un archivo *e/e, sino que queda en otro formato. La librera tiene un nombre y adems, dentro de su cdigo tiene "partes" que nosotros podemos llamar y utilizar para nuestros propsitos. Para usar una librera simplemente debemos saber su nombre y claro, qu partes de ella queremos usar. Existen libreras por defecto que ya vienen con el compilador, pero hay otras que pueden obtenerse por la web. Existe una librera incluida en Free Pascal llamada C3:. Esta librera nos provee de funciones para el control de la pantalla y el teclado. De todas ellas solo nos interesa una, ClrScr, lo cual es una abreviacin de Clear Screen, que significa Limpiar Pantalla. Para indicar las libreras que vamos a usar debemos escribir la palabra reservada 9S7S luego de la declaracin del identificador de nuestro programa. Luego de 9S7S escribimos los nombres de nuestras libreras y ya, podemos comenzar llamar a sus funciones y procedimientos sin problema. Veamos un simple ejemplo de la limpieza de la pantalla: Cdigo: 1 PROGRAM LimpiaPantalla; 2 3 USES crt; 4 5 VAR 6 i, j: integer; 7 8 BEGN 9 For i:=1 to 20 do 10 begin 11 For j:=1 to 20 do 12 write('#'); 13 writeln; 14 end; 15 writeln; 16 write('Presione ENTER para limpiar la pantalla...'); 17 readln; 18 clrscr; 19 write('Ha borrado la pantalla. Presione ENTER para cerrar...'); 20 readln; 21 END. Este programa lo nico que hace es dibujar un cuadro de 20x20 utilizando el carcter #, luego borra el dibujo y muestra un nuevo mensaje. El procedimiento clrscr puede ser llamado cada vez que queramos. En resumen, escriben 9S7S crt antes de declarar constantes, tipos y variables, y luego pueden usar clrscr en cualquier parte de su programa para borrar todo su contenido. Programando desde $% &D' Primer pro"ecto di1icil% Master Mind* Primer pro"ecto di1icil% MAS:73 M(+? Esta no ser una leccin propiamente dicha, sino que les propondr realizar un proyecto, bastante difcil por cierto. Voy a pedirles explsitamente que participen en esto, que posteen, comenten y sobretodo que pregunten. Es muy importante para m obtener sus comentarios, ya sea un simple "Leccin leida" o un "Buena leccin" as como tambin un "No entend nada". O sea, comenten. Con el Adivinador no se como les fue, no se si lo pudieron realizar o si al menos lo intentaron, eso tambin sera bueno saberlo. En este caso el ejercicio ser de una dificultad mucho mayor. Se tratar de un juego bastante comn en pginas web, el Master Mind,solo que en este caso ha sido adaptado por los profesores de la Facultad de ngeniera para ser propuesto para programarse en Pascal con los conociemientos que ustedes mismos han obtenido de las lecciones dadas hasta ahora. Por qu les propongo esto? Para que realmente terminen de asimilar lo que les he impartido hasta ahora. Para que tengan un pantallazo inicial de lo complejo que puede ser un problema a ser programado y cmo a veces resulta hasta imposible de realizar, aunque en verdad no lo es. Para que vean que parte de la gran dificultad de la programacin radica en primera instancia en entender el problema planteado. Antes de pensar tansiquiera en el lenguaje de programacin hay que entender al mximo lo que se quiere resolver, y eso no es para nada sencillo. Yo les dar todo el planteo y ustedes intentarn modelar el programa y hacerlo acorde a lo que les pido. Luego de eso estar al pendiente de todas sus preguntas para ayudarlos, pero la idea no es que esperen a que yo les publique el cdigo que hice sino que realmente intenten hacer esto. Dada su complejidad les llevar varios das hacerlo bien. Adems, como esto no es curso formal, no estarn abocados a hacer esto, as que se extender un poco ms. La idea, antes de continuar con las lecciones siguientes, es hacer esto. Todos aquellos que an no han llegado hasta aqu no se preocupen, sigan a su ritmo. Si desisten en esto pues, no aprendern a programar bien a menos que hagan un curso formal en alguna institucin. Este es un intento por mi parte de que realmente puedan aprender. Ojal les sirva de algo. --------------------------------------------- Master Mind% El Master Mind es un juego de estrategia, donde un jugador intenta adivinar un cdigo creado por otro jugador. El cdigo tiene una cantidad fija de caracteres tomados de un conjunto conocido. Llamemos adi3inador al jugador que debe adivinar, y pensador al jugador que piensa el cdigo. El adi3inador sucesivamente va proponiendo un cdigo que intenta adivinar el cdigo del pensador. Cada una de estas propuestas recibe una nota por parte del pensador de acuerdo con el grado de aproximacin que tenga la propuesta con el cdigo pensado. Esas notas actan como pistas que le permiten al adivinador aproximarse ms al cdigo del pensador en cada intento. El juego termina cuando el adi3inador descubre el cdigo del pensador. O sea, el adi3inador intentar adivinar un cdigo que solo el pensador conoce, en un nmero mximo de intentos. El pensador le dar al adivinador las notas correspondientes para que este tenga una gua de cmo proponer su siguiente cdigo. ------------------------------------------------- 7l cdigo Los cdigos vlidos tanto para el pensador como para el adi3inador son los que cumplen con las siguientes caractersticas: Tienen una cantidad fija de caracteres. Llamemos LA3;5FC5?(;5 a esa cantidad. Los caracteres vlidos son las letras ma"sculas comprendidas entre P3(M73AFL7:3A y 9L:(MAFL7:3A. +o pueden contener caracteres repetidos* Existen diferentes modalidades de juego, segn los valores de los parmetros LA3;5FC5?(;5, P3(M73AFL7:3A y 9L:(MAFL7:3A. En algunas modalidades tambin se admiten caracteres repetidos. Por ejemplo, si suponemos: Cdigo: LARGO_CODGO = 6 PRMERA_LETRA = 'A' ULTMA_LETRA = 'H'. Entonces los siguientes son cdigos vlidos: Cdigo: ABCDEF FAGBCH FCDEAB GDHBCA HEFGBD porque son de largo 6 y contienten letras que estn comprendidas entre la letra 'A' y la letra 'H'. Los siguientes, en cambio, son cdigos no vlidos: Cdigo: AHJKAB AABCDE BBBBBB A12BCD ABC FGHFGH ya sea porque no son de largo 6 y/o porque contienen caracteres que no estn comprendidos entre la 'A' y la 'H'. ------------------------------------------ Las notas La nota que adjudica el pensador a cada propuesta del adi3inador consiste de una pareja de nmeros I2E3J. Esta pareja de nmeros se calcula de la siguiente manera: 2 es la cantidad de caracteres que aparecen en la propuesta del adi3inador y en el cdigo del pensador en la misma posicin. A este nmero se le llama: la cantidad de buenos de la propuesta. 3 es la cantidad de caracteres de la propuesta del adi3inador que tambin aparecen en el cdigo del pensador pero en diferente posicin . A este nmero se le llama: la cantidad de regulares de la propuesta* Ejemplos de notas: Supongamos que el cdigo del pensador es ABCFGH. Propuesta Buenos Regulares ABCDEF 3 1 DEFHCB 0 4 AGCFBH 4 2 ABCFGH 6 0 Para ser ms e/plBsito " redundar un poco% Supongamos que el pensador se inventa el cdigo A2C? para que el adi3inador aivine. Como primer intento el adi3inador presenta el cdigo AFGH. Como ven no ha acertado, pero una de las letras de su cdigo coincide con la del cdigo del pensador, por tanto hay una bien. Esa A corresponde a un BUENO ya que adems de ser la misma letra est en la misma posicin que en el cdigo del pensador, en este caso, en el primer lugar. Un REGULAR corresponde a una letra que esta en ambos cdigos pero en una posicin diferente. Por ejemplo, si para adivinar el ABCD el adivinador presentara el FAGH solo la letra A est en ambos cdigos, pero en el del pensador est en primer lugar y en el del adi3inador est en segundo lugar. Ambas notas se presentan a la vez. Veamos un ejemplo suponiendo que las letras que puede haber en el cdigo van de la A a la F inclusive. En este ejemplo las letras pueden repetirse, pero para lo que ustedes tendrn que programar recuerden que NO PUEDEN REPETRSE LETRAS. El cdigo del pensador es FDDA: Primer intento: ABCD Buenos: 0 Regulares 2 Como ven no hay letras que coincidan en posicin, pero tenemos en el cdigo del adi3inador una A que est en el primer lugar (en el del pensador est en el ltimo) y una D en ltimo lugar (en el del pensador est en segundo o tercer lugar) y corresponden cada una a un regular. Segundo intento: BADC Buenos: 1 Regulares: 1 Ahora la D coincide en el tercer lugar de ambos cdigos. Notar que en el cdigo del pensador hay tambin una D en el segundo lugar, pero esta no hace que la D del tercer lugar del cdigo del adivinador sea un regular ya que esta coincide con la D del tercer lugar. La A siegue estando en posiciones distintas. Tercer intento: EDAE Buenos: 1 Regulares: 1 Cuarto intento: EDAF Buenos: 1 Regulares: 2 Quinto intento: DDAF Buenos: 1 Regulares: 3 Sexto intento: FADD Buenos: 2 Regulares: 2 Sptimo intento: FDDA Buenos: 4 Regulares: 0 En este caso el adivinador ha ganado. Noten que si suman 2uenos M 3egulares el resultado siempre ser menor o igual al nmero de letras en el cdigo (en este caso 4) y slo ser igual si todas las letras en el cdigo del adivinador estn en el del pensador. Nunca puede ser mayor. -------------------------------------- 7l programa En esta proyecto debern implementar en pascal, un programa que se comporte como el pensador, mientras que el usuario har las veces del adi3inador. El programa deber generar un cdigo al azar, que el usuario intentar adivinar en una cantidad de intentos inferior a MAXMO_NTENTOS. Para cada intento del usuario, el programa despliega la cantidad de buenos y regulares que correspondan. El programa termina cuando el usuario advina la propuesta, o cuando el adi3inador llega a una cantidad de intentos igual a MAXMO_NTENTOS, Los valores de MAXMO_NTENTOS, LARGO_CODGO, PRMERA_LETRA y ULTMA_LETRA se los dir ms adelante. Para fijar ideas, suponderemos en lo que sigue que: Cdigo: MAXMO_NTENTOS = 10, LARGO_CODGO = 4, PRMERA_LETRA = 'A' ULTMA_LETRA = 'H' Comien)o del Programa: Al comenzar el programa despliega el siguiente texto: Cdigo: Dispone de 10 intentos para adivinar (ngreso de propuestas: A partir de ah comienza a pedir los cdigos del usuario y a cada uno de ellos le adjudica la nota. El programa despliega el nmero de propuesta que corresponde: &J, J hasta &$J. A cada propuesta le responde en la lnea siguiente la cantidad de buenos y regulares (en ese orden) de la propuesta leda. Cdigo: 1) ABCD 2 0 2) ACBD 1 2 Los cdigos que all aparecen corresponden al ingreso de la propuesta por parte del usuario. 0alidacin de cdigos% Cuando el cdigo ingresado no es vlido, se vuelve a pedir el cdigo sin incrementar el nmero de intentos: Cdigo: 4) AABC ERROR 4) ABFD 1 1 5) . Un cdigo no vlido es cualquier combinacin de caracteres que no respete las reglas especificadas en la seccin 7l cdigo. .inali)acin del programa: Luego del dcimo intento, si el usuario no adivin el cdigo, el programa despliega el siguiente mensaje y el programa termina: Cdigo: 10) ABCDF 2 1 Se alcanz el nmero mximo de intentos El cdigo era: ABHGC Fin del juego Cuando el usuario ingresa un cdigo que corresponde a 4 buenos, se despliega el siguiente mensaje y el programa termina.: Cdigo: 7) AFGH 4 0 Correcto. Ha acertado Fin del juego ---------------------------------------- Se pide mplementar un programa en Pascal que imite el comportamiento que acabo de describir. Debe ser exactamente igual, tanto los mensajes como todo lo descrito. Si esto les sale bien luego ustedes podrn agregarle todas las mejoras que quieran. Pueden usar solo y nicamente lo dado en las lecciones anteriores, incluyendo arreglos. ---------------------------------------- ?i1icultades evidentes Al intentar realizar este programa tendrn las siguientes dificultades: *Entender bien el problema planteado para poder empezar a trabajar en l. *Crear un cdigo al azar. *Realizar las lecturas de la entrada estndar. *Calcular las notas del cdigo planteado por el usuario. Recuerden que en los cdigos no habr caracteres repetidos, eso dificultara mucho las cosas y ser pedido ms adelante cuando comencemos a ver subprogramas. Leccin &N% Subprogramas% Procedimientos (ntroduccin Bien, hasta ahora el tema ms complicado que hemos visto lo representan los arreglos (array); sin embargo entraremos ahora en temas un tanto ms difciles y que por ende requerirn ms trabajo por parte de ustedes a la hora de practicar. Yo intentar explicarlos lo ms detalladamente posible y de un modo entendible siempre partiendo de la base de que ustedes como lectores no tienen conocimiento alguno sobre programacin. Hasta el momento hemos visto programas que podan o no estar divididos en varios bloques. Por si no lo recuerdan llambamos bloque a aquella seccin de cdigo delimitada entre un BEGN y un END. Cada bloque siempre contiene ms de una instruccin, de lo contrario no tendra sentido definirlo aunque es posible hacerlo, pero es visto por el programa como una nica instruccin. Del modo en que hemos venido programando, si nuestro programa tuviera que realizar la misma tarea ms de una vez en distintos bloques de cdgio nosotros deberamos escribir las mismas lneas de cdigo todas esas veces. Esto extiende muchsimo nuestro texto fuente dejndolo difcil de entender adems de complicar muchsimo la tarea del programador. Es por esto que existen dos estructuras muy importantes y potentes que forman a los llamados subprogramas (pequeos programas independientes dentro del programa principal) conocidos como PROCEDMENTOS y FUNCONES (en otros lenguajes, como Java, ambas estructuras se conocen como Mtodos, aunque tambin se pueden diferenciar entre procedimientos y funciones). En muchas ocasiones ustedes han visto que he nombrado la palabra 1uncin y la palabra procedimiento, por ejemplo, al hablar del procedimiento C3(:7 o de la 1uncin 3A+?5M. En lo que sigue de este curso veremos la diferencia explcita entre lo que es un procedimiento y lo que es una funcin. Estas estructuras comienzan con lo que en programacin se conoce como Modulari)acin ya que como su nombre lo indica permiten formar mdulos de programa que se encargan de ciertas tareas especficas. De este modo el cdigo queda mucho ms entendible y compacto adems de lograrse una buena ordenacin del mismo, un diseo ms sencillo y fcil de mantener y resultados mucho ms poderosos. Cuando veamos Modula2 entraremos en una extensin de esto y veremos que nuevamente obtendremos resultados mucho ms potentes, adems de poder al fin aprender a programar en lenguajes como Java. Es sumamente importante que entiendan todo este captulo antes de continuar si en verdad quieren lograr crear un buen programa, sea del tipo que sea, ya que los procedimientos y las funciones son bsicos para cualquier programador de nivel medio, o incluso de nivel bajo. --------------------------------- Como ya han visto, aunque tal vez no se han dado cuenta, es posible tener un procedimiento declarado por ah y luego simplemente usar su nombre para llamarlo y hacer que este haga su tarea. Por ejemplo, cuando ustedes invocan al procedimiento WRTE, estn haciendo un llamado a su cdigo fuente y pues, aunque nosotros no lo vemos, dicho procedimiento realiza muchas tareas para mostrar algo en pantalla. Eso es lo que haremos nosotros, nos declararemos un procedimiento al que le pondremos el nombre que ms nos guste, y luego, cada vez que lo necesitemos lo llamaremos para que realice sus tareas. ------------------------------------------------------------------------------------- Procedimientos% ?eclaracin " llamado% Veamos entonces, antes que las FUNCONES, los PROCEDMENTOS: Un Procedimiento ser un subprograma que se encargar de realizar una tarea especfica dentro del programa principal. Al igual que al programa principal, a los procedimientos se les asigna un nombre (identificador) con el cual podremos llamarlo luego para pedirle que realice su tarea. Un procedimiento se define de la siguiente manera Cdigo: PROCEDURE identificador(parmetros); Usamos la palabra reservada PROCEDURE para indicar que definiremos un procedimiento, luego le damos un nombre cualquiera que identifique su tarea o que nos sirva a nosotros como referencia. Seguido del nombre se colocan entre parntesis los parmetros que utilizar el procedimiento para trabajar (esto lo veremos dentro de poco) y finalmente un punto y coma. Todo esto compone lo que llamamos encabe)ado o 1irma del procedimiento. No pueden existir dos procedimientos con el mismo identificador ya que como ha sido hasta ahora y debera resultarles obvio, no pueden repetirse identificadores (existen excepciones a esta regla, pero no nos interesan ahora). Esto puede cambiar de un lenguaje a otro, pero no entraremos en esos detalles, concentrmonos en Pascal. Como ya he dicho, un procedimiento es un subprograma, o sea, un pequeo programa dentro del programa principal y por este motivo tendr una estructura casi idntica a la de cualquier programa. Lo que quiero decir con esto es que, luego del encabezado del procedimiento, podremos definir CONSTANTES, TPOS, VARABLES e incluso otros subprogramas dentro. Tambin tendr un bloque principal delimitado entre BEGN y END solo que este END terminar en punto y coma. Nunca olviden que el nico END que termina en punto es el del programa principal. Esta sera la estructura del programa principal con lo visto hasta el momento: Cdigo: PROGRAM Nombre_del_programa; Const //Declaramos constantes. Type //Declaramos tipos. Var //Declaramos variables. BEGN //Bloque principal del programa. END. Veamos la estructura pero agregando el lugar donde se declaran los procedimientos y funciones: Cdigo: PROGRAM Nombre_del_programa; Const //Declaramos constantes. Type //Declaramos tipos. Var //Declaramos variables. {Declaracin e implementacin de PROCEDMENTOS y FUNCONES} BEGN //Bloque principal del programa. END. Veamos ahora la estructura de un procedimiento: Cdigo: PROCEDURE Nombre_del_procedimiento(parmetros); Const //Declaracin de constantes. Type //Declaracin de tipos. Var //Declaracin de variables. BEGN {Bloque principal del procedimiento} END; Noten que la estructura es idntica a la del programa principal excepto por el encabezado y por el hecho de que el END del bloque principal termina en punto y coma. A esa estructura debera aadirle la declaracin de funciones y procedimientos, pero esta va en el mismo lugar que en el bloque del programa principal y no creo que haga falta mostrrselos. No se pongan nerviosos, pronto entendern mejor todo esto. Veamos un ejemplo sencillo en el que pedimos al usuario que ingrese su Nombre, su Apellido, su Edad, su Documento de dentidad y su Direccin. Luego mostraremos los datos ingresados pero separados por una lnea formada por guiones y luego varias lneas en blanco. Veremos la versin sin procedimiento y luego la versin con procedimiento. Para este ejemplo en particular usaremos el tipo primitivo STRNG, que lee cadenas de caracteres desde la entrada estndar. Lo correcto a los efectos de este manual sera leer carcter a carcter y guardar estos en un arreglo para formar la palabra, pero esto se los pedir luego en un ejercicio. Cdigo: 1 PROGRAM Datos_de_Usuario; 2 3 Const 4 separador='-'; 5 lineas_a_saltear= 4; 6 7 Var 8 nombre, apellido, documento, direccion: string; 9 i: integer; 10 11 BEGN 12 //Pedimos los ingresos al usuario. 13 Write('ngresa tu nombre: '); 14 readln(nombre); 15 write('ngresa tu apellido: '); 16 readln(apellido); 17 write('ngresa tu documento: '); 18 readln(documento); 19 write('ngresa tu direccin: '); 20 readln(direccion); 21 22 //Realizamos la primera separacin. 23 For i:=1 to 20 do 24 write(separador); 25 For i:=1 to lineas_a_saltear do 26 writeln; 27 28 //Escribimos el nombre del usuario. 29 writeln('NOMBRE: ',nombre); 30 31 //Realizamos la segunda separacin. 32 For i:=1 to 20 do 33 write(separador); 34 For i:=1 to lineas_a_saltear do 35 writeln; 36 37 //Escribimos el apellido del usuario. 38 writeln('APELLDO: ',apellido); 39 40 //Realizamos la tercera separacin. 41 For i:=1 to 20 do 42 write(separador); 43 For i:=1 to lineas_a_saltear do 44 writeln; 45 46 //Escribimos el documento del usuario. 47 writeln('DOCUMENTO: ',documento); 48 49 //Realizamos la cuarta separacin. 50 For i:=1 to 20 do 51 write(separador); 52 For i:=1 to lineas_a_saltear do 53 writeln; 54 55 //Escribimos la direccin del usuario. 56 writeln('DRECCN: ',direccion); 57 END. Este es un programa muy sencillo y no deberan tener ninguna dificultad al leerlo. An as explicar lo que hace para que luego se entienda perfectamente el ejemplo con procedimiento. Declaramos en las primeras lneas dos constantes: separador, que es del tipo c,ar inicializada con el guin; este carcter ser el que dibuje una lnea separadora, esto es bien simple, escribimos unos 20 guiones en la misma lnea de salida y ya. Luego est la constante lineasFaFsaltear que es del tipo integer inicializada con el nmero N y es la que utilizaremos para indicar cuantas lneas en blanco dejaremos entre dato y dato. Luego declaramos cuatro variables del tipo string para leer los datos del usuario, una por cada dato. Como ya dije, el tipo string lee los datos en forma de cadenas de caracteres. Esto implica que si uno ingresa un valor 4556 no ser el nmero entero 4556 sino la cadena de caracteres '4556'. Es ideal para leer palabras o frases, pero no hablaremos de su uso explsito en este curso ya que la idea aqu es que ustedes aprendan a programar estructuradamente y entiendan como funcionan las herramientas ms primitivas. De este modo lograrn desarrollar una gran habilidad para programar y sern capaces de resolver grandes problemas con pocas herramientas, que muchas veces ser a lo que tendrn que enfrentarse. La otra variable declarada es i, del tipo entero, y ser la que usaremos como variable de control para los FOR. Desde la lnea 13 a 20 inclusive solo pedimos al usuario que ingrese sus datos y los leemos desde la entrada estndar. Esto no implica ninguna dificultad para ustedes. En la lnea 23 declaramos un FOR que simplemente dibuja los 20 guiones y en la lnea 25 declaramos el FOR que se encarga de dejar lneas en blanco, tantas como la constante lineasFaFsaltear indique en su valor. Estos dos FOR se repetirn varias veces durante el cdigo, cada vez que necesitemos dibujar la lnea de guiones y dejar lneas en blanco. Como podrn ver, usaremos cuatro veces estas dos instrucciones en nuestro programa. Realmente esto resulta estpido ya que quedara ms prolijo si no dejramos lneas en blanco para presentar los datos del usuario, pero la intencin de este ejemplo es ver la necesidad de los procedimientos de una manera sencilla, ya que un buen ejemplo sera muy complejo y no es adecuado presentarlo en el momento en el que ustedes estn intentando aprender una nueva herramienta y que resultar bastante difcil de comprender si no se trabaja con cuidado. Ahora veamos el mismo ejemplo pero con un procedimiento llamado Saltear que se encargue de realizar la tarea de los dos FOR, o sea, dibujar la lnea de guiones y de dejar lneas en blanco: Cdigo: 1 PROGRAM Datos_de_Usuario; 2 3 Const 4 separador='-'; 5 lineas_a_saltear= 4; 6 7 Var 8 nombre, apellido, documento, direccion: string; 9 i: integer; 10 11 Procedure Saltear(); 12 Begin 13 For i:= 1 to 20 do 14 Write(separador); 15 For i:= 1 to lineas_a_saltear do 16 Writeln; 17 End; 18 19 BEGN 20 //Pedimos los ingresos al usuario. 21 Write('ngresa tu nombre: '); 22 readln(nombre); 23 write('ngresa tu apellido: '); 24 readln(apellido); 25 write('ngresa tu documento: '); 26 readln(documento); 27 write('ngresa tu direccin: '); 28 readln(direccion); 29 30 //Realizamos la primera separacin. 31 Saltear(); 32 //Escribimos el nombre del usuario. 33 writeln('NOMBRE: ',nombre); 34 35 //Realizamos la segunda separacin. 36 Saltear(); 37 38 //Escribimos el apellido del usuario. 39 writeln('APELLDO: ',apellido); 40 41 //Realizamos la tercera separacin. 42 Saltear(); 43 44 //Escribimos el documento del usuario. 45 writeln('DOCUMENTO: ',documento); 46 47 //Realizamos la cuarta separacin. 48 Saltear(); 49 50 //Escribimos la direccin del usuario. 51 writeln('DRECCN: ',direccion); 52 END. Bien, este programa es idntico al anterior en el sentido de que realiza exactamente la misma tarea. Como suceda en la versin anterior, repetamos cuatro veces la declaracin de los FOR que se ocupan de dibujar los guiones y saltear lneas. Ahora lo haremos solo una vez dentro del procedimiento Saltear. Las declaraciones de constantes y variables quedan idnticas a las anteriores. Ahora la diferencia principal est en que luego de las variables declaramos a nuestro procedimiento. Vemoslo detalladamente: Cdigo: Procedure Saltear(); Begin For i:= 1 to 20 do Write(separador); For i:= 1 to lineas_a_saltear do Writeln; End; Tenemos su encabezado que consta simplemente de la palabra reservada procedure y luego de su identificador Saltear seguido por los parntesis. En este caso estos parntesis no tienen nada dentro porque este procedimiento no utiliza parmetros, eso lo veremos ms adelante. A pesar de que no existan parmetros, es conveniente incluir los parntesis vacos, aunque pueden no hacerlo si lo prefieren. Luego del encabezado podramos haber declarado constantes, variables, tipos y/u otros procedimientos, pero no hace falta para este ejemplo tan sencillo, as que procedemos directamente a iniciar el bloque principal con la palabra 2egin. A partir de aqu se escriben todas las instrucciones que realizar el procedimiento, las cuales pueden ser lo que a ustedes se les ocurra, lo que les haga falta y que saben utilizarn en ms de una ocasin. No olviden que un procedimiento es un pequeo programa dentro del programa principal y por lo tanto admite exactamente las mismas reglas. En este caso nuestro procedimiento contiene a los dos FOR de antes y nada ms. Cerramos su bloque principal con End; con lo cual nuestro programa sabe que all termina la declaracin de Saltear. Bien, ya tenemos nuestro procedimiento que se encarga de dibujar la lnea de guiones y de dejar lneas en blanco, ahora solo debemos llamarlo cada vez que lo necesitemos. Esto es bien fcil, solo escribimos su nombre en el lugar en el que deseamos que realice su tarea y entre parntesis colocamos los parmetros que utilizaremos, en este caso como no hay parmetros solo dejamos los parntesis vacos aunque bien podramos no incluirlos. En este ejemplo vemos las cuatro llamadas en las lneas 31, 36, 42 y 48. En este caso en particular no ahorramos muchas lneas de cdigo al utilizar el procedimiento, pero como ya dije, un verdadero ejemplo sera muy complejo y en realidad los procedimientos y funciones utilizados llegan a estar formados por cientos y cientos de lneas. Como ven, utilizando un procedimiento solo hace falta escribir una nica vez una tarea especfica volvindose el cdigo ms legible y ms fcil de mantener en caso de errores o actualizacin. Cuando nuestro programa principal llega, por ejemplo, a la lnea 31, regresa a la 12 (o a aquella donde est el BEGN del bloque principal del procedimiento) y realiza una por una las instrucciones all indicadas hasta llegar al END que finaliza el bloque del procedimiento. Pueden ver esto si utilizan el DEBUGER paso a paso utilizando F7 en vez de F8 para avanzar. Como ya expliqu antes, F7 ingresa dentro de los subrprogramas en el paso a paso y F8 no lo hace. ------------------------------------------------------------------------------------- 0ariables ;lobales " Locales* (ntroduccin al Alcance de (denti1icadores% En nuestro ejemplo vimos que nuestro procedimiento no posea ninguna variable declarada dentro. Sin embargo tambin vemos que la nica variable que usa es i y la nica constante es lineasFaFsaltear adems de que ambas solo son usadas por el procedimiento y por nadie ms. Dado este caso bien podramos haberlas declarado adentro del procedimiento para que se entienda que solo sern usadas por este y por nadie ms. Las variables declaradas en el programa principal son llamadas variables globales y las que se declaran dentro de un procedimiento o una funcin son llamadas variables locales o internas. Las variables globales son visibles dentro de todo el programa, o sea, uno puede hacer referencia a ellas en cualquier parte del cdigo. Por ejemplo, si tenemos una variable global entera llamada / podremos asignarle un valor en cualquier parte de nuestro programa, o sea, escribir /%H&$ en la lnea nmero 5 y luego en la lnea nmero 1258 escribir /%H O o utilizarla en expresiones o para que el usuario ingrese un valor, etc., por citar ejemplos tontos. Las variables locales son visibles solo dentro del procedimiento o la 1uncin en -ue son declaradas* Esto implica que solo podamos hacer referencia a variables locales dentro del bloque principal de su subprograma y n 1uera. Por ejemplo, si tenemos una variable string llamada nombre dentro de un procedimiento podremos utilizarla como queramos solo dentro su bloque principal, por ejemplo con una instruccin readlnInombreJ, pero si escribimos la misma instruccin u otra que implique a dicha variable fuera del bloque principal de su subprograma el compilador no la reconocer porque no la ve y nos dir que no est declarada. Si vemos al programa principal como una mquina, por ejemplo, un vehculo, cada subprograma corresponder a alguna parte que se encarga de una tarea especfica. Por ejemplo, nosotros podemos conducir y utilizar un reproductor de CDs a la vez. La unidad lectora de CDs del vehculo es como un procedimiento que se encarga de reproducir los CDs cuando nosotros lo dispongamos, pero aunque la podemos utilizar cuando queramos y colocar el CD que queramos (este sera nuestro parmetro), no podemos ver ni utilizar sus piezas internas (que seran sus variables locales). De este modo si se rompe la unidad reproductora simplemente debemos ir directamente a ella para repararla sin necesidad de tocar nada ms del vehculo. Lo mismo sucede con nuestros subprogramas. Cdigo: 1 PROGRAM Datos_de_Usuario; 2 3 Var 4 nombre, apellido, documento, direccion: string; 5 6 Procedure Saltear(); 7 Const 8 separador='-'; 9 lineas_a_saltear= 4; 10 11 Var 12 i: integer; 13 Begin 14 For i:= 1 to 20 do 15 Write(separador); 16 For i:= 1 to lineas_a_saltear do 17 Writeln; 18 End; 19 20 BEGN 21 //Pedimos los ingresos al usuario. 22 Write('ngresa tu nombre: '); 23 readln(nombre); 24 write('ngresa tu apellido: '); 25 readln(apellido); 26 write('ngresa tu documento: '); 27 readln(documento); 28 write('ngresa tu direccin: '); 29 readln(direccion); 30 31 //Realizamos la primera separacin. 32 Saltear(); 33 //Escribimos el nombre del usuario. 34 writeln('NOMBRE: ',nombre); 35 36 //Realizamos la segunda separacin. 37 Saltear(); 38 39 //Escribimos el apellido del usuario. 40 writeln('APELLDO: ',apellido); 41 42 //Realizamos la tercera separacin. 43 Saltear(); 44 45 //Escribimos el documento del usuario. 46 writeln('DOCUMENTO: ',documento); 47 48 //Realizamos la cuarta separacin. 49 Saltear(); 50 51 //Escribimos la direccin del usuario. 52 writeln('DRECCN: ',direccion); 53 END. No solo las variables son visibles segn donde estn declaradas, las constantes y los tipos tambin pueden ser globales o locales. Como vemos en este ejemplo, he colocado las constantes de nuestro programa y la variable i dentro del procedimiento Saltear. Si ustedes quisieran referirse a i fuera del procedimiento tendran un error en tiempo de compilacin indicndoles que no encuentra el identificador "i. Esto es porque i no es visible fuera del procedimiento. Es como una pieza de nuestro reproductor de CDs, no podemos verlas ni utilizarlas. Esto garantiza que el procedimiento se dedique nicamente a su tarea y esta no pueda ser modificada accidentalmente por un cambio de valores o cosas por el estilo. Fjense que si tuviramos un programa de miles y miles de lneas donde solo existen variables globales, cuando nuestros subprogramas se dispongan a usarlas, si nosotros no nos dimos cuenta y las modificamos antes en algn lado del programa, realizarn errneamente sus tareas adems de que son totalmente dependientes de lo que sucede globalmente en el programa y por tanto de nuestra suma atencin en el momento de programar. Esto causa que el intentar corregir errores se vuelva una tarea ardua y tediosa cuando en realidad podra ser ms sencillo. En nuestro vehculo no sera aconsejable que funcionara mal el reproductor de CDs porque ser rompi el radiador, por ejemplo, sino que el reproductor es independiente y por ende no depende de las dems piezas del vehculo. A la inversa, no sera bueno que no funcionara el radiador si se nos rompe el reproductor. Esto se aplica a otras muchsimas partes, por supuesto. Obviamente existen componentes que son dependientes unos de otros, pero eso lo veremos ms adelante. Ahora bien, no olvidemos que las variables globales son visibles en todo el programa y podemos usarlas tanto dentro como fuera de los subprogramas. En nuestro vehculo podramos decir que la batera es global ya que es usada por muchas partes y si esta falla todas esas partes fallarn. En realidad lo correcto sera decir que el sistema elctrico es un subprograma donde est declarada la batera y dentro de l tenemos a otros subprogramas como el reproductor de CDs, el claxon, las luces, los limpiaparabrisas, etc, y por tanto para todos estos subprogramas la batera resultara global, aunque no para el resto del vehculo. Dicho de otra manera. Todo lo declarado dentro de un subprograma es local al mismo y por ende solo visible dentro de este, pero resulta global a lo que est declarado all dentro. Siendo as, si tenemos un subprograma dentro del cual hay ms subprogramas, las variables declaradas dentro de l sern "globales a sus subprogramas pero no sern visibles fuera de l. Veamos esto con declaraciones sencillas: Cdigo: PROGRAM alcance_identificadores; Var x, y: integer; Procedure Procedimiento1(); Var a, b: integer;
Procedure Procedmiento2(); Var j, k: integer; Begin //nstrucciones Procedimiento2. End; Begin //nstrucciones Procedimiento1. End; BEGN //nstrucciones programa principal. END. Este es un ejemplo genrico sencillo. Tenemos el programa principal y dos procedimientos, Procedimiento& y Procedmiento de modo que el segundo est declarado dentro del primero. Estn las variables globales / e " declaradas en el programa principal y por ende visibles en cualquier parte del cdigo, dentro o fuera de cualquiera de los procedimientos. Declaradas en Procedimiento& estn las variables a y b las cuales son visibles solo dentro de dicho procedimiento y no fuera. Como Procedmiento est declarado dentro de Procedimiento& estas variables resultan globales para Procedmiento, o sea que son visibles dentro de todo su cdigo. Finalmente dentro de Procedmiento estn declaradas , y 4 las cuales son solo visibles all dentro y en ningn otro lado. Ahora veamos este mismo ejemplo pero con un funcionamiento sencillo: Cdigo: 1 PROGRAM alcance_identificadores; 2 3 Var 4 x, y: integer; 5 6 Procedure Procedimiento1(); 7 Var 8 a, b: integer; 9 10 Procedure Procedmiento2(); 11 Var 12 j, k: integer; 13 Begin 14 x:= 10; 15 y:= 11; 16 a:= 1; 17 b:= 2; 18 j:= 20; 19 k:= 21; 20 21 write(x,' ',y,' ',a,' ',b,' ',j,' ',k); 22 End; 23 Begin 24 Procedimiento2(); 25 End; 26 27 BEGN 28 Procedimiento1(); 29 END. Como ya deberan saber, dadas estas declaraciones, cualquier variable es visible en Procedimiento as que utilizamos este para inicializarlas todas con los valores que ven y luego utilizamos el mtodo WRTE para mostrar estos nmeros en pantalla separados por un espacio. Procedimiento& lo nico que hace es llamar a Procedimiento y el programa principal lo nico que hace es llamar a Procedimiento&. Este programa podra resumirse solo a tener Procedimiento o incluso ni tenerlo, pero es para que aprendan esto del alcance de los identificadores de las variables y dems estructuras. Ahora bien. Qu pasa si escribimos la instruccin de la lnea 21 fuera de Procedimiento? Si lo hacemos dentro Procedimiento& tendramos un error de compilacin ya que dentro del WRTE hacemos referencia a las variables , y 4 y estas solo son visibles dentro de Procedimiento. Si lo hacemos fuera de Procedimiento& tendramos un error del mismo tipo al anterior ya que hacemos referencia a las variables a, b, , y 4 que no son visibles fuera de sus procedimientos. Por este motivo el nico que puede mostrar en pantalla los resultados es Procedimiento ya que es donde son visibles todas las variables de nuestro programa. No hace falta inicializar todas las variables dentro de Procedimiento. Veamos el mismo ejemplo pero inicializando cada variable dentro de su procedimiento para luego mostrar el resultado en pantalla: Cdigo: 1 PROGRAM alcance_identificadores; 2 3 Var 4 x, y: integer; 5 6 Procedure Procedimiento1(); 7 Var 8 a, b: integer; 9 10 Procedure Procedmiento2(); 11 Var 12 j, k: integer; 13 Begin 14 j:= 20; 15 k:= 21; 16 17 write(x,' ',y,' ',a,' ',b,' ',j,' ',k); 18 End; 19 Begin 20 a:= 1; 21 b:= 2; 22 Procedimiento2(); 23 End; 24 25 BEGN 26 x:= 10; 27 y:= 11; 28 Procedimiento1(); 29 END. Este programa produce exactamente la misma salida que el anterior. Solo hemos inicializado las variables en distintos lugares. Deben identificar bien cada bloque, o sea, cual pertenece al programa principal, cual a un procedimiento y cual al otro. Si no logran entender esto no deben continuar hasta que lo hayan logrado ya que esto forma parte de la base necesaria para entender subprogramas. Lo que viene a continuacin requiere que hayan comprendido donde puede visualizarse cada variable en dependencia de donde ha sido declarada. Sombreado de (denti1icadores% Bien, continuemos con esto del alcance de los identificadores. Hasta ahora simplemente hemos visto que cada variable es visible dentro del cuerpo del subprograma en que ha sido declarada y no fuera. Ahora bien, la complicacin con esto comienza cuando tenemos una variable global con cierto nombre y luego en un subprograma tenemos una variable local con el mismo nombre. Pero como? No era que no pueden repetirse identificadores? En efecto, no pueden repetirse, pero como hemos visto, una variable local es visible solo dentro del subprograma donde se ha declarado y por tanto fuera de este es como si no estuviera declarada, como si no existiera, por lo tanto es posible declarar otra con el mismo nombre. Pero si la variable global es visible dentro de un subprograma, cuando adems declaramos dentro de este una variable local con el mismo nombre cmo sabemos a cual nos estamos refiriendo dentro del subprograma? Esto es simple pero genera muchas confusiones. Si tenemos una variable global con un nombre idntico al de una local, cuando dentro del subprograma nos referimos a ese identificador tiene precedencia la variable local, o sea, esta "sombrea a la global dentro del subprograma. Veamos un ejemplo bien sencillo de entender: Cdigo: 1 PROGRAM sombreo_identificadores; 2 3 Var 4 X: integer; 5 6 Procedure sombreo(); 7 Var 8 X: integer; 9 10 Begin 11 X:= 10; 12 End; 13 14 BEGN 15 Sombreo(); 16 END. En este ejemplo tenemos una variable global ` y una local dentro del procedimiento sombreo tambin llamada `. Como vemos, dentro del procedimiento he inicializado ` en 10. El programa principal lo nico que hace es llamar al procedimiento. Cul de las dos ` vale 10? Como la inicializacin fue dictada dentro del procedimiento, al referenciar a ` nos estamos dirigiendo a la ` local y no a la global, por lo tanto la ` que vale 10 es la interna al procedimiento y la otra no sabemos cuanto vale porque no le hemos dado ningn valor an. Ahora veamos otro ejemplito sencillo: Cdigo: 1 PROGRAM sombreo_identificadores; 2 3 Var 4 X: integer; 5 6 Procedure sombreo(); 7 Var 8 X: integer; 9 10 Begin 11 X:= 10; 12 Writeln(X); 13 End; 14 15 BEGN 16 X:= 5; 17 Sombreo(); 18 Write(X); 19 END. Ahora he inicializado ambas variables, la global con el valor 5 y la interna con el valor 10. Cmo ser la salida de este programa? ------------------------------------------------------------------------------------- Bien, hasta aqu hemos llegado por ahora. No dejar ejercicios ya que lo que deben hacer ustedes es entender los ejemplos. Ms adelante tendrn bastante para practicar. Saludos.