Sunteți pe pagina 1din 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.

S-ar putea să vă placă și