UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. 4. Desarrollo de programas básicos. Introducción informal. Se emplearán las acciones sobre datos (vistas en 2.1, 2.2 y 2.3): entrada, asignación y salida; y las acciones de control: concatenación, alternativa e iteración (vistas en 3.1, 3.2 y 3.3). En los ejemplos que se verán a continuación, se destacarán aspectos del lenguaje: léxico, sintáctico y semántico; fundamentos de programación interactiva, uso de mensajes y avisos (prompts en inglés); también se destacarán técnicas para la correcta construcción de los bloques estructurados básicos. En los desarrollos siguientes es de fundamental importancia captar las relaciones entre el texto del programa y la ejecución o computación de éste. 4.1. Mensajes. a) Código: Program mensaje; begin write('Mi primer programa') end. b) Observaciones respecto del lenguaje. ♦ La secuencia de caracteres Program (programa en castellano) indica, en el texto, el inicio del programa. ♦ El nombre del programa es la palabra mensaje que fue elegida por el programador. ♦ El ; después del nombre del programa es un delimitador que da fin al nombre. ♦ El algoritmo queda ubicado entre las palabras begin (comienzo o principio en castellano) y end (fin). ♦ El punto final indica el fin del programa. ♦ La secuencia de caracteres gráficos entre comillas simples se denomina "string" (fila o tira de caracteres). ♦ Observamos que en el programa mensaje no hay variables. c) Edición, Compilación, Ejecución. Prof. Leopoldo Silva Bijit. 07-07-2003 15 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. El programa debe ser pasado desde el papel a un archivo del sistema. Este proceso se realiza mediante un programa especial denominado Editor de Textos. Luego el programa fuente, el texto recién escrito, debe ser compilado. Es decir debe ser traducido a una secuencia de instrucciones que la máquina básica es capaz de interpretar. Después el programa objeto, el recién compilado, debe ser ejecutado. Su ejecución simplemente da por resultado la escritura en la pantalla de la frase: Mi primer programa. ( sin las comillas simples). Existe una alternativa a la compilación, y es la interpretación; ésta consiste en la traducción del texto fuente a un lenguaje de una máquina virtual. Luego se carga en memoria el programa intérprete que, como su nombre lo indica, es capaz de interpretar cada una de las instrucciones de la máquina virtual. Por supuesto que el programa intérprete debe estar escrito en el lenguaje de la máquina física. (host computer, computador huésped). En lo sucesivo, asumiremos que disponemos de un intérprete del lenguaje Pascal; en este caso, es el mismo programador que opera como una máquina virtual Pascal. De este modo podremos evocar el proceso asociado al programa. El ejemplo muestra como introducir un mensaje en la salida. El objetivo de éstos, como se verá más adelante, es hacer más comprensible la salida. Una variante del mensaje es el 'prompt', que es un texto que se envía hacia la salida para alertar al operador; indicándole que se requiere su intervención para que efectúe una entrada de datos. 4.2. Lectura de datos. a) Código Program lectura; var dato: integer; begin read(dato) . end b) Observaciones respecto al lenguaje: Prof. Leopoldo Silva Bijit. 07-07-2003 16 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. ♦ Se ha efectuado una declaración de variables. Se ha asociado al nombre dato el tipo entero (integer en inglés). La zona de declaración es antes del algoritmo y comienza con la palabra reservada var. Se dice reservada pues el programador no puede usar ese nombre para bautizar sus propias variables. ♦ El tipo entero es un tipo básico estándar. En la práctica el máximo entero representable depende del computador. Suele ser una potencia de dos, ya que los enteros suelen guardarse en la memoria como un número binario. ♦ El programa tiene un defecto fundamental y es que no hay salida. Debido a esto no queda constancia de si se ejecutó o no. c) Proceso. Al ejecutarse, primero se reserva el espacio destinado a un entero en un lugar que queda asociado al nombre dato; nombre que el programador escogió para su variable. Luego el cursor en el terminal queda a la espera que el operador efectúe la entrada de un entero, esto corresponde a la digitación de una secuencia de números decimales (cuyo valor no sea mayor que el máximo representable); el final del número queda determinado al digitar en el teclado un carácter que sea diferente de los dígitos decimales. El valor queda almacenado en dato. Por razones prácticas, los números digitados son copiados en el terminal; de esta manera el operador tiene una realimentación visual de lo que está digitando. Esto suele denominarse 'lectura con eco'; debe tenerse presente que la escritura en el terminal no corresponde a una salida de datos. Es perfectamente posible efectuar 'lecturas sin eco'; suele emplearse este método cuando se digita la palabra secreta de acceso al sistema (password). 4.3. Sumar dos enteros. a) Código: Program suma; var x,y:integer; begin writeln; write('Entre el primer número: '); read(x); writeln; write('Entre el segundo número: '); read(y); Prof. Leopoldo Silva Bijit. 07-07-2003 17 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. writeln; write('La suma es: '); write(x + y); writeln end. b) Observaciones: ♦ Se leen las variables con un prompt. ♦ Todas las acciones del algoritmo se separan mediante un punto y coma. ♦ Se ha introducido una instrucción primitiva de salida con el nombre writeln. Que es una abreviatura de write line (escriba línea). La acción que ejecuta es avanzar el cursor desde la posición en que se encuentre, hasta la primera posición de la línea siguiente. ♦ Esto permite dar forma a la salida. Suele hablarse de salida formateada (o con forma). ♦ Se escribe un mensaje que da significado al resultado. ♦ Finalmente se escribe el valor del resultado; nótese que el argumento de write es una expresión. ♦ Se habla de programación interactiva, cuando el programa dialoga en forma amistosa, con el operador. No cabe duda que la omisión de los prompts y el mensaje, harán el diálogo menos amigable, y más difícil de entender. ♦ En la declaración de variables se ha empleado una lista (variables separadas por comas) de variables de igual tipo. 4.4. Repetición del programa. Los programas desarrollados hasta aquí sólo se ejecutan una vez, y luego se retorna al sistema operativo. Para mantener al programa en la memoria principal suele emplearse el siguiente esquema: a) Código: Prof. Leopoldo Silva Bijit. 07-07-2003 18 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. Programa repetición; var ch:char; {variables del bloque} begin ch := 'S'; while ch = 'S' do begin {bloque de repetición} write('Desea continuar? (S/N)'); read(ch); readln end end. b) Observaciones: ♦ La variable ch puede adoptar los valores de los caracteres digitables en el teclado. ♦ Al inicio se asigna a ch el valor 'S', esto se denomina inicialización de la variable ch. ♦ El algoritmo propiamente tal, y que se desea volver a repetir, se ubica dentro del bloque del do. ♦ Al final del bloque se pregunta si se desea continuar y se permite leer un valor para ch. ♦ La instrucción readln se emplea para descartar todos los caracteres que se digiten hasta el retorno de carro. Es equivalente a no considerar toda la entrada que se digite en el teclado hasta encontrar un retorno, lo cual finaliza la instrucción. ♦ Notese que ch = 'S' es una condición y es verdadera si el carácter digitado es la letra ese mayúscula. Si se deseara incluir la ese minúscula, el código adecuado sería: (ch = 'S') or (ch = 's') ♦ El mensaje no es muy adecuado, pues sólo continúa si se oprime la ese mayúscula; en cualquier otro caso termina la ejecución y se retorna al sistema operativo. Un mejor mensaje es: 'Oprima <S> para continuar'. ♦ Esta forma de mantener el programa en memoria, permite revisar su comportamiento frente a diversas variaciones de la entrada; procedimiento que se denomina verificación. Cuando se diseña un programa debe considerarse cómo se verificará que funcionará de acuerdo a las especificaciones. Prof. Leopoldo Silva Bijit. 07-07-2003 19 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. ♦ Los paréntesis de llave se emplean para denotar comentarios. En el programa anterior, se han empleado comentarios para indicar la posición que deben ocupar las variables y acciones del bloque que se desea repetir c) Empleando la sentencia repeat. Program repetición; var ch:char; {variables} begin repeat {acciones} write('Para Salir (S): '); read(ch); readln until ch = 'S' end. Nótese que en este caso no es necesario inicializar la variable ch. 4.5. Concepto de asignación. El concepto de asignación es de fundamental importancia en programación. El siguiente ejemplo ilustra algunos aspectos de interés: a) Código: Program asignación; var x,y,z :integer; begin read(x);read(y); z:=x+y; x:=z+x; y:=z*x; write(x,y,z) end. b) Observaciones. Las reglas que gobiernan la construcción de expresiones son las siguientes: Prof. Leopoldo Silva Bijit. 07-07-2003 20 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. i) Cualquier variable que se emplee en una expresión debe tener un valor asignado previamente. Ya sea por lectura o por una asignación previa, en la que dicha variable figure al lado izquierdo de una asignación. ii) Nunca debe escribirse un operador al lado de otro. Por ejemplo: x*-y No es una expresion legal; debe escribirse: x*(-y) iii) iv) v) Nunca debe omitirse un signo de multiplicación, como suele efectuarse en la notación algebraica. Por ejemplo: 2n no es expresión correcta; debe codificarse: 2*n En general se realizan primero las multiplicaciones y divisiones antes que las sumas y restas. Esto dependerá de las reglas de precedencia de los operadores del lenguaje. Se recomienda siempre, en caso de duda, mejorar la claridad de la expresión, mediante el empleo de paréntesis redondos. En estos casos los paréntesis abiertos deben existir en igual número que los paréntesis cerrados; lo anterior se conoce como la regla de balance o equilibrio de paréntesis. c) Traza. Debe recordarse que la secuencia de asignaciones, en el texto del programa, se refleja en diferentes instancias en el tiempo, en el proceso que las implementa. Una forma adecuada de reflejar lo anterior es el procedimiento que se denomina Traza. Que consiste en especificar los valores que toman las variables, una vez que se ha ejecutado la instrucción. Traza Instrucción read(x) read(y) z:=x+y x:=z+x y:=z*x write(x,y,z) x 4 y indefinido 1 z indefinido indefinido 5 9 Prof. Leopoldo Silva Bijit. Observaciones Se asume que se digitó un cuatro Se asume que se digitó un 1 Cambia el valor de x Cambia valor de y Se escribe: 9 45 5 45 07-07-2003 21 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. d) Importancia del orden. i) En el programa anterior si se hubiese cambiado el orden, por ejemplo: x:=z+x; z:=x+y; y:=z*x Habría ocurrido un error; pues el valor de z está indefinido, en el momento de evaluar la primera expresión. ii) En caso de que el orden fuera: z:=x+y; y:=z*x; x:=z+x Se habría escrito: 20 20 5; en caso de haber leído x igual a 4, e y igual a 1. e) Limitaciones de la aritmética discreta. Si por ejemplo el máximo entero representable fuera 65536, y si los números leídos para x e y, sumados exceden este valor, se produciría un error; denominado rebalse (overflow en inglés). Y los valores restantes estarán todos errados. El disponer de una aritmética discreta, hace bien diferente la notación algebraica tradicional respecto del lenguaje usado en programación. Más adelante se desarrollará más sobre este asunto. f) Intercambio de valores entre dos variables (swap en inglés). El intercambio de valores entre dos variables refuerza el concepto de asignación. Puede comprobarse que la secuencia: x:=y; y:=x no cumple con los requisitos; pues la primera asignación borra el valor anterior de x. Es preciso introducir una variable z, en forma temporal, y especificar las tres asignaciones siguientes: z:=x; x:=y; y:=z Se denomina temporal, pues su existencia sólo es necesaria mientras dura el intercambio. La variable temporal z permite salvar el valor de x; luego se copia el valor de y en x; y finalmente se le asigna a y el valor inicial de x guardado en z. Luego de esto no es necesaria la variable z. Prof. Leopoldo Silva Bijit. 07-07-2003 22 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. 4.6 Selección de múltiples alternativas. Dado un cierto número de posibles acciones alternativas, la elección de una de ellas puede realizarse mediante estructuras de control selectivas. En el caso de elegir dos alternativas es suficiente la acción de control: if <condición> then <acción 1> else <acción2> Se verán algunos ejemplos en los que existen alternativas múltiples. 4.6.1 Buscar el mínimo de tres números enteros. a) Se decide tener tres variables; x, y, z para representar los números. Adicionalmente se empleará la variable mín para almacenar el valor mínimo. Al fin de la acción, no deben modificarse los valores de x, y, z. El siguiente diagrama de flujo estructurado describe gráficamente un algoritmo que busca el mínimo de tres números: x<y V V x<z min:=x F V F y<z F min:=z min:=y min:=z Puede codificarse según: if x<y then { falta comparar x con z} if x<z then min:=x else min:=z else {falta comparar y con z} if y<z then min:=y else min:=z Nótese que se destacan los bloques de selección interna, mediante un adentramiento del margen izquierdo; esto se denomina indentación. Prof. Leopoldo Silva Bijit. 07-07-2003 23 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. Con fines de mejorar la legibilidad del texto, y para enfatizar los conceptos de la estructura: conviene escribir, siempre que sea posible, una acción compuesta en una línea de código. A veces las componentes corresponden a una larga secuencia de acciones; en este caso los bloques internos se destacan mediante indentación. Las frases entre paréntesis de llave son comentarios. b) El método anterior no es el único posible. Por ejemplo, el siguiente segmento realiza también la búsqueda del mínimo. Se asume que uno de los números es el menor; y luego se compara con los siguientes: .... min:=x; if y<min then min:=y; if z<min then min:=z; .... Prof. Leopoldo Silva Bijit. 07-07-2003 24 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. 4.6.2 Condiciones mutuamente excluyentes. En ciertas situaciones se tienen condiciones mutuamente excluyentes, cada una de las cuales condiciona una acción diferente. a) Sean tres condiciones y cuatro acciones: V C1 F C2 F V C3 V A1 A2 A3 F A4 Puede escribirse: .... if C1 then A1 else if C2 then A2 else if C3 then A3 else A4 .... Si las acciones son compuestas, deben definirse nuevos bloques, y posiblemente nuevos márgenes indentados. Una forma alternativa de escribir el mismo segmento es el siguiente: .... if C1 then A1 else if C2 then A2 else if C3 then A3 else A4 .... Prof. Leopoldo Silva Bijit. 07-07-2003 25 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. que consiste en colocar después de else el siguiente if. Nótese que nunca se coloca un punto y coma antes de un else; esto se justificará más adelante. En ciertos casos es posible establecer las condiciones en términos de una variable. Por ejemplo la condición 1 puede asociarse a un valor 1 de la variable de control; la condición 2 al valor 2; y así sucesivamente. En este caso puede emplearse una instrucción de control denominado caso de (case of en inglés). b) Otra forma de tres condiciones excluyentes es: C1 V F C2 V F C3 V A1 F A2 A3 A4 Que puede escribirse: .... if C1 then if C2 then if C3 then A1 else A2 else A3 else A4 .... Nótese que cada margen está asociado a un bloque. 4.6.3 Minimización. Ejemplo de Algebra de Boole. Prof. Leopoldo Silva Bijit. 07-07-2003 26 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. Si las acciones no están condicionadas en forma excluyente, se puede, a través del álgebra de Boole, lograr simplificaciones del código. En el siguiente ejemplo, se realiza la acción A1 o la acción A2: C1 V F C2 V A1 F A2 V A1 C3 F A2 …. if C1 then if C2 then A1 else A2 else if C3 then A1 else A2 ….. Puede observarse que la acción A1 se realiza si se cumple que: (C1 AND C2) OR ( (NOT C1) AND C3) Entonces puede escribirse: If (C1 AND C2) OR ( (NOT C1) AND C3) then A1 else A2 Debe notarse que la descripción de acciones se simplifica; pero al mismo tiempo resulta una condición más compleja. Se han empleado operadores lógicos (NOT, OR, AND) y abundante uso de paréntesis para escribir la condición; ésta podría eventualmente reducirse de acuerdo a reglas del Algebra de Boole. Cuando se emplean paréntesis, el número de paréntesis abiertos debe ser igual al número de paréntesis cerrados. Si se hubiera preferido; podría haberse establecido la condición para la ejecución de A2: Prof. Leopoldo Silva Bijit. 07-07-2003 27 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. if ((NOT C2) AND C1) OR ((NOT C3) AND (NOT C1)) then A2 else A1 4.6.4 Abuso de cláusula condicional. En caso de asignar un valor a una variable lógica, que sólo puede ser verdadera o falsa, de acuerdo a cierta condición, suele escribirse: if condición then vlógica:=true else vlógica:=false Es más simple escribir, sin emplear if: vlógica:=condición 4.6.5 Ambigüedad semántica. La posibilidad de la cláusula condicional if..then (sin else) produce ambigüedades en el significado del secuenciamiento de acciones, en caso de estar dentro de bloques de alternativa. Por ejemplo: if C1 then if C2 then A1 else A2 Puede interpretarse según: a) b) C1 V C2 C2 V A1 C1 V F F A2 A1 A2 Diagramas que no son equivalentes; es decir no significan lo mismo. Por esta razón se dice que existe ambigüedad. Una forma de resolver lo anterior, es definir un significado para dicha construcción. El Report pág. 151 aclara que el significado es el dado por el diagrama a). Prof. Leopoldo Silva Bijit. 07-07-2003 28 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. No obstante lo anterior, es recomendable emplear la siguiente notación, para describir los diagramas estructurados anteriores: a) b) if C1 then begin if C2 then A1 else A2 end if C1 then begin if C2 then A1 end else A2 4.7 Iteración. Repetición. Cuando se desea repetir una acción simple o compuesta bajo el control de una condición; y el número de veces que se repite no se conoce de antemano; y además si la acción puede que no se efectúe ninguna vez, suele usarse la cláusula While..do. 4.7.1 Cálculo de la potencia de un entero positivo. Se desea obtener: b elevado a e; donde b es la base y e el exponente. Si ambos números deben leerse desde el medio externo y el resultado debe guardarse en la variable de nombre potencia, un programa que cumple las especificaciones anteriores es el siguiente: Prof. Leopoldo Silva Bijit. 07-07-2003 29 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. Program Calcpotencia; var b, e, potencia, contador: integer; begin read(b); readln; {1} read(e); readln; {2} contador:=0; potencia:=1; {3} while contador<e do begin potencia:=potencia*b; contador:=contador+1 {4} end; write(potencia);writeln {5} end. El texto del programa no incluye mensajes ni prompts para no desviar la atención de lo esencial. Tampoco se valida la entrada; es decir, no se efectúan verificaciones que los valores leídos para b y e sean enteros positivos. Deben observarse los siguientes aspectos o reglas constructivas para un bloque while: a) Reglas para el While. i) Las variables que forman la condición deben haber sido inicializadas antes de entrar al while. Es decir, deben tener valores asignados. ii) Alguna de las variables que forman la condición deben tener una asignación dentro del bloque de acciones del while. iii) Cada vez que se efectúe el bloque, la condición debe estar más cerca de cumplirse. iv) Si la condición no se satisface inicialmente, debe proveerse valores para las variables que tienen asignaciones en el bloque. Este es el caso, si en el ejemplo se lee un valor de exponente cero; por esta razón se inicializa potencia con valor uno. v) Una forma adecuada de verificar la construcción del bloque es mediante la inducción matemática. Prof. Leopoldo Silva Bijit. 07-07-2003 30 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. En esta situación, en lugar de razonar enumerativamente; es decir, revisando cada uno de los casos que se producen, conviene ubicar alguna relación que no cambie durante la repetición. Esto se denomina invariante del lazo. En el ejemplo el invariante es: potencia = bcontador vi) A pesar de que la paciencia de un computador es enorme, debe evitarse la repetición de computaciones idénticas dentro del bloque que se repite. Esto puede detectarse si existen expresiones cuyas variables no cambian su valor dentro del bloque. b) Puede apreciarse, en el programa calcpotencia que el número de veces que se repite el bloque depende de un valor que se digita en el teclado. Además si se digita cero, el bloque no se efectuará. c) Contadores: A menudo suelen ocuparse variables sobre las cuales sólo se actúa para incrementarlas o decrementarlas en uno. Este es el caso de la variable contador en el ejemplo. A este tipo de variables suele denominárselas contadores. En un caso general si el incremento es un entero n se habla de un contador progresivo módulo n; en caso que el decremento sea una constante entera n se habla de contador regresivo módulo n. d) Inicialización de variables. De acuerdo a la regla i) y iv) para la construcción de while, es necesario dar valores a ciertas variables antes de entrar al while. En el ejemplo, el contador se inició en cero; y la potencia en uno. e) Traza en repeticiones. Se denomina traza al procedimiento de registrar, ordenadamente en el tiempo, los valores que van tomando las variables para una determinada entrada. Corresponde a una verificación de la corrección del algoritmo para una entrada dada. En el caso de segmentos que involucran repeticiones es preciso identificar la instancia de repetición. En el programa se han agregado como comentarios, números de línea que nos servirán para efectuar la traza. Al número de las líneas que se repiten, se les agregará un indicador de la Prof. Leopoldo Silva Bijit. 07-07-2003 31 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. instancia de repetición. Los valores que se registran son aquellos que resultan después de haber efectuado el paso. Traza b e contador potencia observaciones 1 2 Se digitó 2 para la base 2 4 Los guiones indican valores indefinidos. 3 0 1 Inicialización 4.1 1 2 4.2 2 4 4.3 3 8 4.4 4 16 5 Se escribe 16 Nótese que dentro del bloque, pasos 4.1 a 4.4, se cumple que: bcontador = potencia que es el invariante del lazo. Además en cada paso la condición está más cercana a cumplirse. Prof. Leopoldo Silva Bijit. 07-07-2003 32 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. f) Se podría haber empleado un contador regresivo. { ---- } contador := e ; potencia := 1; while contador > 0 do begin potencia := potencia*b; contador := contador - 1 end {----- } Traza 1 2.1 2.2 2.3 2.4 b 2 e 4 contador 4 3 2 1 0 {1} {2} potencia 1 2 4 8 16 Invariante del lazo: be-contador = potencia En este caso contador parte con valor inicial positivo y dentro del bloque se lo va disminuyendo. Y la condición de terminación tiende a cumplirse, lo que se ilustra en el diagrama siguiente: Variación Contador CT Condición de término VI Valor Inicial 4.7.2. Repeticiones de computaciones idénticas. En el siguiente segmento: { ---- } while i < 3*N do begin w := x + y*z + z*i; i := i+1 end; Prof. Leopoldo Silva Bijit. 07-07-2003 33 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. { ---- } Las variables N, x, y, z no cambian dentro del bloque; una manera más efectiva de realizar la computación es: { --- } n := 3*N ; u := x + y*z; while i < n do begin w :=u + z*i; i := i + 1 end; { --- } Lo anterior requiere definir las variables n y u. Si bien la codificación anterior es conceptualmente adecuada; en la práctica, la mayor parte de los compiladores actuales generan código optimizado que contempla, entre otras cosas, la extracción de computaciones idénticas en bloques de repetición. 4.7.3. Cláusula Repeat. La palabra cláusula se emplea con el significado de frase. Como sinónimo se usa a veces sentencia . Se suele emplear esta secuenciación de acciones cuando se conoce que el bloque debe repetirse a lo menos una vez. El resto de las reglas para esta construcción son similares a las vistas en 4.7.1.a). Adicionalmente las variables que componen la fórmula de la condición pueden ser inicializadas dentro del bloque; es decir, las variables de la condición pueden estar indefinidas antes de entrar al repeat. a) Indefinición de variable de control antes de ingresar al bloque. .... repeat | | read(ch) until ch = 'N'; .... Prof. Leopoldo Silva Bijit. 07-07-2003 34 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. Se repite hasta leer un caracter N mayúscula. b) Comienzo y fin del bloque de repetición. En el caso de esta instrucción, no es necesario emplear begin y end para definir el comienzo y fin del bloque. Las palabras reservadas repeat y until sirven para este propósito. 4.7.4. Multiplicación de enteros positivos mediante sumas. El algoritmo siguiente describe un segmento que efectúa la multiplicación no destructiva de dos enteros x e y mediante la realización de sumas. Se denomina no destructiva pues se preservan los valores de los operandos; lo anterior demanda la definición de una variable para guardar el producto (sea z el resultado). La operación sería destructiva, si el resultado se almacenara en uno de los operandos. En este caso no se requiere una variable adicional. Los lenguajes de alto nivel suelen tener definidas las operaciones elementales para los tipos estándar. El producto, que suele indicarse con un arterisco, generalmente está definido. Sin embargo, el segmento que se describe a continuación se limita a multiplicar a través de sumas para ilustrar cómo se elaboran operaciones complejas a partir de otras más simples. Sea y la variable que se sumará repetidamente; la variable x contendrá el número de veces a repetir. Se precisa una variable (sea u) que cuente dicho número de veces. Entonces: ---z:=0 ; u:= x; repeat z:=z + y; u:=u - 1 until u = 0 ---Nótese que el segmento debe estar protegido para no aceptar valores negativos o iguales a cero para x. En caso de x <= 0 se tendrá un repita para siempre (do forever); lo cual es inaceptable. El número de veces que se repite el bloque depende de x. A mayor x, mayor número de veces se repite la acción compuesta. Prof. Leopoldo Silva Bijit. 07-07-2003 35 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. Al asumir que x e y serán mayores que cero se tiene que el bloque se repetirá por lo menos una vez. Y puede emplearse la sentencia repeat. Empleando la instrucción while puede aceptarse una valor cero para x; restringiendo sólo los valores negativos. Se desea ahora disminuir el número de veces que se repite el bloque. Una variación del algoritmo anterior es aceptar como operaciones permitidas a la multiplicación y división por 2, además de la suma. Puede comprobarse que cuando los números se representan en el sistema binario, las operaciones de multiplicación y división por dos corresponden a corrimientos de los dígitos hacia la izquierda y derecha respectivamente. Estas operaciones, incluída la suma, suelen estar implementadas a nivel electrónico; es decir son instrucciones de máquina. Número binario 01000 00100 00010 00001 Decimal equivalente 8 4 2 1 El operador div se emplea para representar la división entera. El resultado es la parte entera del cuociente. Ejemplo: 4 div 2 tiene valor 2 4 div 3 tiene valor 1 1 div 2 tiene valor 0 El código siguiente emplea la función odd(u) que da valor verdadero si u es impar ; y falso si u es par. Odd significa impar en español. En sistema binario la condición odd equivale a preguntar por el estado del último bit del número; es impar si es uno, en caso contrario es par. Entonces: Prof. Leopoldo Silva Bijit. 07-07-2003 36 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. ----z:=0; u:=x; v:=y; while u <> 0 do begin if odd(u) then z:=z+v; u:=u div 2; v:= 2*v end; ----Cada vez que se realiza el bloque de repetición, el valor de u disminuye a la mitad. Entonces el número de veces n, que se repite el bloque, queda determinado por el menor valor de n que cumple: 2^n > x Tomando logaritmo en base 2, se obtiene: n > log x El número de veces n, que se repite el bloque, también queda determinado por el mayor valor de n que cumple: 2^(n-1) > x Tomando logaritmo en base 2, se obtiene: n-1 <= log x Graficando las curvas de x y log x, puede comprobarse que este algoritmo siempre es más eficiente que el anterior (para todo x entero). 4.7.5. División como restas sucesivas. Dividir el número natural x por el número natural y; dejando el cuociente entero en q y el resto de la división en r. Pero sólo empleando sumas y restas. En Pascal existen los operadores div y mod que realizan directamente las operaciones anteriores. a) Mediante while: Prof. Leopoldo Silva Bijit. 07-07-2003 37 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. -----q := 0; r := x; {x>=0; y>0} while r >= y do begin r:=r-y; q:=q+1 end; ------ Prof. Leopoldo Silva Bijit. 07-07-2003 38 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. b) Mediante repeat: -----q := 0; r := x; {x>0; y>0} repeat r := r-y; q:=q+1 until r < y -----4.7.6. Repeat en términos de while. Puede comprobarse que la estructura básica de la repetición es el while. Veremos que la instrucción repeat puede implementarse en términos de while. Recordemos la configuración para el while: V C F while C do A A El siguiente diagrama muestra la sentencia repeat: A repeat A until C V C F Entonces de acuerdo al algebra de Boole, se tendrá, modificando el diagrama para el repeat: A repeat A until (not C) F not C Prof. Leopoldo Silva Bijit. 07-07-2003 V 39 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. Y también se tendrá, que el siguiente diagrama de flujo es equivalente semánticamente al anterior: A A A; repeat A until (not C) F V not C El que comparado con el diagrama del while, nos permite escribir que: repeat A until C es equivalente a: A A; while not C do A V F not C A Prof. Leopoldo Silva Bijit. 07-07-2003 40 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. 4.8. INTRODUCCION A LOS PROCEDIMIENTOS. Se han estudiado tres formas para la secuenciación de acciones; la concatenación, la alternativa y la iteración. Existe otra forma elemental de indicar el orden en que se efectuarán las acciones, y consiste en asignar un nombre a un grupo de acciones. Lo anterior se efectúa con una declaración que convierte al grupo de acciones en una unidad llamada procedimiento. Ejemplo: Rectángulo de asteriscos. Se desea construir un rectángulo de 4 renglones por tres columnas, en cada posición se debe dibujar el carácter asterisco. Una forma de describir lo anterior: Repetir 4 veces: escribir un renglón pasar al siguiente renglón; A su vez la orden escribir un renglón puede descomponerse en: Repetir 3 veces: escribir un asterisco. Es preciso tener una variable para contar los renglones (sea r) y otra para contar las columnas (sea c). A continuación se describe un programa que desarrolla lo anterior: Program rectángulo; Var r:integer; Procedure asterisco; Begin write('*') End; Procedure Renglon; Var c:integer; Begin c:=0; Repeat asterisco; c:=c+1 until c=3 End; {renglon} Prof. Leopoldo Silva Bijit. 07-07-2003 41 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. Begin {rectángulo} r:=0; Repeat renglon; writeln; r:=r+1 until r=4 End. *** *** *** *** Debe notarse que la estructura de construcción de un procedimiento es similar a la de un programa; excepto que la parte que describe el algoritmo queda terminada en punto y coma y no en punto. Las acciones agrupadas por la declaración de procedimiento van ubicadas antes de la parte algorítmica del programa principal. En el diseño de programas los procedimientos juegan un papel fundamental: permiten descomponer un programa en unidades lógicamente coherentes y además facilitan la visualización de la estructura del algoritmo principal. En el caso de programas largos; es decir, algoritmos complejos, lo anterior es particularmente importante. En el ejemplo anterior puede considerarse rebuscado el haber declarado procedimientos separados para acciones tan simples; y quizá resultaría también simple de entender, el programa que se obtendría al reemplazar los identificadores renglón y asterisco por las acciones básicas que representan. Sin embargo, aún en casos simples, es recomendable el empleo de procedimientos si se logra mayor claridad de la estructura del programa. La agrupación de numerosas acciones bajo un nombre, resulta particularmente útil cuando el mismo procedimiento se invoca en diferentes puntos de un programa. Ya que esto reduce el largo del programa y por lo tanto la tarea del programador; adicionalmente se reducen los riesgos de cometer errores. Desde el punto de vista de la secuenciación de acciones cuando se invoca a un procedimiento por su nombre, se realizan a continuación las acciones especificadas en su declaración; luego de efectuadas éstas, se retorna a la siguiente instrucción (la que está ubicada después del nombre). En esta introducción del concepto de procedimiento se hace énfasis en el aspecto de agrupar accio nes por un nombre; es decir, la abstracción de una secuencia compleja de acciones primitivas mediante un símbolo (el nombre del procedimiento). Como se verá más adelante, existen otros aspectos conceptuales de suma importancia en el diseño de Prof. Leopoldo Silva Bijit. 07-07-2003 42 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 4. Desarrollo de programas básicos. procedimientos, y son los relativos a la forma de comunicación entre el programa principal y los procedimientos y a los mecanismos de acceso a la información. Prof. Leopoldo Silva Bijit. 07-07-2003 43