Source: http://docplayer.es/2847582-Capitulo-2-metodologia-de-la-programacion-y-desarrollo-de-software.html
Timestamp: 2017-11-24 15:32:11+00:00

Document:
CAPÍTULO 2 METODOLOGÍA DE LA PROGRAMACIÓN Y DESARROLLO DE SOFTWARE - PDF
Download "CAPÍTULO 2 METODOLOGÍA DE LA PROGRAMACIÓN Y DESARROLLO DE SOFTWARE"
Trinidad Naranjo Toledo
1 cap.2 28/6/05 12:17 Página 40 CAPÍTULO 2 METODOLOGÍA DE LA PROGRAMACIÓN Y DESARROLLO DE SOFTWARE C O N T E N I D O 2.1. Fases en la resolución de problemas 2.2. Programación modular 2.3. Programación estructurada 2.4. Concepto y características de algoritmos 2.5. Escritura de algoritmos 2.6. Representación gráfica de los algoritmos 2.7. El ciclo de vida del software 2.8. Métodos formales de verificaciónde programas 2.9. Resumen Ejercicios Ejercicios resueltos 40
2 cap.2 28/6/05 12:17 Página 41 I N T R O D U C C I Ó N Este capítulo le introduce a la metodología a seguir para la resolución de problemas con computadoras y con un lenguaje de programación como C. La resolución de un problema con una computadora se hace escribiendo un programa, que exige al menos los siguientes pasos: Uno de los objetivos fundamentales de este libro es el aprendizaje y diseño de los algoritmos. Este capítulo introduce al lector en el concepto de algoritmo y de programa, así como las herramientas que permiten «dialogar» al usuario con la máquina: los lenguajes de programación. 1. Definición o análisis del problema. 2. Diseño del algoritmo. 3. Transformación del algoritmo en un programa. 4. Ejecución y validación del programa. C O N C E P T O S C L A V E Algoritmo Ciclo de vida Diseño descendente Diagrama Nassi Schneiderman Diagramas de flujo Diseño Dominio del problema Factores de calidad Invariantes Métodos formales Postcondiciones Precondiciones Programación modular Programación estructurada Pruebas Pseudocódigo Verificación 41
3 cap.2 28/6/05 12:17 Página 42 42mmProgramación en C: Metodología, algoritmos y estructura de datos 2.1. FASES EN LA RESOLUCIÓN DE PROBLEMAS El proceso de resolución de un problema con una computadora conduce a la escritura de un programa y a su ejecución en la misma. Aunque el proceso de diseñar programas es esencialmente un proceso creativo, se puede considerar una serie de fases o pasos comunes, que generalmente deben seguir todos los programadores. Las fases de resolución de un problema con computadora son: Análisis del problema. Diseño del algoritmo. Codificación. Compilación y ejecución. Verificación. Depuración. Mantenimiento. Documentación. Constituyen el ciclo de vida del software y sus características más sobresalientes son: Análisis. El problema se analiza teniendo presente la especificación de los requisitos dados por el cliente de la empresa o por la persona que encarga el programa. Diseño. Una vez analizado el problema, se diseña una solución que conducirá a un algoritmo que resuelva el problema. Codificación (implementación). La solución se escribe en la sintaxis del lenguaje de alto nivel (por ejemplo, C) y se obtiene un programa fuente que se compila a continuación. Ejecución, verificación y depuración. El programa se ejecuta, se comprueba rigurosamente y se eliminan todos los errores (denominados «bugs», en inglés) que puedan aparecer. Mantenimiento. El programa se actualiza y modifica, cada vez que sea necesario, de modo que se cumplan todas las necesidades de cambio de sus usuarios. Documentación. Escritura de las diferentes fases del ciclo de vida del software, esencialmente el análisis, diseño y codificación, unidos a manuales de usuario y de referencia, así como normas para el mantenimiento. Las dos primeras fases conducen a un diseño detallado escrito en forma de algoritmo. Durante la tercera etapa (codificación)seimplementa 1 el algoritmo en un código escrito en un lenguaje de programación, reflejando las ideas desarrolladas en las fases de análisis y diseño. Las fases de compilación y ejecución traducen y ejecutan el programa. En las fases de verificación y depuración el programador busca errores de las etapas anteriores y los elimina. Comprobará que mientras más tiempo se gaste en la fase de análisis y diseño, menos se gastará en la depuración del programa. Por último, se debe realizar la documentación del programa. Antes de conocer las tareas a realizar en cada fase, vamos a considerar el concepto y significado de la palabra algoritmo. La palabra algoritmo se deriva de la traducción al latín de la palabra Alkhô-warîzmi 2, nombre de un matemático y astrónomo árabe que escribió un tratado sobre manipulación de números y ecuaciones en el siglo IX. Unalgoritmo es un método para resolver un problema mediante una serie de pasos precisos, definidos y finitos. 1 En la última edición (21ª) del DRAE (Diccionario de la Real Academia Española) se ha aceptado el término implementar: (Informática) «Poner en funcionamiento, aplicar métodos, medidas, etc. para llevar algo a cabo». 2 Escribió un tratado matemático famoso sobre manipulación de números y ecuaciones titulado Kitab al-jabr w almugabala. La palabra álgebra se derivó, por su semejanza sonora, de al-jabr.
4 cap.2 28/6/05 12:17 Página 43 Metodología de la programación y desarrollo de softwaremm43 Características de un algoritmo preciso (indica el orden de realización en cada paso), definido (si se sigue dos veces, obtiene el mismo resultado cada vez), finito (tiene fin; un número determinado de pasos). Un algoritmo debe producir un resultado en un tiempo finito. Los métodos que utilizan algoritmos se denominan métodos algorítmicos, en oposición a los métodos que implican algún juicio o interpretación que se denominan métodos heurísticos. Los métodos algorítmicos se pueden implementar en computadoras; sin embargo, los procesos heurísticos no han sido convertidos fácilmente en las computadoras. En los últimos años las técnicas de inteligencia artificial han hecho posible la implementación del proceso heurístico en computadoras. Ejemplos de algoritmos son: instrucciones para montar en una bicicleta, hacer una receta de cocina, obtener el máximo común divisor de dos números, etc. Los algoritmos se pueden expresar por fórmulas, diagramas de flujo o N-S y pseudocódigos. Esta última representación es la más utilizada para su uso con lenguajes estructurados como C Análisis del problema La primera fase de la resolución de un problema con computadora es el análisis del problema. Esta fase requiere una clara definición, donde se contemple exactamente lo que debe hacer el programa y el resultado o solución deseada. Dado que se busca una solución por computadora, se precisan especificaciones detalladas de entrada y salida. La Figura 2.1 muestra los requisitos que se deben definir en el análisis. Resolución de un problema Análisis del problema Diseño del algoritmo Resolución del problema con computadora Figura 2.1. Análisis del problema Para poder identificar y definir bien un problema es conveniente responder a las siguientes preguntas: Qué entradas se requieren? (tipo de datos con los cuales se trabaja y cantidad). Cuál es la salida deseada? (tipo de datos de los resultados y cantidad). Qué método produce la salida deseada? Requisitos o requerimientos adicionales y restricciones a la solución. Problema 2.1. Se desea obtener una tabla con las depreciaciones acumuladas y los valores reales de cada año, de un automóvil comprado en pesetas en el año 1996, durante los seis años siguientes suponiendo
5 cap.2 28/6/05 12:17 Página 44 44mmProgramación en C: Metodología, algoritmos y estructura de datos un valor de recuperación o rescate de Realizar el análisis del problema, conociendo la fórmula de la depreciación anual constante D para cada año de vida útil. coste - valor de recuperación D = vida útil D = = = Entrada Salida Proceso { { { coste original vida útil valor de recuperación depreciación anual por año depreciación acumulada en cada año valor del automóvil en cada año depreciación acumulada cálculo de la depreciación acumulada cada año cálculo del valor del automóvil en cada año La tabla siguiente muestra la salida solicitada Año Depreciación Depreciación Valor anual acumulada 1 (1996) (1997) (1998) (1999) (2000) (2001) Diseño del algoritmo En la etapa de análisis del proceso de programación se determina qué hace el programa. En la etapa de diseño se determina cómo hace el programa la tarea solicitada. Los métodos más eficaces para el proceso de diseño se basan en el conocido divide y vencerás. Es decir, la resolución de un problema complejo se realiza dividiendo el problema en subproblemas y a continuación dividiendo estos subproblemas en otros de nivel más bajo, hasta que pueda ser implementada una solución en la computadora. Este método se conoce técnicamente como diseño descendente (top-down) o modular. El proceso de romper el problema en cada etapa y expresar cada paso en forma más detallada se denomina refinamiento sucesivo. Cada subprograma es resuelto mediante un módulo (subprograma) que tiene un sólo punto de entrada y un sólo punto de salida. Cualquier programa bien diseñado consta de un programa principal (el módulo de nivel más alto) que llama a subprogramas (módulos de nivel más bajo) que a su vez pueden llamar a otros subprogramas. Los programas estructurados de esta forma se dice que tienen un diseño modular y el método de romper el programa en módulos más pequeños se llama programación modular. Los módulos pueden ser planeados, codificados, comprobados y depurados independientemente (incluso por diferentes programadores) y a continuación combinarlos entre sí. El proceso implica la ejecución de los siguientes pasos hasta que el programa se termina:
6 cap.2 28/6/05 12:17 Página 45 Metodología de la programación y desarrollo de softwaremm45 1. Programar un módulo. 2. Comprobar el módulo. 3. Si es necesario, depurar el módulo. 4. Combinar el módulo con los módulos anteriores. El proceso que convierte los resultados del análisis del problema en un diseño modular con refinamientos sucesivos que permitan una posterior traducción a un lenguaje se denomina diseño del algoritmo. El diseño del algoritmo es independiente del lenguaje de programación en el que se vaya a codificar posteriormente Herramientas de programación Las dos herramientas más utilizadas comúnmente para diseñar algoritmos son: diagramas de flujo y pseudocódigos. Un diagrama de flujo (flowchart) es una representación gráfica de un algoritmo. Los símbolos utilizados han sido normalizados por el Instituto Norteamericano de Normalización (ANSI), y los más frecuentemente empleados se muestran en la Figura 2.2., junto con una plantilla utilizada para el dibujo de los diagramas de flujo (Figura 2.3.). En la Figura 2.4. se representa el diagrama de flujo que resuelve el Problema 2.1. Terminal Subprograma Entrada/ salida Decisión No Proceso Conectores Sí Figura 2.2. Símbolos más utilizados en los diagramas de flujo. Figura 2.3. Plantilla para dibujo de diagramas de flujo.
7 cap.2 28/6/05 12:17 Página 46 46mmProgramación en C: Metodología, algoritmos y estructura de datos El pseudocódigo es una herramienta de programación en la que las instrucciones se escriben en palabras similares al inglés o español, que facilitan tanto la escritura como la lectura de programas. En esencia, el pseudocódigo se puede definir como un lenguaje de especificaciones de algoritmos. Aunque no existen reglas para escritura del pseudocódigo en español, se ha recogido una notación estándar que se utilizará en el libro y que ya es muy empleada en los libros de programación en español 3 3. Las palabras reservadas básicas se representarán en letras negritas minúsculas. Estas palabras son traducción libre de palabras reservadas de lenguajes como C, Pascal, etc. Más adelante se indicarán los pseudocódigos fundamentales a utilizar en esta obra. El pseudocódigo que resuelve el Problema 2.1 es: Previsiones de depreciacion Introducir coste vida util valor final de rescate (recuperacion) imprimir cabeceras Establecer el valor inicial del Año Calcular depreciacion mientras valor año =< vida util hacer calcular depreciacion acumulada calcular valor actual imprimir una linea en la tabla incrementar el valor del año fin de mientras Ejemplo 2.1. Calcular la paga neta de un trabajador conociendo el número de horas trabajadas, la tarifa horaria y la tasa de impuestos. Algoritmo 1. Leer Horas, Tarifa, tasa 2. Calcular PagaBruta = Horas * Tarifa 3. Calcular Impuestos = PagaBruta * Tasa 4. Calcular PagaNeta = PagaBruta - Impuestos 5. Visualizar PagaBruta, Impuestos, PagaNeta 3 Para mayor ampliación sobre el pseudocódigo, puede consultar, entre otras, algunas de estas obras: Fundamentos de programación, Luis Joyanes, 2.ª edición, 1997; Metodología de la programación, Luis Joyanes, 1986; Problemas de Metodología de la programación, Luis Joyanes, 1991 (todas ellas publicadas en McGraw-Hill, Madrid), así como Introducción a la programación, de Clavel y Biondi. Barcelona: Masson, 1987, o bien Introducción a la programación y a las estructuras de datos, de Braunstein y Groia. Buenos Aires: Editorial Eudeba, Para una formación práctica puede consultar: Fundamentos de programación: Libro de problemas de Luis Joyanes, Luis Rodríguez y Matilde Fernández en McGraw-Hill (Madrid, 1998).
8 cap.2 28/6/05 12:17 Página 47 Metodología de la programación y desarrollo de softwaremm47 Inicio Leer Coste, Vida util, ValorRescate Leer Año Valor actual Coste Depreciación (Coste-ValorRescate)/ VidaUtil Acumulada 0 Año < Vida_Util No Sí Acumulada Acumulada + Depreciación Fin Valor actual Valor actual + Depreciación Año Año + 1 Figura 2.4. Diagrama de flujo (Ejemplo 2.1). Ejemplo 2.2. Calcular el valor de la suma Algoritmo Se utiliza una variable Contador como un contador que genere los sucesivos números enteros, y Suma para almacenar las sumas parciales 1, 1+2, Establecer Contador a 1 2. Establecer Suma a 0 3. mientras Contador < = 100 hacer Sumar Contador a Suma Incrementar Contador en 1 fin_mientras 4. Visualizar Suma
9 cap.2 28/6/05 12:17 Página 48 48mmProgramación en C: Metodología, algoritmos y estructura de datos Codificación de un programa Codificación es la escritura en un lenguaje de programación de la representación del algoritmo desarrollada en las etapas precedentes. Dado que el diseño de un algoritmo es independiente del lenguaje de programación utilizado para su implementación, el código puede ser escrito con igual facilidad en un lenguaje o en otro. Para realizar la conversión del algoritmo en programa se deben sustituir las palabras reservadas en español por sus homónimos en inglés, y las operaciones/instrucciones indicadas en lenguaje natural expresarlas en el lenguaje de programación correspondiente. /* Este programa obtiene una tabla de depreciaciones acumuladas y valores reales de cada año de un determinado producto */ #include <stdio.h> void main() { double Coste, Depreciacion, Valor_Recuperacion, Valor_Actual, Acumulado, Valor_Anual; int Anio, Vida_Util; puts("introduzca coste, valor recuperación y vida útil"); scanf("%lf %lf %d",&coste,&valor_recuperacion,&vida_util); puts("introduzca año actual"); scanf("%d",&anio); Valor_Actual = Coste; Depreciacion = (Coste-Valor_Recuperacion)/Vida_Util; Acumulado = 0; puts("año Depreciación Dep. Acumulada"); while (Anio < Vida_Util) { Acumulado = Acumulado + Depreciacion; Valor_Actual = Valor_Actual Depreciacion; printf("año: %d, Depreciacion:%.2lf, %.2lf Acumulada", Anio,Depreciacion,Acumulado); Anio = Anio + 1; } } Documentación interna Como se verá más tarde, la documentación de un programa se clasifica en interna y externa. La documentación interna es la que se incluye dentro del código del programa fuente mediante comentarios que ayudan a la comprensión del código. Todas las líneas de programas que comiencen con un símbolo / * son comentarios. El programa no los necesita y la computadora los ignora. Estas líneas de comentarios sólo sirven para hacer los programas más fáciles de comprender. El objetivo del programador debe ser escribir códigos sencillos y limpios. Debido a que las máquinas actuales soportan grandes memorias (512 Mb o Mb de memoria central mínima en computadoras personales) no es necesario recurrir a técnicas de ahorro de memoria, por lo que es recomendable que se incluya el mayor número de comentarios posibles, pero eso sí, que sean significativos.
10 cap.2 28/6/05 12:17 Página 49 Metodología de la programación y desarrollo de softwaremm Compilación y ejecución de un programa Una vez que el algoritmo se ha convertido en un programa fuente, es preciso introducirlo en memoria mediante el teclado y almacenarlo posteriormente en un disco. Esta operación se realiza con un programa editor. Posteriormente el programa fuente se convierte en un archivo de programa que se guarda (graba) en disco. El programa fuente debe ser traducido a lenguaje máquina, este proceso se realiza con el compilador y el sistema operativo que se encarga prácticamente de la compilación. Si tras la compilación se presentan errores (errores de compilación) en el programa fuente, es preciso volver a editar el programa, corregir los errores y compilar de nuevo. Este proceso se repite hasta que no se producen errores, obteniéndose el programa objeto que todavía no es ejecutable directamente. Suponiendo que no existen errores en el programa fuente, se debe instruir al sistema operativo para que realice la fase de montaje o enlace (link), carga, del programa objeto con las bibliotecas del programa UCP EIDCIDE Memoria externa Teclado Editor de textos Programa editor UCP a) Memoria externa Compilador Programa editor Programa objeto UCP b) Memoria externa Enlace del programa Programa objeto Programa de carga c) Figura 2.5. Fases de la compilación/ejecución de un programa: a) edición; b) compilación; c) montaje o enlace.
11 cap.2 28/6/05 12:17 Página 50 50mmProgramación en C: Metodología, algoritmos y estructura de datos del compilador. El proceso de montaje produce un programa ejecutable. La Figura 2.5 describe el proceso completo de compilación/ejecución de un programa. Cuando el programa ejecutable se ha creado, se puede ya ejecutar (correr o rodar) desde el sistema operativo con sólo teclear su nombre (en el caso de DOS). Suponiendo que no existen errores durante la ejecución (llamados errores en tiempo de ejecución), se obtendrá la salida de resultados del programa. Las instrucciones u órdenes para compilar y ejecutar un programa en C puede variar según el tipo de compilador. Así el proceso de Visual C++ es diferente del de C bajo UNIX o bajo Linux Verificación y depuración de un programa La verificación o compilación de un programa es el proceso de ejecución del programa con una amplia variedad de datos de entrada, llamados datos de test o prueba, que determinarán si el programa tiene errores («bugs»). Para realizar la verificación se debe desarrollar una amplia gama de datos de test: valores normales de entrada, valores extremos de entrada que comprueben los límites del programa y valores de entrada que comprueben aspectos especiales del programa. La depuración es el proceso de encontrar los errores del programa y corregir o eliminar dichos errores. Cuando se ejecuta un programa, se pueden producir tres tipos de errores: 1. Errores de compilación. Se producen normalmente por un uso incorrecto de las reglas del lenguaje de programación y suelen ser errores de sintaxis. Si existe un error de sintaxis, la computadora no puede comprender la instrucción, no se obtendrá el programa objeto y el compilador imprimirá una lista de todos los errores encontrados durante la compilación. 2. Errores de ejecución. Estos errores se producen por instrucciones que la computadora puede comprender pero no ejecutar. Ejemplos típicos son: división por cero y raíces cuadradas de números negativos. En estos casos se detiene la ejecución del programa y se imprime un mensaje de error. 3. Errores lógicos. Se producen en la lógica del programa y la fuente del error suele ser el diseño del algoritmo. Estos errores son los más difíciles de detectar, ya que el programa puede funcionar y no producir errores de compilación ni de ejecución, y sólo puede advertirse el error por la obtención de resultados incorrectos. En este caso se debe volver a la fase de diseño del algoritmo, modificar el algoritmo, cambiar el programa fuente y compilar y ejecutar una vez más Documentación y mantenimiento La documentación de un problema consta de las descripciones de los pasos a dar en el proceso de resolución de dicho problema. La importancia de la documentación debe ser destacada por su decisiva influencia en el producto final. Programas pobremente documentados son difíciles de leer, más difíciles de depurar y casi imposibles de mantener y modificar. La documentación de un programa puede ser interna y externa. La documentación interna es la contenida en líneas de comentarios. La documentación externa incluye análisis, diagramas de flujo y/o pseudocódigos, manuales de usuario con instrucciones para ejecutar el programa y para interpretar los resultados. La documentación es vital cuando se desea corregir posibles errores futuros o bien cambiar el programa. Tales cambios se denominan mantenimiento del programa. Después de cada cambio la documentación debe ser actualizada para facilitar cambios posteriores. Es práctica frecuente numerar las sucesivas versiones de los programas 1.0, 1.1, 2.0, 2.1, etc. (Si los cambios introducidos son importantes, se varía el primer dígito [1.0, 2.0,...], en caso de pequeños cambios sólo se varía el segundo dígito [2.0, 2.1 ].)
12 cap.2 28/6/05 12:17 Página 51 Metodología de la programación y desarrollo de softwaremm PROGRAMACIÓN MODULAR La programación modular es uno de los métodos de diseño más flexible y potente para mejorar la productividad de un programa. En programación modular el programa se divide en módulos (partes independientes), cada uno de las cuales ejecuta una única actividad o tarea y se codifican independientemente de otros módulos. Cada uno de estos módulos se analiza, codifica y pone a punto por separado. Cada programa contiene un módulo denominado programa principal que controla todo lo que sucede; se transfiere el control a submódulos (posteriormente se denominarán subprogramas), de modo que ellos puedan ejecutar sus funciones; sin embargo, cada submódulo devuelve el control al módulo principal cuando se haya completado su tarea. Si la tarea asignada a cada submódulo es demasiado compleja, éste deberá romperse en otros módulos más pequeños. El proceso sucesivo de subdivisión de módulos continúa hasta que cada módulo tenga solamente una tarea específica que ejecutar. Esta tarea puede ser entrada, salida, manipulación de datos, control de otros módulos o alguna combinación de éstos. Un módulo puede transferir temporalmente (bifurcar) el control a otro módulo; sin embargo, cada módulo debe eventualmente devolver el control al módulo del cual se recibe originalmente el control. Los módulos son independientes en el sentido en que ningún módulo puede tener acceso directo a cualquier otro módulo excepto el módulo al que llama y sus propios submódulos. Sin embargo, los resultados producidos por un módulo pueden ser utilizados por cualquier otro módulo cuando se transfiera a ellos el control. Raíz Módulo 1 Módulo 2 Módulo 3 Módulo 4 Módulo 11 Módulo 12 Módulo 31 Módulo 41 Módulo 42 Módulo 21 Módulo 22 Módulo 221 Módulo 222 Figura 2.6. Programación modular. Dado que los módulos son independientes, diferentes programadores pueden trabajar simultáneamente en diferentes partes del mismo programa. Esto reducirá el tiempo del diseño del algoritmo y posterior codificación del programa. Además, un módulo se puede modificar radicalmente sin afectar a otros módulos, incluso sin alterar su función principal. La descomposición de un programa en módulos independientes más simples se conoce también como el método de «divide y vencerás» (divide and conquer). Se diseña cada módulo con independencia de los demás, y siguiendo un método ascendente o descendente se llegará hasta la descomposición final del problema en módulos en forma jerárquica.
13 cap.2 28/6/05 12:17 Página 52 52mmProgramación en C: Metodología, algoritmos y estructura de datos 2.3. PROGRAMACIÓN ESTRUCTURADA Los términos programación modular, programación descendente y programación estructurada se introdujeron en la segunda mitad de la década de los sesenta y a menudo se utilizan como sinónimos aunque no significan lo mismo. La programación modular y descendente ya se ha examinado anteriormente. La programación estructurada significa escribir un programa de acuerdo a las siguientes reglas: El programa tiene un diseño modular. Los módulos son diseñados de modo descendente. Cada módulo se codifica utilizando las tres estructuras de control básicas: secuencia, selección y repetición. Si está familiarizado con lenguajes como BASIC, Pascal, FORTRAN o C, la programación estructurada significa también programación sin /GOTO/ (C no requiere el uso de la sentencia GOTO). El término programación estructurada se refiere a un conjunto de técnicas que han ido evolucionando desde los primeros trabajos de Edgar Dijkstra. Estas técnicas aumentan considerablemente la productividad del programa reduciendo en elevado grado el tiempo requerido para escribir, verificar, depurar y mantener los programas. La programación estructurada utiliza un número limitado de estructuras de control que minimizan la complejidad de los programas y, por consiguiente, reducen los errores; hace los programas más fáciles de escribir, verificar, leer y mantener. Los programas deben estar dotados de una estructura. La programación estructurada es el conjunto de técnicas que incorporan: recursos abstractos, diseño descendente (top-down), estructuras básicas Recursos abstractos La programación estructurada se auxilia de los recursos abstractos en lugar de los recursos concretos de que dispone un determinado lenguaje de programación. Descomponer un programa en términos de recursos abstractos según Dijkstra consiste en descomponer una determinada acción compleja en términos de un número de acciones más simples capaces de ejecutarlas o que constituyan instrucciones de computadoras disponibles Diseño descendente (top-down) El diseño descendente (top-down) es el proceso mediante el cual un problema se descompone en una serie de niveles o pasos sucesivos de refinamiento (stepwise). La metodología descendente consiste en efectuar una relación entre las sucesivas etapas de estructuración de modo que se relacionasen unas con otras mediante entradas y salidas de información. Es decir, se descompone el problema en etapas o estructuras jerárquicas, de forma que se puede considerar cada estructura desde dos puntos de vista: qué hace? y cómo lo hace? Si se considera un nivel n de refinamiento, las estructuras se consideran de la siguiente manera:
14 cap.2 28/6/05 12:17 Página 53 Metodología de la programación y desarrollo de softwaremm53 Nivel n: desde el exterior «qué hace?» Nivel n + 1: Vista desde el interior «cómo lo hace?» El diseño descendente se puede ver en la Figura 2.7. Figura 2.7. Diseño descendente Estructuras de control Las estructuras de control de un lenguaje de programación son métodos de especificar el orden en que las instrucciones de un algoritmo se ejecutarán. El orden de ejecución de las sentencias (lenguaje) o instrucciones determina el flujo de control. Estas estructuras de control son, por consiguiente, fundamentales en los lenguajes de programación y en los diseños de algoritmos, especialmente los pseudocódigos. Las tres estructuras de control básico son: secuencia, selección, repetición. y se estudian en los Capítulos 5 y 6. La programación estructurada hace los programas más fáciles de escribir, verificar, leer y mantener; utiliza un número limitado de estructuras de control que minimizan la complejidad de los problemas.
15 cap.2 28/6/05 12:17 Página 54 54mmProgramación en C: Metodología, algoritmos y estructura de datos Teorema de la programación estructurada: estructuras básicas En mayo de 1966, Böhm y Jacopini demostraron que un programa propio puede ser escrito utilizando solamente tres tipos de estructuras de control. secuenciales, selectivas, repetitivas. Un programa se define como propio si cumple las siguientes características: Posee un solo punto de entrada y uno de salida o fin para control del programa. Existen caminos desde la entrada hasta la salida que se pueden seguir y que pasan por todas las partes del programa. Todas las instrucciones son ejecutables y no existen lazos o bucles infinitos (sin fin). La programación estructurada significa que El programa completo tiene un diseño modular. Los módulos se diseñan con metodología descendente (puede hacerse también ascendente). Cada módulo se codifica utilizando las tres estructuras de control básicas: secuenciales, selectivas y repetitivas (ausencia total de sentencias GOTO). Estructuración y modularidad son conceptos complementarios (se solapan) CONCEPTO Y CARACTERÍSTICAS DE ALGORITMOS El objetivo fundamental de este texto es enseñar a resolver problemas mediante una computadora. El programador de computadora es antes que nada una persona que resuelve problemas, por lo que para llegar a ser un programador eficaz se necesita aprender a resolver problemas de un modo riguroso y sistemático. A lo largo de todo este libro nos referiremos a la metodología necesaria para resolver problemas mediante programas, concepto que se denomina metodología de la programación. El eje central de esta metodología es el concepto, ya tratado, de algoritmo. Un algoritmo es un método para resolver un problema. Aunque la popularización del término ha llegado con el advenimiento de la era informática, algoritmo proviene como se comentó anteriormente de Mohammed al-khowârizmi, matemático persa que vivió durante el siglo IX y alcanzó gran reputación por el enunciado de las reglas paso a paso para sumar, restar, multiplicar y dividir números decimales; la traducción al latín del apellido en la palabra algorismus derivó posteriormente en algoritmo. Euclides, el gran matemático griego (del siglo IV a.c.) que inventó un método para encontrar el máximo común divisor de dos números, se considera con Al-Khowârizmi el otro gran padre de la algoritmia (ciencia que trata de los algoritmos). El profesor Niklaus Wirth inventor de Pascal, Modula-2 y Oberon tituló uno de sus más famosos libros, Algoritmos + Estructuras de datos = Programas, significándonos que sólo se puede llegar a realizar un buen programa con el diseño de un algoritmo y una correcta estructura de datos. Esta ecuación será una de las hipótesis fundamentales consideradas en esta obra. La resolución de un problema exige el diseño de un algoritmo que resuelva el problema propuesto.
16 cap.2 28/6/05 12:17 Página 55 Metodología de la programación y desarrollo de softwaremm55 Problema Diseño del algoritmo Programa de computadora Figura 2.8. Resolución de un problema. Los pasos para la resolución de un problema son: 1. Diseño del algoritmo, que describe la secuencia ordenada de pasos sin ambigüedades que conducen a la solución de un problema dado. (Análisis del problema y desarrollo del algoritmo.) 2. Expresar el algoritmo como un programa en un lenguaje de programación adecuado. (Fase de codificación.) 3. Ejecución y validación del programa por la computadora. Para llegar a la realización de un programa es necesario el diseño previo de un algoritmo, de modo que sin algoritmo no puede existir un programa. Los algoritmos son independientes tanto del lenguaje de programación en que se expresan como de la computadora que los ejecuta. En cada problema el algoritmo se puede expresar en un lenguaje diferente de programación y ejecutarse en una computadora distinta; sin embargo, el algoritmo será siempre el mismo. Así, por ejemplo, en una analogía con la vida diaria, una receta de un plato de cocina se puede expresar en español, inglés o francés, pero cualquiera que sea el lenguaje, los pasos para la elaboración del plato se realizarán sin importar el idioma del cocinero. En la ciencia de la computación y en la programación, los algoritmos son más importantes que los lenguajes de programación o las computadoras. Un lenguaje de programación es tan sólo un medio para expresar un algoritmo y una computadora es sólo un procesador para ejecutarlo. Tanto el lenguaje de programación como la computadora son los medios para obtener un fin: conseguir que el algoritmo se ejecute y se efectúe el proceso correspondiente. Dada la importancia del algoritmo en la ciencia de la computación, un aspecto muy importante será el diseño de algoritmos. A la enseñanza y práctica de esta tarea se dedica gran parte de este libro. El diseño de la mayoría de los algoritmos requiere creatividad y conocimientos profundos de la técnica de la programación. En esencia, la solución de un problema se puede expresar mediante un algoritmo Características de los algoritmos Las características fundamentales que debe cumplir todo algoritmo son: Un algoritmo debe ser preciso e indicar el orden de realización de cada paso. Un algoritmo debe estar definido. Si se sigue un algoritmo dos veces, se debe obtener el mismo resultado cada vez. Un algoritmo debe ser finito. Si se sigue un algoritmo, se debe terminar en algún momento; o sea, debe tener un número finito de pasos. La definición de un algoritmo debe describir tres partes: Entrada, Proceso y Salida. En el algoritmo de receta de cocina citado anteriormente se tendrá: Entrada: ingredientes y utensilios empleados. Proceso: elaboración de la receta en la cocina. Salida: terminación del plato (por ejemplo, cordero).
17 cap.2 28/6/05 12:17 Página 56 56mmProgramación en C: Metodología, algoritmos y estructura de datos Ejemplo 2.3. Un cliente ejecuta un pedido a una fábrica. La fábrica examina en su banco de datos la ficha del cliente, si el cliente es solvente entonces la empresa acepta el pedido; en caso contrario, rechazará el pedido. Redactar el algoritmo correspondiente. Los pasos del algoritmo son: 1. Inicio. 2. Leer el pedido. 3. Examinar la ficha del cliente. 4. Si el cliente es solvente, aceptar pedido; en caso contrario, rechazar pedido. 5. Fin. Ejemplo 2.4. Se desea diseñar un algoritmo para saber si un número es primo o no. Un número es primo si sólo puede dividirse por sí mismo y por la unidad (es decir, no tiene más divisores que él mismo y la unidad). Por ejemplo, 9, 8, 6, 4, 12, 16, 20, etc., no son primos, ya que son divisibles por números distintos a ellos mismos y a la unidad. Así, 9 es divisible por 3, 8 lo es por 2, etc. El algoritmo de resolución del problema pasa por dividir sucesivamente el número por 2, 3, 4..., etc. 1. Inicio. 2. Poner X igual a 2 (X = 2, X variable que representa a los divisores del número que se busca N). 3. Dividir N por X (N/X). 4. Si el resultado de N/X es entero, entonces N no es un número primo y bifurcar al punto 7; en caso contrario, continuar el proceso. 5. Suma 1 a X (X X + 1). 6. Si X es igual a N, entonces N es un número primo; en caso contrario, bifurcar al punto Fin. Por ejemplo, si N es 131, los pasos anteriores serían: 1. Inicio. 2. X = /X. Como el resultado no es entero, se continúa el proceso. 5. X 2 + 1, luego X = Como X no es 131, se continúa el proceso /X resultado no es entero. 5. X 3 + 1, X = Como X no es 131 se continúa el proceso /X..., etc. 7. Fin.
18 cap.2 28/6/05 12:17 Página 57 Metodología de la programación y desarrollo de softwaremm57 Ejemplo 2.5. Realizar la suma de todos los números pares entre 2 y El problema consiste en sumar Utilizaremos las palabras SUMA y NÚMERO (variables, serán denominadas más tarde) para representar las sumas sucesivas (2+4), (2+4+6), ( ), etc. La solución se puede escribir con el siguiente algoritmo: 1. Inicio. 2. Establecer SUMA a Establecer NÚMERO a Sumar NÚMERO a SUMA. El resultado será el nuevo valor de la suma (SUMA). 5. Incrementar NÚMERO en 2 unidades. 6. Si NÚMERO =< bifurcar al paso 4; en caso contrario, escribir el último valor de SUMA y terminar el proceso. 7. Fin Diseño del algoritmo Una computadora no tiene capacidad para solucionar problemas más que cuando se le proporcionan los sucesivos pasos a realizar. Estos pasos sucesivos que indican las instrucciones a ejecutar por la máquina constituyen, como ya conocemos, el algoritmo. La información proporcionada al algoritmo constituye su entrada y la información producida por el algoritmo constituye su salida. Los problemas complejos se pueden resolver más eficazmente con la computadora cuando se rompen en subproblemas que sean más fáciles de solucionar que el original. Este método se suele denominar divide y vencerás (divide and conquer) y consiste en dividir un problema complejo en otros más simples. Así, el problema de encontrar la superficie y la longitud de un círculo se puede dividir en tres problemas más simples o subproblemas (Figura 2.9.). Superficie y longitud de circunferencia Entrada de datos Cálculo de superficie (S) Cálculo de longitud (L) Salida resultados Entrada radio (R) S = PI* R 2 L = 2* PI * R Salida R Salida S Salida L Figura 2.9. Refinamiento de un algoritmo.
19 cap.2 28/6/05 12:17 Página 58 58mmProgramación en C: Metodología, algoritmos y estructura de datos La descomposición del problema original en subproblemas más simples y a continuación la división de estos subproblemas en otros más simples que pueden ser implementados para su solución en la computadora se denomina diseño descendente (top-down design). Normalmente los pasos diseñados en el primer esbozo del algoritmo son incompletos e indicarán sólo unos pocos pasos (un máximo de doce aproximadamente). Tras esta primera descripción, éstos se amplían en una descripción más detallada con más pasos específicos. Este proceso se denomina refinamiento del algoritmo (stepwise refinement). Para problemas complejos se necesitan con frecuencia diferentes niveles de refinamiento antes de que se pueda obtener un algoritmo claro, preciso y completo. El problema de cálculo de la circunferencia y superficie de un círculo se puede descomponer en subproblemas más simples: (1) leer datos de entrada, (2) calcular superficie y longitud de circunferencia y (3) escribir resultados (datos de salida). Subproblema Refinamiento leer radio leer radio calcular superficie superficie = * radio ^ 2 calcular circunferencia circunferencia = 2 * * radio escribir resultados escribir radio, circunferencia, superficie Las ventajas más importantes del diseño descendente son: El problema se comprende más fácilmente al dividirse en partes más simples denominadas módulos. Las modificaciones en los módulos son más fáciles. La comprobación del problema se puede verificar fácilmente. Tras los pasos anteriores (diseño descendente y refinamiento por pasos) es preciso representar el algoritmo mediante una determinada herramienta de programación: diagrama de flujo, pseudocódigo o diagrama N-S. Así pues, el diseño del algoritmo se descompone en las fases recogidas en la Figura Diseño de un algoritmo Diseño descendente (1) Refinamiento por casos (2) Herramientas de programación (3) diagrama de flujo pseudocódigo diagrama N-S Figura Fases del diseño de un algoritmo ESCRITURA DE ALGORITMOS Como ya se ha comentado anteriormente, el sistema para describir («escribir») un algoritmo consiste en realizar una descripción paso a paso con un lenguaje natural del citado algoritmo. Recordemos que un
20 cap.2 28/6/05 12:17 Página 59 Metodología de la programación y desarrollo de softwaremm59 algoritmo es un método o conjunto de reglas para solucionar un problema. En cálculos elementales estas reglas tienen las siguientes propiedades: deben estar seguidas de alguna secuencia definida de pasos hasta que se obtenga un resultado coherente, sólo puede ejecutarse una operación a la vez. El flujo de control usual de un algoritmo es secuencial; consideremos el algoritmo que responde a la pregunta Qué hacer para ver la película Harry Potter? La respuesta es muy sencilla y puede ser descrita en forma de algoritmo general de modo similar a: ir al cine comprar una entrada (billete o ticket) ver la película regresar a casa El algoritmo consta de cuatro acciones básicas, cada una de las cuales debe ser ejecutada antes de realizar la siguiente. En términos de computadora, cada acción se codificará en una o varias sentencias que ejecutan una tarea particular. El algoritmo descrito es muy sencillo; sin embargo, como ya se ha indicado en párrafos anteriores, el algoritmo general se descompondrá en pasos más simples en un procedimiento denominado refinamiento sucesivo, ya que cada acción puede descomponerse a su vez en otras acciones simples. Así, por ejemplo, un primer refinamiento del algoritmo ir al cine se puede describir de la forma siguiente: 1. inicio 2. ver la cartelera de cines en el periódico 3. si no proyectan "Harry Potter" entonces 3.1. decidir otra actividad 3.2. bifurcar al paso 7 si_no 3.3. ir al cine fin_si 4. si hay cola entonces 4.1. ponerse en ella 4.2. mientras haya personas delante hacer avanzar en la cola fin_mientras fin_si 5. si hay localidades entonces 5.1. comprar una entrada 5.2. pasar a la sala 5.3. localizar la(s) butaca(s) 5.4. mientras proyectan la película hacer ver la película fin_mientras 5.5. abandonar el cine si_no 5.6. refunfuñar fin_si 6. volver a casa 7. fin
2.3 DEFINICIÓN DE LENGUAJES ALGORÍTMICOS
2.3 DEFINICIÓN DE LENGUAJES ALGORÍTMICOS Características de los algoritmos Las características fundamentales que debe cumplir todo algoritmo son: Un algoritmo debe ser preciso e indicar el orden de realización

References: resolución 
 resolución 
 resolución 
 RESOLUCIÓN 
 resolución 
 resolución 
 resolución 
 Resolución 
 Resolución 
 resolución 
 resolución 
 resolución 
 Resolución 
 resolución 
 resolución