Notas de clase: Fundamentos de Programación
Fases de creación de un programa
El proceso de resolución de problemas en un computador conduce a la escritura de un programa y su ejecución. Las fases en el desarrollo de un programa pueden resumirse de la siguiente forma:
Analizar el problema consiste en conocer perfectamente en qué consiste y qué resultados se desean obtener.
Planificación de la resolución del problema, dividiéndolo, si es complicado, en una secuencia de etapas más simples. Esta fase se lleva a cabo EN UN PAPEL, estableciendo lo más claramente posible la finalidad de cada etapa, los datos que se necesitan de entrada, los datos que producirían en salida, los algoritmos (ver la Sección 5.2) que se utilizarán, etc.
Edición del código fuente, es decir, escritura del mismo utilizando un editor de textos simple (sin formato) y un lenguaje de programación. Los programas fuente serán almacenados en ficheros de texto, normalmente en el disco duro del computador.
Compilación y ejecución del programa al lenguaje máquina.
Corrección de errores del programa. Los errores se corregirán en el código fuente, repitiendo los pasos 3 y 4 tantas veces como sea necesario. Si se producen errores en la lógica del programa, es decir, si el programa “funciona” pero produce resultados incorrectos, hay que modificar el algoritmo volviendo al paso 2. Estos errores son los más difíciles de detectar.
Documentación. Una vez que el programa funcione correctamente, es conveniente revisar el código fuente para ordenarlos, eliminar cálculos innecesarios e incluir las líneas de comentario necesarias, que normalmente deben incluir unas breves explicaciones al principio del código sobre la finalidad del programa y sus argumentos de entrada y de salida.
Algoritmos
Un computador es capaz de realizar “sólo” determinadas acciones sencillas, tales como sumar, comparar o transferir datos, pero los problemas que normalmente interesa resolver son más complejos.
Para resolver un problema real es necesario, en primer lugar, encontrar un método de resolución y, posteriormente, determinar la sucesión de acciones sencillas (susceptibles de ser ejecutadas por un computador) en que se descompone dicho método.
No todos los métodos de solución de un problema pueden ser puestos es práctica en un computador.
Para que un procedimiento pueda ser implantado en un computador debe ser:
Preciso: estar compuesto de pasos bien definidos (no ambiguos) y ordenados.
Definido: si se sigue dos veces, se obtiene el mismo resultado cada vez.
Finito: tener un número finito de pasos.
Un procedimiento o método para resolver un problema que cumpla los requisitos anteriores se dice que es un algoritmo. Se puede dar por tanto la siguiente definición:
Un algoritmo es un método para resolver un problema mediante una secuencia de pasos bien definidos, ordenados y finitos.
Para que se pueda ejecutar el algoritmo es preciso, además, que se disponga de las “herramientas” adecuadas para llevar a cabo cada uno de los pasos. Si no es así, estos deberán, a su vez, ser descompuestos en una secuencia (algoritmo) de pasos más simples que sí se puedan llevar a cabo.
Un programa de computador es una sucesión de órdenes que describen un algoritmo, escritas de forma que puedan ser entendidas por el computador.
En un algoritmo (y por tanto en un programa) se distinguen las siguientes acciones:
Entrada: es la información de partida que necesita el algoritmo para arrancar.
Proceso: es el conjunto de todas las operaciones a realizar.
Salida: son los resultados obtenidos.
Representación de algoritmos
Las dos herramientas más utilizadas comúnmente para describir algoritmos son:
Diagramas de flujo: son representaciones gráficas de secuencias de pasos a realizar. Cada operación se representa mediante un símbolo normalizado el Instituto Norteamericano de Normalización (ANSI - American National Standars Institute). Las líneas de flujo indican el orden de ejecución. Algunos de los símbolos principales se muestran en la Figura 5.1, como son: Inicio/Fin del algoritmo, Lectura/Escritura de datos que el programa necesita o genera (por ejemplo,lectura de datos que se teclean o escritura de datos en un fichero); Proceso conjunto de instrucciones secuenciales; Decisión es una bifurcación en el flujo del algoritmo en base a que se verifique o no cierta condición
Los diagramas de flujo suelen ser usados sólo para representar algoritmos pequeíos, ya que abarcan mucho espacio.
Pseudocódigos: describen un algoritmo de forma similar a un lenguaje de programación pero sin su rigidez, de forma más parecida al lenguaje natural. Presentan la ventaja de ser más compactos que los diagramas de flujo, más fáciles de escribir para las instrucciones complejas y más fáciles de transferir a un lenguaje de programación. El pseudocódigo no está regido por ningún estándar. En estos apuntes usaremos las palabras LEER/IMPRIMIR para representar las acciones de lectura de datos (el programa recibe datos desde algún sitio) y salida de datos (el programa escribe información en algún medio)
El Algoritmo y la Figura a continuación muestran respectivamente el pseudocódigo y el diagrama de flujo del algoritmo para calcular la altura de una persona en pulgadas y pies a partir de la altura en centímetros introducida por el teclado.
Algoritmo: Calcular una altura en pulgadas (1 pulgada=2.54 cm) y pies (1 pie=12 pulgadas), a partir de la altura en centímetros, que se introduce por el teclado.
Inicio
1- IMPRIMIR ’Introduce la altura en centimetros: ’
2- LEER: altura
3- CALCULAR pulgadas=altura/2.54
4- CALCULAR pies=pulgadas/12
5- IMPRIMIR ’La altura en pulgadas es: ’, pulgadas
6- IMPRIMIR ’La altura en pies es : ’, pies
Fin
Estructura secuencial
Es aquella en la que una acción (instrucción) sigue a la otra en el orden en el que están escritas.
Estructuras de control: condicionales y bucles
Son parte fundamental de cualquier lenguaje. Sin ellas, las instrucciones de un programa sólo podrían ejecutarse en el orden en que están escritas (orden secuencial). Las estructuras de control permiten modificar este orden.
Hay dos categorías de estructuras de control:
Condicionales o bifurcaciones: permiten que se ejecuten conjuntos distintos de instrucciones, en función de que se verifique o no determinada condición.
Bucles o repeticiones: permiten que se ejecute repetidamente un conjunto de instrucciones, bien un número pre-determinado de veces, o bien hasta que se verifique una determinada condición.
En términos de un lenguaje de programación, que se verifique o no una condición se traduce en que una (adecuada) expresión lógica tome el valor VERDADERO (TRUE) o tome el valor FALSO (FALSE).
En los casos más sencillos y habituales la condición suele ser una comparación entre dos datos, como por ejemplo: si a < b hacer una cosa y en caso contrario hacer otra distinta.
Estructura condicional simple: IF
Este es el tipo más sencillo de estructura condicional. Sirve para implementar acciones condicionales del tipo siguiente:
Si se verifica una determinada condición, ejecutar una serie de instrucciones y luego seguir adelante.
Si la condición NO se cumple, NO se ejecutan dichas instrucciones y se sigue adelante.
Obsérvese que, en ambos casos (que se verifique o no la condición), los “caminos” bifurcados se unen posteriormente en un punto, es decir, el flujo del programa recupera su carácter secuencial, y se continúa ejecutando por la instrucción siguiente a la estructura IF.
Algoritmo Cálculo del valor de la función f(x) = 0 si x ≤ 0, f(x) = x
2 si x > 0.
Inicio
1- LEER x
2- HACER f=0
3- Si x>0
HACER f=x2
Fin Si
4- IMPRIMIR ’El valor de la funcion es: ’, f
Fin
Estructura condicional doble: IF - ELSE
Este tipo de estructura permite implementar condicionales en los que hay dos acciones alternativas:
Si se verifica una determinada condición, ejecutar un serie de instrucciones (bloque 1).
Si no, esto es, si la condición NO se verifica, ejecutar otra serie de instrucciones (bloque 2).
En otras palabras, en este tipo de estructuras hay una alternativa: se hace una cosa o se hace la otra. En ambos casos, se sigue por la instrucción siguiente a la estrucutra IF - ELSE.
Estructura condicional múltiple IF - ELSEIF - ELSE :
En su forma más general, la estructura IF - ELSEIF - ELSE: permite implementar condicionales más complicados, en los que se “encadenan” condiciones en la forma siguiente:
Si se verifica la condición 1, ejecutar las instrucciones del bloque 1.
Si no se verifica la condición 1, pero SI se verifica la condición 2 , ejecutar las instrucciones del bloque 2 .
Si no, esto es, si no se ha verificado ninguna de las condiciones anteriores, ejecutar las instrucciones del bloque 3.
En cualquiera de los casos, el flujo del programa continuá por la instrucción siguiente a la estructura IF - ELSEIF - ELSE.
Algoritmo 5.5 Determinación del signo de un número: positivo, negativo o nulo.
Inicio
1- LEER X
2- Si X>0
IMPRIMIR ’El número tiene signo positivo’
Si no, si X<0
IMPRIMIR ’El número tiene signo negativo’
Si no
IMPRIMIR ’El número es nulo’
Fin
En la estructura IF - ELSEIF - ELSE se puede multiplicar la cláusula ELSEIF, obteniéndose así una “cascada” de condiciones, como se muestra en el organigrama, cuyo funcionamiento es claro. En este tipo de estructura condicional, la cláusula ELSE junto con su bloque de instrucciones pueden no estar presente.
Las distintas estructuras condicionales descritas pueden ser anidadas, es decir, puede incluirse una estructura IF (de cualquier tipo), como parte de las instrucciones que forman el bloque de uno de los casos de otro IF. Como es lógico, no puede haber solapamiento. Cada estructura IF debe tener su propio fin (end).
Estructura de elección entre varios casos: SWITCH
Este tipo de estructura permite decidir entre varios caminos posibles, en función del valor que tome una determinada instrucción.
En cada uno de los casos, el valor correspondiente puede ser o bien un sólo valor, o bien un conjunto de valores, en cuyo caso se indican entre llaves. La cláusula OTHERWISE y su correspondiente conjunto de instrucciones puede no estar presente.
El funcionamiento es el siguiente:
Al comienzo se evala la expresión.
Si expresión toma el valor (ó valores) especificados junto a la primera cláusula CASE, se ejecuta el conjunto de instrucciones de este caso y despúes se abandona la estructura SWITCH, continuando por la instrucción siguiente al END.
Se repite el procedimiento anterior, de forma ordenada, para cada una de las cláusulas CASE que siguen.
Si la cláusula OTHERWISE está presente y la expresión no ha tomado ninguno de los valores anteriormente especificados, se ejecuta el conjunto de instrucciones correspondiente.
Obsérvese que se ejecuta, como máximo el conjunto de instrucciones de uno de los casos, es decir, una vez que se ha verificado un caso y se ha ejecutado su conjunto de instrucciones, no se testea el resto de casos, ya que se abandona la estructura. Obviamente, si la cláusula OTHERWISE no está presente, puede ocurrir que no se dé ninguno de los casos.
Estructura de repetición indexada: FOR
Este tipo de estructura permite implementar la repetición de un cierto conjunto de instrucciones un número pre-determinado de veces.
Para ello se utiliza una variable de control del bucle, llamada también índice, que va recorriendo un conjunto pre-fijado de valores en un orden determinado. Para cada valor del índice en dicho conjunto, se ejecuta una vez el mismo conjunto de instrucciones.
Nota del diagrama
a) El valor de la variable de control indice puede ser utilizado o no dentro del conjunto de instrucciones que forman parte del cuerpo del FOR, pero no debe ser modificado.
b) El conjunto de valores que debe recorrer el indice puede ser vacío (N=0). En ese caso, el bloque de instrucciones no se ejecuta ninguna vez.
c) Las estructuras FOR e IF pueden “anidarse”, es decir, incluir una dentro de la otra, con la restricción (de sentido común) de que la interior tiene que estar completamente contenida en uno de los bloques de instrucciones de la otra.
Estructura repetitiva condicional: WHILE
Permite implementar la repetición de un mismo conjunto de instrucciones mientras que se verifique una determinada condición: el número de veces que se repetirá el ciclo no está definido a priori.
Su funcionamiento es evidente, a la vista del diagrama: 1. Al comienzo de cada iteración se evalúa la expresión-lógica. 2. Si el resultado es VERDADERO, se ejecuta el conjunto de instrucciones y se vuelve a iterar, es decir, se repite el paso 1. 3. Si el resultado es FALSO, se detiene la ejecución del ciclo WHILE y el programa se sigue ejecutando por la instrucción siguiente al END.
Ruptura de ciclos de repetición: BREAK y CONTINUE
En ocasiones es necesario interrumpir la ejecución de un ciclo de repetición en algún punto interno del bloque de instrucciones que se repiten.
Lógicamente, ello dependerá de que se verifique o no alguna condición.
La interrupción puede hacerse de dos formas: 1. Abandonando el ciclo de repetición definitivamente
2. Abandonando la iteración en curso, pero comenzando la siguiente.
Las instrucciones para poner esto en práctica tienen nombres diversos en los distintos lenguajes de programación