Fundamentos de programación Programa Desarrollado
Cuatrimestre dos Programa de la asignatura: Fundamentos de Programación Clave: 150910206
ESAD Agosto, 2010
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
1
Fundamentos de programación Programa Desarrollado
Índice I.
Información general de la asignatura
3
a. Ficha de identificación...................................................................................................................................... 3 b. Descripción ........................................................................................................................................................ 3 c. Propósito ............................................................................................................................................................ 4 II.
Competencia(s) a desarrollar
5
Competencia general:........................................................................................................................................... 5 Competencias específicas: .............................................................................................................................. 5 III. Temario
6
IV. Metodología de trabajo
8
V.
10
Evaluación
VI. Materiales de apoyo
11
VII. Desarrollo de contenidos por unidad
12
Unidad 1: Introducción a la computadora y desarrollo de software ........................................................... 12 Unidad 2: Diseño de algoritmos ........................................................................................................................ 29 Unidad 3: Introducción al lenguaje C ............................................................................................................... 47 Unidad 4: Estructuras de control....................................................................................................................... 76 Unidad 5: Estructuras de datos ....................................................................................................................... 116 Unidad 6: Funciones ......................................................................................................................................... 146
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
2
Fundamentos de programación Programa Desarrollado
I. Información general de la asignatura a. Ficha de identificación
Nombre de la Licenciatura o Ingeniería:
Ingeniería en logística y transporte, Ingeniería en telemática
Nombre del curso o asignatura
Fundamentos de Programación
Clave de asignatura:
150910206
Seriación:
Bases de Datos, Análisis Orientado a Objetos, Programación Orientada a Objeto
Cuatrimestre:
Dos
Horas contempladas:
72
b. Descripción La asignatura de Fundamentos de Programación tiene como meta principal que desarrolles las competencias necesarias para construir programas que resuelvan problemas reales. Constituye un pilar primordial para aquellos alumnos que, como tú, están estudiando una carrera relacionada con computación -como Desarrollo de Software y Telemática- pues los conocimientos y habilidades que desarrollen en este curso serán indispensables para la varias de las asignaturas subsecuentes del plan de estudios de ambas ingenierías, tal es el caso de bases de datos, programación orientada a objetos, programación web, estructura de datos, entre otras. El lenguaje de alto nivel que se ha elegido para implementar los programas es C, ya que es uno de los lenguajes, estructurados y modulares, utilizados actualmente; además cuenta con entornos de trabajo de software libre, como el que utilizaremos llamado Dev-C. Para facilitar que desarrolles las competencias establecidas, los contenidos del curso se han dividido de forma estratégica en seis unidades. En la primera se delinea el concepto de computadora y su funcionamiento, para ello se describen los elementos que la integran; posteriormente, se hace una aproximación a los lenguajes de programación y los paradigmas que existen en la actualidad, resaltando la programación modular y estructurada. En la siguiente unidad se expone la metodología de la programación y se introduce el concepto de algoritmo, que es la solución sistemática de problemas, así que también se presentan dos formas de representación: el pseudocódigo y los diagramas de flujo. Asimismo, se ilustran las estructuras secuenciales, selectivas y repetitivas. A continuación, en la unidad tres, se presentan los elementos básicos para construir un programa simple en lenguaje C: datos, contantes, variables y las operaciones básicas de entradas/salidas para describir el uso de los
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
3
Fundamentos de programación Programa Desarrollado
operadores aritméticos, relacionales y lógicos para la manipulación de operaciones y expresiones en C. En la unidad cuatro se distinguen y utilizan las distintas estructuras de control, tanto selectivas (if, ifelse, switch) como repetitivas (while, do-while, for), que ofrece el lenguaje C; se introduce su representación en diagrama de flujo y algoritmo, además de su sintaxis en C. En la unidad cinco se introducen las estructuras de datos: arreglos y registros, se explica qué son, cómo funcionan y para qué sirven, además, se plantean problemas en donde su uso es indispensable para su resolución. Por último, en la unidad seis se reconoce la importancia de la programación modular, construyendo soluciones modulares utilizando funciones en lenguaje C.
c. Propósito El curso tiene como finalidad proporcionarte las bases para que comiences a desarrollar programas estructurados que solucionen problemas simples, a través del desarrollo de algoritmos en pseudocódigo y diagrama de flujo y su codificación en lenguaje C, además se te describe el proceso de compilación de un programa y su ejecución identificando los elementos de la computadora que intervienen en cada paso.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
4
Fundamentos de programación Programa Desarrollado
II. Competencia(s) a desarrollar
Competencia general: Desarrollar programas estructurados y modulares que resuelvan problemas simples, mediante el análisis del problema, el diseño de un algoritmo y su codificación en lenguaje C.
Competencias específicas:
Describir los elementos de la computadora y el ciclo de vida de software mediante el análisis un programa simple, con el fin de identificar los pasos que se realizan para construirlo y determinar qué elementos de la computadora intervienen en su ejecución. Diseñar algoritmos para resolver problemas mediante su representación en un diagrama de flujo y la elaboración del pseudocódigo. Utilizar el lenguaje de programación C para resolver problemas a través de la implementación de algoritmos secuenciales. Utilizar estructuras de control selectivas y repetitivas para resolver problemas simples a través del desarrollo de programas en lenguaje C. Utilizar estructuras de datos para almacenar y manipular los datos de un programa por medio del desarrollo de programas en lenguaje C. Implementar funciones para resolver problemas a través del desarrollo de programas modulares escritos en lenguaje C.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
5
Fundamentos de programación Programa Desarrollado
III. Temario 1. Introducción a la computadora y desarrollo de software 1.1. ¿Qué es una computadora? 1.2. Estructura y funcionamiento de una computadora 1.2.1. Modelo de Von Neumann 1.2.2. Ejecución de programas en la computadora 1.2.3. Almacenamientos de programas y datos 1.3. Lenguajes de programación 1.3.1. Evolución de los lenguajes de programación 1.3.2. Paradigmas de los lenguajes de programación 1.4. Ciclo de vida del software 2. Diseño de algoritmos 2.1. Concepto de algoritmo y características 2.2. Representaciones de algoritmos 2.2.1. Pseudocódigo 2.2.2. Diagrama de flujo 2.3. Estructuras de control 2.3.1. Secuenciales 2.3.2. Selectivas 2.3.3. Repetitivas 3. Introducción al lenguaje C 3.1. Componentes de un programa 3.1.1. Instrucciones 3.1.2. Comentarios 3.1.3. Palabras reservadas 3.1.4. Estructura general de un programa 3.2. Tipos de datos 3.3. Variables y constantes 3.3.1. Identificadores 3.3.2. Declaración e inicialización de variables 3.3.3. Tipos de constantes 3.3.4. Declaración de constantes 3.4. Expresiones matemáticas 3.4.1. Tipos de operadores 3.4.2. Evaluación de expresiones 3.5. Bibliotecas y funciones 3.5.1. Funciones matemáticas 3.5.2. Funciones de entrada y salida 3.6. Codificación de algoritmos
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
6
Fundamentos de programación Programa Desarrollado
4. Estructuras de control 4.1. Estructuras selectivas 4.1.1. Estructura selectivasimple (if) 4.1.2. Estructura selectiva doble (if-else) 4.1.3. Estructura selectiva múltiple (switch-case) 4.2. Estructuras repetitivas 4.2.1. Estructura Mientras (while) 4.2.2. Estructura Desde-mientras (for) 4.2.3. Estructura Hacer-mientras (do-while) 4.3. Estructuras anidadas 5. Estructuras de datos 5.1. Arreglos 5.1.1. Definición y tipos 5.1.2. Declaración e inicialización 5.1.3. Acceso a los elementos de un arreglo 5.1.4. Ciclos y arreglos 5.1.5. Cadenas 5.2. Estructuras 5.2.1. Definición, declaración e inicialización 5.2.2. Acceso a los elementos 6. Funciones 6.1. Diseño descendente 6.2. Definición, declaración e invocación de funciones en C 6.3. Alcance de las variables 6.4. Paso de parámetros 6.4.1. Por valor 6.4.2. Por referencia
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
7
Fundamentos de programación Programa Desarrollado
IV. Metodología de trabajo Para trabajar en esta asignatura, se ha propuesto la metodología del Aprendizaje Basado en Problemas, pues debido a la naturaleza de los contenidos, tendrás que resolver problemas de manera constante para poner en práctica lo aprendido. Como el propósito de este curso es que desarrolles programas de software que resuelvan problemas simples, por cada unidad se ha propuesto uno o más problemas a partir de los cuales sete presentan los contenidos correspondientes, la intención de esto es que primero se te planteen los problemas para que los analices y posteriormente se te presente la solución de los mismos mediante algoritmos o programas; lo que se busca es que alcances las competencias específicas de cada unidad a través de, primero la observación y el análisis de los problemas ejemplo que te ayudarán a identificar patrones comunes, y posteriormente la resolución de problemas un poco más complejos a través del desarrollo de estrategias de solución similares. Ahora bien, para que puedas resolver un problema mediante un programa de computadora, primero tienes que tener claro el funcionamiento principal de la misma, tanto para almacenar la información como para llevar a cabo el conjunto de instrucciones que integran la solución de un problema, es decir, el programa. Por tal motivo, en la primera unidad se expone la arquitectura tradicional de las computadoras conocida como el Modelo de Von Neumann a través de la cual se te explica cómo se almacenan los programas y los datos de un problema en una computadora y qué elementos intervienen en la ejecución de las instrucciones. Lo anterior se expone utilizando un programa que se encarga de calcular el área de un rectángulo, de esta manera podrás aprender los contenidos mediante un ejemplo simple. Posteriormente, se describen los pasos que llevan a la construcción de un programa, nuevamente, utilizando un ejemplo simple. La evaluación de esta unidad se realizará mediante una prueba de opción múltiple en la que se incluyen los temas expuestos. Para exponer los temas relacionados con la elaboración de los algoritmos, se recurre al mundo de la ardilla, un ejemplo en el cual se supone que una ardilla ha sido entrenada para realizar un conjunto limitado de instrucciones precisas, de tal manera que para solucionar un problema únicamente se puede recurrir a este conjunto. De esta forma se pretende que reconozcas intuitivamente que la computadora –al igual que la ardilla– sólo es capaz de realizar un conjunto limitado de instrucciones precisas, por lo que la solución de un problema sólo puede incluir instrucciones reconocidas por ésta. Así mismo, mediante este ejemplo, se te muestra qué es un algoritmo, cuáles son sus características y sus formas de representación; posteriormente se te presentan las estructuras de control básicas de la programación estructurada ejemplificando su uso a través de la construcción de algoritmos que dirigen a la ardilla en la realización de una tarea específica. Así se te introduce en el diseño de soluciones estructuradas de problemas simples representadas de manera formal, ya sea con un diagrama de flujo o con un pseudocódigo. Es importante mencionar que la ventaja de presentar el tema desde un ejemplo tan simple y limitado como el mundo de la ardilla, facilita que puedas proponer soluciones estructuradas en un lenguaje específico, que es justo de lo que se trata la programación.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
8
Fundamentos de programación Programa Desarrollado
En las siguientes unidades la estrategia de aprendizaje es similar, se te presentan los contenidos al mismo tiempo que se utilizan para solucionar problemas, sólo que en este caso se proponen situaciones reales que te son familiares, de tal manera que cuentes con los conocimientos necesarios para solucionarlos y solo te tengas que enfocar en representar la solución utilizando las estructuras de control definidas, es decir, las instrucciones permitidas. En general, en las actividades formativas deberás realizar algunas modificaciones a los algoritmos o programas presentados en los contenidos, o bien, los escribirás en lenguaje C para que puedas ver su ejecución, además debes ingresar al foro de cada unidad para realizar los comentarios que tengas al respecto. Es importante que realices cada una de las actividades propuestas por que a través de ellas se complementan los temas expuestos. De igual manera, para poner en práctica los conocimientos adquiridos y evaluar que se haya alcanzado la competencia específica a lo largo del curso desarrollarás un proyecto integrador que consiste en el planteamiento, análisis, diseño de la solución e implementación de un programa que involucre el uso de todas las estructuras de control y de datos que se estudiarán. En este caso, tú serás el responsable de plantear el problema que deseas solucionar y junto con tu facilitador delimitarás las fases y/o versiones que realizarás en cada unidad. El papel que juega tu facilitador (a) en el proceso de aprendizaje es fundamental, pues su tarea es guiarte en la solución de problemas a partir del análisis que tú realices y las ideas o dudas que te surjan con el mismo. El facilitador por ningún motivo debe darte la solución completa de un problema, en lugar de ello debe propiciar el intercambio de ideas y experiencias de los estudiantes mediante foros de discusión, favoreciendo el aprendizaje colaborativo; si después de esto siguen existiendo dudas se recomienda que resuelva problemas similares para que tanto tú como tus compañeros refuercen los conocimientos y habilidades de una manera inductiva y así logren dar solución al problema en cuestión. Por lo anterior, existe un foro de discusión general en el cual cualquiera puede exponer sus dudas respecto a un tema o problema para que sean retroalimentados por tu facilitador y los compañeros de grupo. Es importante que el facilitador promueva un clima de respeto mutuo y libertad de expresión para que tanto tú como tus compañeros se sientan cómodos al externar sus dudas y propuestas, permitiendo la disensión de manera fundamentada y deferente. En lo referente a la evaluación de las actividades y evidencias, tu facilitador debe revisar cuidadosamente los entregables que hagas y retroalimentarlos de manera positiva, clara y concisa; haciendo evidente el avance que hayas alcance y sin perder de vista que los errores que comentas debe ser utilizados a favor de tu aprendizaje, por lo que debe prestar principal atención a éstos indicándote en qué consiste el error y cómo se corrige, fundamentando su anotación en los contenidos del curso.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
9
Fundamentos de programación Programa Desarrollado
V. Evaluación En el marco del Programa de la ESAD, la evaluación se conceptualiza como un proceso participativo, sistemático y ordenado que inicia desde el momento en que el estudiante ingresa al aula virtual. Por lo que se le considera desde un enfoque integral y continuo. Por lo anterior, para aprobar la asignatura, se espera la participación responsable y activa del estudiante así como una comunicación estrecha con su facilitador para que pueda evaluar objetivamente su desempeño. Para lo cual es necesaria la recolección de evidencias que permitan apreciar el proceso de aprendizaje de contenidos: declarativos, procedimentales y actitudinales. En este contexto la evaluación es parte del proceso de aprendizaje, en el que la retroalimentación permanente es fundamental para promover el aprendizaje significativo y reconocer el esfuerzo. Es requisito indispensable la entrega oportuna de cada una de las tareas, actividades y evidencias así como la participación en foros y demás actividades programadas en cada una de las unidades, y conforme a las indicaciones dadas. La calificación se asignará de acuerdo con la rúbrica establecida para cada actividad, por lo que es importante que el estudiante la revise antes realizarla. A continuación presentamos el esquema general de evaluación. ESQUEMA DE EVALUACIÓN Foros y base de datos
10%
Actividades formativas
30%
E-portafolio. 50%
Evidencias
40%
Autorreflexiones
10%
Examen final
CALIFICACIÓN FINAL
10%
100%
Cabe señalar que para aprobar la asignatura, se debe de obtener la calificación mínima indicada por la ESAD. Los trabajos que se tomarán como evidencias de aprendizaje son: Unidad 2:
Planteamiento del problema Especificación clara y precisa del problema que se resolverá mediante un programa en C
Unidad 3:
Análisis del problema Datos de entrada, salida y bosquejo de la solución.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
10
Fundamentos de programación Programa Desarrollado
Unidad 4:
Programa en C. Estructuras de control. Primera versión de la solución del problema (algoritmo y codificación) que incluya estructuras secuenciales, selectivas y repetitivas.
Unidad 5:
Programa en C. Estructuras de datos Segunda versión de la solución del problema (algoritmo y codificación) que incluya estructuras de datos.
Unidad 6:
Programa en C. Modular (versión final) Entrega final del programa que soluciona el problema de forma modular
VI. Materiales de apoyo
Bibliografía básica: Böhm, C., & Jacopini, G. (1966). Flow diagrams, Turing machines, and languages only with two formation rules". Communications of the ACM, 9 (5), 366-371. Cairó, O. (2005). Metodología de la programación: Algoritmos, diagramas de flujo y programas. México, D.F.: Alfaomega. Guerrero, F. (s.f.). mailxmail.com. Recuperado el 15 de 8 de 2010, de http://www.mailxmail.com/cursointroduccion-lenguaje-c Joyanes, L., & Zohanero, I. (2005). Programación en C. Metodología, algoritmos y estructuras de datos. España: Mc Graw Hill. Kernighan, B., & Ritchie, D. (1991). El lenguaje de programción C. México: Prentice-Hall Hispanoamericana. López, L. (2005). Programación estructurada en lenguaje C. México: Alfaomega. Reyes, A., & Cruz, D. (2009). Notas de clase: Introducción a la programación. México, D.F.: UACM. Villela, H. T. (20 de agosto http://www.fismat.umich.mx/mn1/manual/
de
2010).
Manual
de
C.
Obtenido
de
Viso, E., & Pelaez, C. (2007). Introducción a las ciencias de la computación con Java. México, D.F.: La prensas de ciencias, Facultad de Ciencias, UNAM.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
11
Fundamentos de programación Programa Desarrollado
VII. Desarrollo de contenidos por unidad Unidad 1: Introducción a la computadora y desarrollo de software Propósitos de la unidad En esta unidad: Identificarás los conceptos básicos relacionados con la computadora y los lenguajes de programación. Distinguirás los elementos de una computadora que intervienen en la ejecución de un programa a través del modelo de Von Neumann. Distinguirás los paradigmas de programación y los lenguajes asociados a éstos. Reconocerás las fases que se siguen para solucionar un problema mediante la computadora. Competencia específica Describir los elementos de la computadora y el ciclo de vida de software mediante el análisis un programa simple, con el fin de identificar los pasos que se realizan para construirlo y determinar qué elementos de la computadora intervienen en su ejecución. Introducción Bienvenido a la primera unidad del curso fundamentos de programación, en esta unidad estudiaremos qué son las computadoras y cómo pueden ayudarnos para resolver problemas. Lo primero que tienes que tener claro es que las computadoras no poseen inteligencia alguna, ya que por sí solas no son capaces de resolver ningún problema, su importancia está en la capacidad de datos que pueden almacenar y manipular; de tal manera que para lograr nuestro fin– resolver problemas mediante la computadora – es necesario desarrollar programas escritos en un lenguaje de programación para que puedan ser ejecutados por una computadora. Los orígenes de las computadoras se remontan a dispositivos mecánicos como el ábaco que sirve para contar y ya se utilizaba en el año 2000 a.C, seguido de la Pascalina que fue la primera calculadora mecánica del mundo inventada por el francés Blaise Pascal en el año de 1642, y que después fue perfeccionada por Gottfried Leibniz. Dos siglos después, en el año de 1834, Charles Babbage anticipó la estructura de la computadora electrónica moderna, sin lograr su objetivo dadas las limitaciones de ingeniería del siglo XIX. Fue hasta la segunda guerra mundial (1936) que se cumplieron sus expectativas, cuando Alan Turing desarrolló la primera computadora electromecánica: el Colossus, encargada de descifrar los mensajes alemanes escritos en código Enigma.1 Una década después
1
Se conoce como código Enigma al lenguaje de codificación de la máquina con el mismo nombre, utilizada en Europa a inicios de 1920, para
cifrar y descifrar mensaje.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
12
Fundamentos de programación Programa Desarrollado
Wallace J Eckert y Jonh W. Mauchly construyeron la primera computadora digital totalmente electrónica, llamada ENIAC (por sus siglas en inglés Electronic Numerical Intregrator And Computer). La característica principal de este invento es que se trataba de un componente de propósito general, ya que se podía programar para que resolviera diferentes problemas, pero la programación se realizaba modificando o reconstruyendo algunas partes del hardware. Con el fin de remediar esto, en 1945 el matemático Jonh Von Neumann propuso una arquitectura de computadoras cuya programación no era por medio de cables sino por medio de la creación de programas, a la que se le conoce como Modelo de Von Neumann, y que es, hasta hoy en día, la arquitectura base de las computadoras. Por lo anterior, en esta unidad se estudiarán los siguientes temas: el Modelo de Von Neumann, los pasos para realizar un programa y los principales paradigmas y lenguajes de programación utilizados actualmente. Actividad 1. Foro Fundamentos de programación Para facilitar el estudio de la asignatura, hemos creado un foro de discusión general, a través del cual podrás comentar cualquier asunto relacionado con Fundamentos de programación. Accede al foro desde el aula virtual. 1.1 ¿Qué es una computadora? Para fines de este curso entenderemos que una computadora es una máquina electrónica que recibe datos de entrada y los procesa de acuerdo al conjunto de instrucciones, llamado programa, para obtener nuevos datos que son el resultado del proceso, tal como se ilustra en la siguiente figura.
Figura 1.1:Computadora
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
13
Fundamentos de programación Programa Desarrollado
Lo anterior nos lleva a clasificar los componentes de una computadora en dos clases: hardware y software. Los recursos de hardware son todos aquellos elementos de la computadora que se pueden palpar, como por ejemplo: el monitor, el teclado, el disco duro, la memoria, entre otros. En cambio, los recursos de software son aquellos elementos intangibles sin los cuales la computadora no funcionaría, esto es, el soporte lógico: programas y datos, entre los cuales se encuentran los sistemas operativos, editores de texto, compiladores, bases de datos, videojuegos, entre otros. 1.2 Estructura y funcionamiento de una computadora Si nos cuestionamos ¿cómo funciona y se estructura internamente la computadora?, ¿cómo se obtienen los resultados? y ¿cómo se guardan los programas y datos en la memoria?, cuando tenemos un primer acercamiento con estos equipos, a pesar de manejarlos a diario, estas preguntas no son tan fáciles de contestar. Es por eso que en esta sección explicaremos y responderemos a estos cuestionamientos mediante el Modelo de Von Neumann. 1.2.1 Modelo de Von Neumann El Modelo de Von Neumann propone que tanto el programa como los datos sean almacenados en la memoria, de esta forma la computadora no tendría que reconstruirse, pues para programarla únicamente debe introducirse el programa por el dispositivo indicado, y posteriormente alimentar con los datos de entrada para que calcule la salida correspondiente. Los elementos que componen esta arquitectura son: la unidad central de procesamiento integrada por la unidad aritmética-lógica y la unidad de control, la memoria y los dispositivos de entrada/salida. A continuación se describe brevemente la función de cada uno de los elementos que integran el Modelo de Von Neumann:
Unidad Central de Procesamiento(CPU, Central Process Unit), controla y coordina la ejecución de las instrucciones, para ello utiliza la Unidad Aritmético-Lógica encargada del procesamiento de los datos y la Unidad de Control para el procesamiento de las instrucciones. o
o
Unidad Aritmético-Lógica(ALU, Arithmetic Logic Unit), realiza todas las operaciones aritméticas (suma y resta) y lógicas (operaciones del Algebra de Boole). Además de los circuitos que le permiten realizar dichas operaciones, la ALU incluye un elemento auxiliar donde se almacenan temporalmente los datos que manipula conocido como acumulador o registro temporal (TR, Temporal Register). Unidad de Control(CU, Control Unit), se encarga de leer las instrucciones almacenadas en memoria, decodificarlas y después enviar las señales a los componentes que están involucrados en su ejecución, para lo cual tiene dos elementos auxiliares el Contador del Programa(PC, Program Counter) y el Registro de Instrucción(IR, Instruction Register). En el IR se guarda temporalmente la instrucción que debe ser ejecutada, mientras que en el PC se almacena la dirección de memoria que contiene la siguiente instrucción que se ejecutará.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
14
Fundamentos de programación Programa Desarrollado
Memoria principal, es la parte de la computadora donde se almacenan los datos y las instrucciones durante la ejecución de un programa. Físicamente está compuesta por circuitos integrados. Las computadoras actuales cuentan con un área de memoria de sólo lectura – a la que se le conoce como memoria de tipo ROM (Read Only Memory) –y otra en la cual es posible escribir y leer datos – denominada de tipo RAM (Random Access Memory). La memoria RAM tiene el inconveniente de ser volátil pues al apagarse la computadora los datos almacenados se pierden. Para resolver este inconveniente, se cuenta con otro tipo de memoria, denominada memoria secundaria, en ella se pueden almacenar una gran cantidad de información permanentemente, mientras el usuario no la borre. La desventaja de este tipo de dispositivos es que no son tan rápidos como la memoria RAM. Los discos duros, los discos ópticos (CD o DVD), la memoria flash (USB) y las cintas magnéticas, entre otras, son ejemplos de dispositivos de almacenamiento secundario.
Dispositivos de entrada y salida (Input/Output), son responsables de la comunicación con el usuario del sistema. Los dispositivos de entrada permiten introducir en la computadora datos e instrucciones, mismas que son transformadas en señales binarias de naturaleza eléctrica para almacenarlas en la memoria. Por otro lado, los dispositivos de salida permiten enviar los resultados a los usuarios de las computadoras, transformando las señales eléctricas binarias en información que éstos puedan comprender. El teclado está considerado como el dispositivo de entrada estándar pero existen otros del mismo tipo, por ejemplo: el ratón, el escáner, la lectora óptica, el micrófono o la tabla digital. A su vez el monitor es el dispositivo de salida estándar; otros ejemplos de dispositivos de salida son: impresora, bocinas, plotter, etc.
Es así que todas las unidades de la computadora se comunican a través del sistema de buses que son cables mediante los cuales se envían señales y dependiendo de la información que transmiten se clasifican en: a) El bus de direcciones transmite la dirección de memoria de la que se quiere leer o en la que se quiere escribir. b) El bus de control selecciona la operación a realizar en una celda de memoria (lectura o escritura). c) El bus de datos transmite el contenido desde o hacia una celda de memoria seleccionada en el bus de direcciones según la operación elegida en el bus de control sea lectura o escritura. Ahora ya sabemos cómo está estructurada internamente la computadoras, qué elementos la integran y cuál es la función de cada uno de ellos, el siguiente paso es descubrir cómo colaboran para llevar a cabo la ejecución de un programa, en seguida lo explicamos: los datos de entrada que requiere un programa se introducen a la computadora, a través de los dispositivos de entrada; posteriormente se almacenan en la memoria RAM, para que la CPU pueda procesarlos, conforme a las instrucciones del programa, hasta obtener el resultado deseado, mismo que envía al usuario por medio de los dispositivos de salida. Todas estas acciones son coordinadas por la unidad de control que envía las
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
15
Fundamentos de programación Programa Desarrollado
señales y datos a cada uno de los dispositivos de la computadora involucrados en la ejecución de las instrucciones del programa a través del sistema de buses. En la siguiente sección se describe con mayor detalle este proceso. 1.2.2Ejecución de programas en la computadora Para que entender mejor lo que sucede en el interior de la CPU al ejecutar cualquier programa, a continuación se describen de manera general los pasos que se realizan, una vez que el programa y los datos fueron almacenados en la memoria principal: a) Primero, la unidad de control consulta en la memoria la instrucción indicada en el contador del programa y la almacena en el registro de instrucciones, actualizando el contador del programa con la dirección de memoria de la siguiente instrucción. b) Después de que se almacenó la instrucción en el registro del programa, la unidad de control se encarga de decodificarla, detectando qué dispositivos están implicados en su ejecución, estos pueden ser: la ALU, cuando se tiene que hacer una operación; los dispositivos de entrada y/o salida, cuando se tiene que enviar o recibir un dato; o la memoria, si se quiere guardar o consultar un dato; posteriormente envía las señales de control a los mismos indicándoles la acción y, si es el caso, los datos y/o la dirección de memoria correspondiente. c) Cuando los dispositivos realicen su tarea enviarán una señal a la unidad de control, para que esta repita el mismo procedimiento con la siguiente instrucción, así hasta ejecutar todo el programa. Al período en el que se ejecuta una instrucción se le conoce como ciclo de instrucción o ciclo fetch. Con el fin de ilustrar este procedimiento, analizaremos la ejecución del siguiente programa escrito en un lenguaje de programación ficticio. Ejemplo 1.1: El siguiente conjunto de instrucciones calcula el área de un rectángulo.
Imprimir “Ingresa la base:” Leer b Imprimir “Ingresa la altura:” Leer h area← b*h Imprimir área Programa 1.1:Calcula área de un rectángulo
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
16
Fundamentos de programación Programa Desarrollado
Antes de definir paso a paso la ejecución de este programa describiremos la función de cada una de las instrucciones que lo integran. Instrucción
Descripción
Imprime en el dispositivo de salida estándar los <Datos> Imprimir <Dato> indicados en la instrucción, que pueden ser un mensaje de texto o el valor de una variable. Lee por medio del teclado un dato, lo almacena en la variable Leer <X> <X> indicado y lo almacena en la memoria RAM. La flecha representa una asignación, esta acción actualiza la <X> ← <Dato> dirección de memoria asignada a <X> con el valor <Dato>. Tabla 1.1: Lista de instrucciones en lenguaje de programación ficticio Cabe señalar que en los lenguajes de programación, las direcciones de memoria se representan por medio de variables, para hacerlos más legibles. De tal manera que <X> representa una variable y <Dato> puede ser un mensaje o cualquier valor. Ahora sí, de acuerdo con la información anterior, en la siguiente tabla se describen paso a paso las acciones que realiza la unidad de control junto con las otras unidades de la computadora involucradas en la ejecución de cada una de las instrucciones del programa. Instrucción Imprimir “Ingresa base: ”
Leer b Imprimir “Ingresa altura:”
Leer h area← b *h Imprimir area
Descripción de la instrucción La unidad de control envía señales al monitor para que imprima el mensaje “Ingresa base:”. La unidad de control coordina las acciones necesarias para que, por medio del teclado ,el usuario introduzca un número y lo almacene en la memoria principal, en el espacio correspondiente a la variable b. La unidad de control, nuevamente, envía una señal al monitor para que imprima el mensaje “Ingresa altura:”. La unidad de control coordina las acciones necesarias para que el usuario introduzca un número, por medio del teclado, y lo almacene en el espacio de memoria correspondiente a la variable h. La unidad de control envía la señal indicada a la ALU para que realice la multiplicación posteriormente envía la señal a la memoria junto con el resultado de la multiplicación, para que se almacene en el espacio de memoria a. La unidad de control trae de la memoria el dato almacenado en el espacio asignado a la variable area y coordina las acciones para que el monitor imprima este valor.
Tabla 1.2: Ejecución paso a paso de un programa
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
17
Fundamentos de programación Programa Desarrollado
1.2.2 Almacenamiento de programas y datos La computadora sólo entiende señales binarias: ceros y unos, encendido y apagado, ya que todos los dispositivos de una computadora trabajan con dos únicos estados: hay corriente eléctrica y no hay corriente, respectivamente. Por tal motivo, los datos y programas almacenados en la memoria están codificados como cadenas de 1´s y 0´s para que la unidad de control pueda interpretarlos. A esta codificación se le llama lenguaje de máquina. Cabe mencionar que la memoria está dividida en varias celdas, en cada una de ellas se puede almacenar únicamente 0s ó 1s, a estos valores se les denomina valores binarios o BIT´s (BInary DigiT). Las celdas se agrupan para formar registros (también llamados palabras), a cada uno le corresponde una dirección de memoria, así cuando se desea escribir o leer de la memoria un dato o una instrucción se debe especificar la dirección dónde se encuentra. Como podrás imaginar, para un ser humano resultaría sumamente complicado escribir los programas en lenguaje de máquina, es por eso que los programas se escriben en lenguaje de programación entendibles para los seres humanos y después se traducen mediante un software especial –que pueden ser un compilador o un traductor– a cadenas de 0´s y 1´s. De tal manera que a cada instrucción le corresponde un código binario específico y para cada dato también existe una codificación única. Por ejemplo, la palabra “Hola” se representa como “0100 1000 0110 1111 0110 1100 0110 0000”, ya que a cada letra le corresponde una codificación: H 0100 1000
O 0110 1111
L 0110 1100
A 0110 0000
El número 80 se puede representar como “0101 0000” y la instrucción “MOV R2, R7” se codifica de la siguiente manera “0010 0000 1000 0100.” Conforme fueron evolucionando las computadoras se inventaron diversas maneras de representar la información en código binario, hoy en día existen codificaciones estándar para los símbolos y los números, al igual que para las instrucciones; sin embargo, para nuestros objetivos es suficiente tener claro que cualquier dato o instrucción puede ser representado mediante cadenas de 0s y 1s. Por otro lado, escribir programas en lenguaje binario es sumamente complicado para los seres humanos, por lo que en las últimas décadas se han desarrollado diversos lenguajes de programación que son más cercanos al lenguaje natural (humano), de los cuales hablaremos en la siguiente sección. 1.3 Lenguajes de Programación Los lenguajes de programación sirven para escribir programas de computadora orientados a resolver algún problema o necesidad. Cada lenguaje de programación se define a partir de un conjunto de símbolos básicos, llamado alfabeto; un conjunto de reglas, llamado sintaxis, que definen la forma de
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
18
Fundamentos de programaciĂłn Programa Desarrollado
manipularlos o combinarlos para representar instrucciones; y las reglas que especifican los efectos de dichas instrucciones cuando son ejecutadas por la computadora, conocidas como semĂĄntica. De esta manera tenemos que: đ??żđ?&#x2018;&#x2019;đ?&#x2018;&#x203A;đ?&#x2018;&#x201D;đ?&#x2018;˘đ?&#x2018;&#x17D;đ?&#x2018;&#x2014;đ?&#x2018;&#x2019;đ?&#x2018;&#x2018;đ?&#x2018;&#x2019;đ?&#x2018;?đ?&#x2018;&#x;đ?&#x2018;&#x153;đ?&#x2018;&#x201D;đ?&#x2018;&#x;đ?&#x2018;&#x17D;đ?&#x2018;&#x161;đ?&#x2018;&#x17D;đ?&#x2018;?đ?&#x2018;&#x2013;Ăłđ?&#x2018;&#x203A; = đ?&#x2018;&#x17D;đ?&#x2018;&#x2122;đ?&#x2018;&#x201C;đ?&#x2018;&#x17D;đ?&#x2018;?đ?&#x2018;&#x2019;đ?&#x2018;Ąđ?&#x2018;&#x153; + đ?&#x2018; đ?&#x2018;&#x2013;đ?&#x2018;&#x203A;đ?&#x2018;Ąđ?&#x2018;&#x17D;đ?&#x2018;Ľđ?&#x2018;&#x2013;đ?&#x2018; + đ?&#x2018; đ?&#x2018;&#x2019;đ?&#x2018;&#x161;ĂĄđ?&#x2018;&#x203A;đ?&#x2018;Ąđ?&#x2018;&#x2013;đ?&#x2018;?đ?&#x2018;&#x17D; Por otro lado, dependiendo de su legibilidad para el ser humano los lenguajes de programaciĂłn se clasifican en lenguajes de bajo nivel y lenguajes de alto nivel. Los primeros se caracterizan porque sus instrucciones se parecen mĂĄs a las acciones elementales que ejecuta una computadora, como son: sumar, restar, guardar en memoria, etc. En cambio, las instrucciones de los lenguajes de alto nivel son mĂĄs parecidas a un lenguaje humano, por lo regular inglĂŠs. Por otro lado, los programas escritos en bajo nivel describen a detalle lo que sucede a nivel de hardware, mientras que los programas escritos en un lenguaje de alto nivel lo ocultan, teniendo como ventaja que son mĂĄs fĂĄciles de entender para las personas. 1.3.1. EvoluciĂłn de los lenguajes de programaciĂłn Con las primeras computadoras surgiĂł el primer lenguaje de programaciĂłn que â&#x20AC;&#x201C;como es de imaginarseâ&#x20AC;&#x201C; fue el lenguaje de mĂĄquina, el cual es considerado el lenguaje de primera generaciĂłn. Las instrucciones en lenguaje de mĂĄquina dependĂan de las caracterĂsticas de cada equipo, por lo que dada la dificultad de desarrollar programas en unos y ceros, los investigadores de la ĂŠpoca desarrollaron el lenguaje ensamblador, cuyo conjunto de instrucciones consta de palabras nemotĂŠcnicas que corresponden a las operaciones bĂĄsicas que una computadora puede ejecutar. Para ilustrar esto revisemos la siguiente instrucciĂłn:2 Mueve el contenido del registro 8 al contenido del registro 10 En lenguaje de mĂĄquina esta se podrĂa representar como: 0010 0000 1000 0100 Lo cual es ilegible para el ser humano, en cambio en lenguaje ensamblador esta instrucciĂłn se puede representar de la siguiente forma: MOV R2, R7
2
Este ejemplo es una adaptaciĂłn de la versiĂłn original que aparece en (Joyanes & Zohanero, 2005, pĂĄg. 32) (Joyanes & Zohanero, 2005, pĂĄg. 32)
EducaciĂłn Superior Abierta y a Distancia â&#x20AC;˘ Ciencias Exactas, IngenierĂa y TecnologĂa
19
Fundamentos de programación Programa Desarrollado
Aunque sigue estando en clave, es más amigable que las cadenas de ceros y unos. Otra característica del lenguaje ensamblador es que las instrucciones dependían de las características físicas (arquitectura) de la computadora. Para traducir de lenguaje ensamblador a lenguaje de máquina, se desarrollaron programas llamados ensambladores (en inglés, assemblers). Este lenguaje fue considerado de segunda generación. Posteriormente, en la década de los 50´s aparecieron los primeros lenguajes de alto nivel, cuyas instrucciones son más parecidas al idioma inglés y, por lo tanto, más fácil de utilizar para los programadores, además de que son independientes de la arquitectura de las computadoras. Algunos ejemplos son: FORTRAN y COBOL (que son los primeros lenguajes que aparecieron y en sus inicios se utilizaron para aplicaciones científicas), C, Pascal, Ada, Lisp y Prolog (utilizados principalmente en inteligencia artificial), Java, C++, C#, entre otros. Al igual que el lenguaje ensamblador, los programas escritos en un lenguaje de alto nivel deben ser codificados a lenguaje de máquina, así que junto con ellos se desarrollaron programas traductores, que de acuerdo con la forma en que trabajan se dividen en dos tipos: compiladores e intérpretes.
Los compiladores traducen todo el programa escrito en un lenguaje de alto nivel, llamado programa fuente, generando un nuevo programa objeto que está escrito en lenguaje de máquina y a partir de este se genera un programa ejecutado, el cual puede ejecutarse cada vez que se desee sin tener que compilar el programa fuente de nueva cuenta. Además, como parte del proceso de traducción el compilador detecta los errores que hay en el código fuente, informándole al programador para que los corrija, pues un programa sólo se compila si no tiene errores.
En cambio, un intérprete revisa una a una cada línea de código, la analiza y enseguida la ejecuta, sin revisar todo el código y sin generar un programa objeto, así que cada vez que se quiere ejecutar el programa se vuelve a traducir el programa fuente línea por línea.
Por lo anterior, los compiladores requieren una fase extra antes de poder generar un programa ejecutable, y aunque esto pareciera menos eficiente en cuanto a tiempo, los programas creados con compiladores se ejecutan mucho más rápido que un mismo programa ejecutado con un intérprete. Además, cuando un programa ya ha sido compilado puede ejecutarse nuevamente sin tener que compilarse, mientras que los programas que son interpretados, cada vez que se ejecutan se deben volver a traducir. Conforme han ido evolucionando las computadoras también lo han hecho las estrategias para solucionar problemas, generando nuevos programas programación con diferentes filosofías, llamadas paradigmas de programación, de esto hablaremos a continuación.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
20
Fundamentos de programaciĂłn Programa Desarrollado
1.3.2 Paradigmas de los lenguajes de programaciĂłn Un paradigma de programaciĂłn representa un enfoque particular o filosofĂa para diseĂąar soluciones. Los paradigmas difieren unos de otros en los conceptos y la forma de abstraer los elementos involucrados en un problema, asĂ como en los pasos que integran su soluciĂłn del problema, en otras palabras, el cĂłmputo. Un lenguaje de programaciĂłn siempre sigue un paradigma de programaciĂłn, aunque tambiĂŠn podemos encontrar lenguajes con la influencia de dos paradigmas, tal es el caso del lenguaje C++, que surgiĂł bajo el paradigma procedimental y se transformĂł al paradigma orientado a objetos, de tal manera que puede soportar ambos paradigmas. Los paradigmas mĂĄs importantes son: ď&#x201A;ˇ
Paradigma imperativo o procedural. Es el mĂŠtodo de programaciĂłn tradicional, donde los programas describen la forma de solucionar un problema a partir de una lista de instrucciones que se ejecuta de forma secuencial, a menos que se trate de estructuras de control condicionales o repetitivas, o bien, saltos de secuencia representados por la instrucciĂłn GOTO.3 La programaciĂłn imperativa se define a partir del cambio de estado de las variables que se produce por la ejecuciĂłn de las instrucciones, por ejemplo, el programa 1.1, que calcula el ĂĄrea de un rectĂĄngulo, es un ejemplo de un programa imperativo, ya que describe paso a paso como solucionar el problema y el resultado corresponde al estado final de la variable area. Sin embargo, el lenguaje en el que estĂĄ escrito no corresponde a ningĂşn lenguaje de programaciĂłn real, pero el lenguaje de mĂĄquina es un ejemplo de este paradigma. Otros lenguajes imperativos son: Fortran, Cobol, Pascal, Basic, Ada y C.
ď&#x201A;ˇ
Paradigma declarativo. En contraste con el paradigma imperativo, el objetivo de este paradigma no es describir cĂłmo solucionar un problema, sino describir un problema mediante predicados lĂłgicos o funciones matemĂĄticas. Dentro de este paradigma se encuentran los lenguajes de programaciĂłn funcionales y los lenguajes de programaciĂłn lĂłgicos. Los primeros representan el problema utilizando funciones matemĂĄticas, por ejemplo, un programa que calcule el ĂĄrea de un rectĂĄngulo utilizando un lenguaje funcional se verĂa asĂ: đ?&#x2018;&#x17D;đ?&#x2018;&#x;đ?&#x2018;&#x2019;đ?&#x2018;&#x17D;đ?&#x2018;&#x2026;đ?&#x2018;&#x2019;đ?&#x2018;?đ?&#x2018;Ąđ?&#x2018;&#x17D;đ?&#x2018;&#x203A;đ?&#x2018;&#x201D;đ?&#x2018;˘đ?&#x2018;&#x2122;đ?&#x2018;&#x153;(đ?&#x2018;?, đ?&#x2018;&#x2022;) = đ?&#x2018;? â&#x2C6;&#x2014; đ?&#x2018;&#x2022;
3
De esto hablaremos en unidades posteriores.
EducaciĂłn Superior Abierta y a Distancia â&#x20AC;˘ Ciencias Exactas, IngenierĂa y TecnologĂa
21
Fundamentos de programaciĂłn Programa Desarrollado
De tal manera que para calcular el ĂĄrea de un rectĂĄngulo de base igual a 5 unidades y altura igual a 10 unidades, se ejecuta la funciĂłn con los parĂĄmetros 5,10, es decir, areaRectĂĄngulo (5,10), la cual devuelve como resultado 50. Los lenguajes de programaciĂłn mĂĄs representativos del paradigma funcional son: Lisp, ML y Haskell. En el caso de los lenguajes lĂłgicos la soluciĂłn se representa a travĂŠs de un conjunto de reglas, por ejemplo: đ?&#x2018;&#x17D;đ?&#x2018;&#x;đ?&#x2018;&#x2019;đ?&#x2018;&#x17D;đ?&#x2018;&#x2026;đ?&#x2018;&#x2019;đ?&#x2018;?đ?&#x2018;ĄĂĄđ?&#x2018;&#x203A;đ?&#x2018;&#x201D;đ?&#x2018;˘đ?&#x2018;&#x2122;đ?&#x2018;&#x153;(đ?&#x2018;?, đ?&#x2018;&#x2022;, đ?&#x2018;&#x17D;đ?&#x2018;&#x;đ?&#x2018;&#x2019;đ?&#x2018;&#x17D;) â&#x2C6;ś â&#x2C6;&#x2019;đ?&#x2018;&#x161;đ?&#x2018;˘đ?&#x2018;&#x2122;đ?&#x2018;Ąđ?&#x2018;&#x2013;đ?&#x2018;?đ?&#x2018;&#x2122;đ?&#x2018;&#x2013;đ?&#x2018;?đ?&#x2018;&#x17D;đ?&#x2018;?đ?&#x2018;&#x2013;Ăłđ?&#x2018;&#x203A;(đ?&#x2018;?, đ?&#x2018;&#x2022;, đ?&#x2018;&#x17D;đ?&#x2018;&#x;đ?&#x2018;&#x2019;đ?&#x2018;&#x17D;) Esta regla dice que el valor de la variable area corresponde al ĂĄrea del rectĂĄngulo con base b y altura h sĂłlo si area es el resultado de multiplicar b por h. Estamos suponiendo que se ha definido el predicado multiplicaciĂłn(a, b, c). En este caso para calcular el resultado se utiliza el principio de razonamiento lĂłgico para responder a las preguntas planteadas, por ejemplo si se desea calcular el ĂĄrea del mismo rectĂĄngulo, la pregunta serĂa la siguiente: ? đ?&#x2018;&#x17D;đ?&#x2018;&#x;đ?&#x2018;&#x2019;đ?&#x2018;&#x17D;đ?&#x2018;&#x2026;đ?&#x2018;&#x2019;đ?&#x2018;?đ?&#x2018;Ąđ?&#x2018;&#x17D;đ?&#x2018;&#x203A;đ?&#x2018;&#x201D;đ?&#x2018;˘đ?&#x2018;&#x2122;đ?&#x2018;&#x153;(5,10, đ?&#x2018;&#x2039;) Y despuĂŠs de que se realicen los cĂĄlculos (en este caso llamadas inferencias) el resultado que arrojarĂa serĂa: đ?&#x2018;&#x2039; = 50 El lenguaje mĂĄs representativo del paradigma lĂłgico es Prolog. ď&#x201A;ˇ
Paradigma orientado a objetos. En este caso la soluciĂłn de un problema se plantea en tĂŠrminos de objetos y relaciones entre ellos. EstĂĄ basado en varias tĂŠcnicas, incluyendo, herencia, polimorfismo, modularidad y encapsulamiento. En este caso se definen clases que son las plantillas para crear objetos, por ejemplo, un si se quiere un programa orientado a objetos que calcule el ĂĄrea de un rectĂĄngulo, se debe definir una clase rectĂĄngulo que contenga un mĂŠtodo encargado de calcular el ĂĄrea. El lenguaje Java y C#, que actualmente son los mĂĄs utilizados, son ejemplos de este paradigma.
EducaciĂłn Superior Abierta y a Distancia â&#x20AC;˘ Ciencias Exactas, IngenierĂa y TecnologĂa
22
Fundamentos de programación Programa Desarrollado
1.4 Ciclo de vida del software Independientemente del paradigma que se siga y del lenguaje que se utilice para programar, existe un conjunto de fases que deben seguirse para realizar un programa de computadora, al cual se le conoce como ciclo de vida del software, en la siguiente figura se lista cada una de ellas.
Planteamiento
Análisis
del problema
problema
del Diseño
del
algoritmo
Ciclo de vida del software Mantenimiento
Implementación o codificación
Documentación delprograma
Pruebas
y
validación
En las siguientes secciones aprenderemos en qué consiste cada una de las fases, para lo cual nos apoyaremos en la resolución del siguiente problema con la intención de que se entienda mejor: Problema 1.1: Se requiere construir un programa que calcule el área de un rectángulo, con base b y altura h. 1.4.1 Análisis del problema En esta fase se determina ¿qué hace el programa? Por lo cual debe definirse de manera clara y concisa el problema en cuestión, se debe establecer el ámbito del problema, las características, limitaciones y modelos de lo que se desea resolver. Este paso debe conducir a una especificación completa del problema en donde se describa cuáles son los datos requeridos para resolverlo (datos de entrada) y cuál es el resultado deseado (salida).
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
23
Fundamentos de programaciĂłn Programa Desarrollado
El anĂĄlisis de nuestro ejemplo es muy simple y se resume en la siguiente tabla: ÂżCuĂĄl es la salida deseada? ÂżQuĂŠ mĂŠtodo(s) se pueden utilizar para llegar a la soluciĂłn? ÂżQuĂŠ datos requieren?
de
entrada
se
El ĂĄrea de un cuadrado, la cual identificaremos como El ĂĄrea de un rectĂĄngulo se puede calcular con la siguiente fĂłrmula: Ă đ?&#x2018;&#x;đ?&#x2018;&#x2019;đ?&#x2018;&#x17D; = đ??ľđ?&#x2018;&#x17D;đ?&#x2018; đ?&#x2018;&#x2019; â&#x2C6;&#x2014; đ??´đ?&#x2018;&#x2122;đ?&#x2018;Ąđ?&#x2018;˘đ?&#x2018;&#x;đ?&#x2018;&#x17D; Por el planteamiento del problema y dado el mĂŠtodo anterior, los Ăşnicos datos que se requieren son: la medida de la base que se representa por b y la medida de la altura indicada por h En este caso no se requiere mĂĄs informaciĂłn.
ÂżQuĂŠ datos o informaciĂłn adicional es necesaria para solucionar el problema? ÂżExiste algĂşn problema o Las Ăşnicas restricciones son que las condiciones que deban medidas de la base y altura sean cumplirse? mayores a cero. Tabla 1.3: AnĂĄlisis del problema 1 1.4.2DiseĂąo de la soluciĂłn
Es en esta fase se define ÂżcĂłmo el programa resuelve el problema? Para ello, se describe paso a paso la soluciĂłn del mismo, lo cual se conoce como algoritmo. Cuando el problema es grande se recomienda dividirlo en subproblemas mĂĄs pequeĂąos y resolver por separado cada uno de ellos. A esta metodologĂa se le conoce como diseĂąo descendente (top-down) o modular. Existen diferentes formas de representar un algoritmo algunas formales, como una fĂłrmula matemĂĄtica, o informales, como es el caso del lenguaje natural. En la siguiente unidad estudiaremos a mayor profundidad los algoritmos y su representaciĂłn, pero para seguir con el desarrollo de nuestro programa ejemplo, plantearemos la soluciĂłn como una secuencia de pasos en espaĂąol. 1. Obtener la medida de la base (đ?&#x2019;&#x192;) y la altura (đ?&#x2019;&#x2030;) 2. Calcular: ĂĄđ?&#x2019;&#x201C;đ?&#x2019;&#x2020;đ?&#x2019;&#x201A; = đ?&#x2019;&#x192; â&#x2C6;&#x2014; đ?&#x2019;&#x2030; 3. Imprimir el resultado (ĂĄđ?&#x2019;&#x201C;đ?&#x2019;&#x2020;đ?&#x2019;&#x201A;) Algoritmo 1.1: Calcula el ĂĄrea de un rectĂĄngulo El programa 1.1es otra forma de representar la soluciĂłn de este problema, se conoce como pseudocĂłdigo.
EducaciĂłn Superior Abierta y a Distancia â&#x20AC;˘ Ciencias Exactas, IngenierĂa y TecnologĂa
24
Fundamentos de programación Programa Desarrollado
1.4.3 Implementación (codificación) El algoritmo no puede ser ejecutado por una computadora por ello debe traducirse a un lenguaje de programación (como por ejemplo C) para obtener un programa fuente que se traduzca a lenguaje de máquina para que sea ejecutado por la computadora. En el siguiente cuadro se muestra la codificación en lenguaje C del algoritmo, por ahora no es necesario que lo comprendas puesto que esto lo podrás hacer conforme vayas aprendiendo a programar, por lo pronto solamente se muestra con fines ilustrativos. #include<stdio.h> #include<stdlib.h> main() { int b,h, area; printf("Ingresa la base y altura:"); scanf("%d %d", &b,&h); area = b * h; printf("Area = %d", area); } Programa 1.2: Programa en C que calcula área de un rectángulo 1.4.4 Validación y pruebas Esta fase debe hacerse una vez que se ha diseñado el algoritmo y después de que se codifica, sirve para verificar que son correctos. Existen diferentes formas de probar que la solución es correcta, algunas de ellas formales y otras informales: las primera se utilizan para garantizar que el programa o algoritmo siempre calcula el resultado deseado para cualquier conjunto de datos de entrada; en cambio, en las segundas sólo se prueba que funciona correctamente para algunos datos de entrada, tratando de encontrar posibles errores, en este caso no se puede garantizar el programa o algoritmo calcule la salida correcta para cualquier conjunto de datos. En cualquiera de los dos casos, si se encuentra alguna falla se debe corregir y volver a realizar pruebas. En este curso utilizaremos las pruebas de escritorio, las cuales se explicarán en la unidad 2.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
25
Fundamentos de programación Programa Desarrollado
El ejemplo es muy sencillo y si ejecutamos manualmente el programa o algoritmo mostrado en la fase anterior, con un caso específico de rectángulo veremos que ambos son correctos. En la siguiente figura se ilustra la ejecución del programa:
Figura 1.2: Ejecución del programa 1.2
1.4.5 Documentación Cualquier proyecto de software por la complejidad que tiene requiere tanto las ideas principales como el desarrollo de principio a fin sea documentado, con el fin de que cualquiera puedan entender la lógica del programa y de ser necesario pueda modificarlos sin tantas complicaciones. Es común que si se desea modificar un programa y no se tiene información acerca de cómo fue construido sea más fácil volverlo a hacer que intentar entenderlo. Uno de los mejores ejemplos de la importancia de la documentación es el software libre, en el cual colaboran diversos desarrolladores para su elaboración, los cuales se encuentran en diferentes puntos geográficos de globo terráqueo, así que la forma de entender que está haciendo cada uno y bajo que método es la documentación. Además de que se debe tomar en cuenta que se llama software libre porque está disponible el código fuente para que cualquier persona pueda modificarlo a su conveniencia. Como parte de la documentación también deben incluirse manuales de usuario y las normas de mantenimiento para que se haga un buen uso del software. 1.4.6 Mantenimiento Esta fase tiene sentido una vez que fue terminada una primera versión del programa y ya está siendo utilizado. Ya que en ésta se actualiza y modifica para corregir errores no detectados o para cambiar y/o agregar una nueva función. Por ejemplo, se puede extender el programa 1.1, que calcula el área de un rectángulo para que también calcule su perímetro.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
26
Fundamentos de programación Programa Desarrollado
Ejemplo 1.2: El siguiente conjunto de instrucciones calcula el área y perímetro de un rectángulo.
#include<stdio.h> #include<stdlib.h> main() { int b,h, area, perimetro; printf("Ingresa la base y altura:"); scanf("%d %d", &b,&h); perimetro = 2*b + 2*h; area = b * h; printf("Perimetro = %d", perimetro); printf("Area = %d", area); } Programa 1.3: Calcula el área y perímetro de un rectángulo En el programa se resaltan las instrucciones que se añadieron al programa para calcular el perímetro. Actividad de Autoevaluación Ingresa al aula virtual para realizar las dos actividades de autoevaluación, la primera trata de un pequeño juego tipo maratón en el que pondrás a prueba tus conocimientos, la segunda consiste en un cuestionario de opción múltiple. Consideraciones específicas de la unidad Para alcanzar los objetivos de esta unidad se ha propuesto una actividad formativa en la cual revises la ejecución de un problema apoyándote en una animación que muestra paso a paso la ejecución del programa 1.1 que se presentó en esta unidad, en dicha animación se especifica cada uno de los elementos que están involucrados en la ejecución de las instrucciones. Referencias:
Guerrero, F. (s.f.). mailxmail.com. Recuperado http://www.mailxmail.com/curso-introduccion-lenguaje-c
el
15
de
agosto
de
2010,
de
Joyanes, L., & Zohanero, I. (2005). Programación en C. Metodología, algoritmos y estructuras de datos. España: Mc Graw Hill.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
27
Fundamentos de programación Programa Desarrollado
Reyes, A., & Cruz, D. (2009). Notas de clase: Introducción a la programación. México, D.F.: UACM. Viso, E., & Pelaez, C. (2007). Introducción a las ciencias de la computación con Java. México, D.F.: La prensas de ciencias, Facultad de Ciencias, UNAM.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
28
Fundamentos de programación Programa Desarrollado
Unidad 2: Diseño de algoritmos Propósitos En esta unidad: Identificar los datos de entrada y la salida de un algoritmo Diseñar un algoritmo que solucione un problema. Representar el algoritmo en diagrama de flujo y pseudocódigo Verificar que el algoritmo calcule el resultado correcto Competencia específica Diseñar algoritmos para resolver problemas mediante su representación en un diagrama de flujo y la elaboración del pseudocódigo. Introducción En la unidad anterior se describieron los pasos que se requieren para construir un software, sin lugar a dudas, la fase más importante es el diseño de la solución, ya que es aquí donde se debe crear un modelo que corresponde a los pasos que llevan a la solución del problema en cuestión, y se conoce como algoritmo. Para construir esta solución se requiere no sólo de inteligencia, sino también de creatividad, ya que el programador sólo cuenta con la especificación del problema y su experiencia en resolver problemas de una forma estructurada. En este apartado se introduce formalmente el concepto de algoritmo, hablaremos de sus características y estudiaremos dos formas de representarlos: una gráfica, conocida como diagramas de flujo; y la otra similar a un lenguaje humano, en este caso español, la cual se llama pseudocódigo. También se describen los tres tipos de estructuras de control: secuenciales, selectivas y repetitivas, que son las instrucciones con que se cuenta en la programación estructurada para diseñar soluciones. Para logar nuestro objetivo se introduce “el mundo de la ardilla”, en el cual se deben solucionar problemas mediante un conjunto de instrucciones específicas que puede ejecutar una ardilla sobre un tablero. 2.1 Concepto de algoritmo y características La palabra algoritmo proviene del nombre de un matemático persa conocido como Mohammad AlKhoWârizmi, nacido alrededor del 780 d.c. en KhoWârizm, de ahí el su seudónimo. Se considera como el padre de la algoritmia porque definió las reglas paso a paso para sumar, restar, multiplicar y dividir números decimales. La traducción al latín de Al-Khwārizmī es algoritmi, que da origen a la palabra algoritmo (Joyanes & Zohanero, 2005).
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
29
Fundamentos de programación Programa Desarrollado
Formalmente, un algoritmo se define como una secuencia finita de instrucciones precisas y eficaces para resolver un problema, que trabaja a partir de cero o más datos (entrada) y devuelve un resultado (salida).4 Para ilustrar este concepto se presenta el siguiente escenario ficticio, que hemos llamado: El mundo de la ardilla Supongamos que una ardilla ha sido entrenada para realizar las instrucciones que se muestran en la tabla 2.1, sobre un tablero.
INSTRUCCIÓN
DESCRIPCIÓN DE LOS MOVIMIENTOS DE LA ARDILLA
avanza()
Se mueve una ubicación en la dirección actual
giraIzquierda()
Voltea a la izquierda
dejaBellota()
Coloca una bellota en la ubicación actual
hayBellota()
Responde si hay o no bellotas en la posición actual
hayPared()
Responde si hay o no pared en la ubicación siguiente
recogeBellota()
La ardilla coloca en su boca una bellota que está en la ubicación actual5
bellotasRecogidas() Dice el número de bellotas que tiene en la boca Tabla 2.1: Lista de instrucciones que puede ejecutar la ardilla
Los paréntesis al final de cada instrucción sirven para identificar que se trata de una orden que puede ejecutar la ardilla. Si observas la lista de instrucciones podrás darte cuenta que, la ardilla no es capaz de voltear a la derecha y mucho menos de responder a órdenes más complejas como “mueve una bellota que se encuentra en la primera casilla del tablero al final del mismo”. Sin embargo, podría realizar ambas tareas si se le dan las instrucciones precisas en términos de las acciones que sabe hacer. Por ejemplo, para que la ardilla gire a la derecha tendríamos que ordenarle tres veces que girará a la izquierda, es decir, la secuencia de instrucciones que debe ejecutar es: giraIzquierda() giraIzquierda() giraIzquierda()
4
Esta definición es una adaptación de la que aparecen en (Viso & Pelaez, 2007, pág. 3)
5La
ardilla poseen una bolsa donde almacena cualquier cantidad de bellotas.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
30
Fundamentos de programaciĂłn Programa Desarrollado
Estos pasos constituyen un algoritmo, el cual soluciona el problema de hacer que la ardilla gire a la derecha. Una de las caracterĂsticas principales de los algoritmos es que cada paso debe estar definido de forma clara y precisa, sin ambigĂźedades, de tal manera que pueda ejecutarse de manera inequĂvoca, por ejemplo, en el mundo de la ardilla, la instrucciĂłn gira() serĂa una instrucciĂłn ambigua, ya que la ardilla no sabrĂa si debe girar a la derecha o a la izquierda. Otra caracterĂstica de los algoritmos es que siempre terminan, por lo que no puede ser una lista infinita de pasos. Y tampoco puede contener pasos que sean irrealizables o cuya ejecuciĂłn sea infinita, pues en este caso no serĂa posible calcular el resultado deseado, si una instrucciĂłn estĂĄ bien definida y es eficaz se puede asegurar que su ejecuciĂłn termina con ĂŠxito, sin embargo, esto no garantiza, de ninguna manera, que el algoritmo tambiĂŠn termine. Por lo anterior, al diseĂąar un algoritmo se debe garantizar que dada cualquier entrada siempre termine y calcule la respuesta correcta. De tal manera que todo algoritmo debe tener las siguientes caracterĂsticas: 1.Entrada. 2. Salida. 3. Definido. 4. Eficaz. 5. TerminaciĂłn. Una vez que se ha diseĂąado un algoritmo, se recomienda realizar una prueba de escritorio para verificar si funciona correctamente, ĂŠsta consiste en ejecutar el algoritmo utilizando papel y lĂĄpiz, se propone datos de entrada especĂficos y se realiza cada una de las instrucciones en el orden establecido, registrando los cambios que se producen despuĂŠs de la ejecuciĂłn de cada instrucciĂłn. De esta manera, se valida que el resultado obtenido en la prueba de escritorio corresponda al resultado deseado (el correcto). 2.2. RepresentaciĂłn de algoritmos Existen diversas formas de representar un algoritmo, en la unidad anterior expusimos diversas formas de representar la soluciĂłn del problema de calcular el ĂĄrea de un rectĂĄngulo, por ejemplo, en el programa 1.1 se expresa la soluciĂłn en pseudocĂłdigo, despuĂŠs en el algoritmo 1.1 se representa en lenguaje natural (espaĂąol) y en el programa 1.2 se utiliza el lenguaje de programaciĂłn C, o se puede expresar mediante la fĂłrmula matemĂĄtica: ĂĄđ?&#x2018;&#x;đ?&#x2018;&#x2019;đ?&#x2018;&#x17D; = đ?&#x2018;?đ?&#x2018;&#x17D;đ?&#x2018; đ?&#x2018;&#x2019; Ă&#x2014; đ?&#x2018;&#x17D;đ?&#x2018;&#x2122;đ?&#x2018;Ąđ?&#x2018;˘đ?&#x2018;&#x;đ?&#x2018;&#x17D;
EducaciĂłn Superior Abierta y a Distancia â&#x20AC;˘ Ciencias Exactas, IngenierĂa y TecnologĂa
31
Fundamentos de programación Programa Desarrollado
Todas estas representaciones, excepto el lenguaje natural, se consideran formales, y cabe mencionar que existen más, sin embargo, las representaciones más comunes son el pseudocódigo y los diagramas de flujo. La primera, generalmente se utilizar por su parecido con el lenguaje natural (español, inglés, francés o cualquier otro) y porque su codificación en un lenguaje de programación estructurado y modular, como C, es directa. En cambio, los diagramas de flujo son totalmente gráficos, lo que hace más fácil seguir el orden en que se ejecutan las instrucciones. Es importante mencionar que se puede utilizar cualquiera de las dos representaciones para diseñar un algoritmo, pues en cualquiera de los dos se puede expresar cualquier algoritmo estructurado, de tal manera que la más conveniente depende de cada programador. En las siguientes secciones se presenta cada uno de ellos y así podrás decidir cuál prefieres. 2.2.1. Pseudocódigo El pseudocódigo es un lenguaje de especificación formal de algoritmos. La solución de un problema se representa de manera narrativa utilizando palabras claves, generalmente verbos, escritos en un lenguaje natural, que en nuestro caso será español. Para ilustrarlo construyamos un algoritmo que resuelva el siguiente problema. Problema 2.1: En la figura 2.1.a. se muestra el estado inicial de un tablero, el cual contiene en la primer casilla (de izquierda a derecha) una bellota, representada por un asterisco (*), y a la ardilla, representada por una flecha que apunta hacia la dirección que está mirando. El problema consiste en diseñar un algoritmo que la ardilla pueda ejecutar para llegar al estado meta representado en la figura 2.1.b., que implica que la ardilla lleve la bellota a la última casilla. Para resolverlo se tiene la siguiente información: a) El mundo es conocido, es decir, se sabe de antemano que el tablero está cercado por paredes y sólo tiene seis casillas colocadas en línea. b) Al inicio la ardilla está en la primera casilla volteando hacia arriba y no tiene ninguna bellota en la boca. c) En la primera casilla hay una bellota.
*
* Estado inicial (a)
Estado final (b)
Figura 2.1: Primer mundo lineal
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
32
Fundamentos de programación Programa Desarrollado
Análisis: Haciendo un rápido análisis del problema, nos podemos dar cuenta que la ardilla debe recoger la bellota, avanzar cinco casillas y soltar la bellota, esto traducido en un algoritmo queda de la siguiente forma:
Inicio recogeBellota() giraIzquierda() giraIzquierda() giraIzquierda() avanza() avanza() avanza() avanza() avanza() dejaBellota() Fin Algoritmo 2.1. Primer mundo de la ardilla
En este caso las instrucciones son parecidas al lenguaje natural.
2.2.2. Diagrama de flujo
Los diagramas de flujo son una representación gráfica de un algoritmo que utiliza símbolos para representar las instrucciones y flechas para unirlas e indicar el orden en que deben ejecutarse -llamadas líneas de flujo. Estos símbolos fueron normalizados por el Instituto Norteamericano de Normalización ANSI (American National Standars Institute, por sus siglas en inglés). Los símbolos más utilizados se muestran en la siguiente tabla.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
33
Fundamentos de programación Programa Desarrollado
Símbolo
Descripción Terminal. Representa el inicio y el final de un algoritmo.
Terminal Entrada y Salida (E/S). Representa la lectura de datos desde el dispositivo de entrada estándar, así como la impresión de datos en el dispositivo de salida estándar.
E/S
Proceso. Representa cualquier tipo de operación que pueda originar un cambio de la información almacenada en memoria, asignaciones u operaciones aritméticas.
Proceso
Decisión. Nos permite analizar una situación, con base en los valores verdadero y falso. Toma una decisión de las instrucciones que a continuación ejecuta el algoritmo.
Decisión
Conector. Sirve para enlazar dos partes cualesquiera del diagrama que están en la misma página. Línea de flujo. Indica el orden de la ejecución de las operaciones. La flecha indica cuál es la siguiente instrucción que se debe realizar. Conector. Conecta a dos puntos del diagrama cuando éstos se encuentran en páginas diferentes. Representa el inicio y el final de un programa. Llamada a subrutina. Llama a un proceso determinado o subrutina. Una subrutina es un módulo independiente del módulo principal, que realiza una tarea determinada y al finalizar regresa el control de flujo al módulo principal.
Subrutina
Tabla 2.2 Símbolos de los diagramas de flujo Problema 2.2: Ahora la tarea de la ardilla es que cambie las bellotas que están en la primera fila (ver figura 2.2.a) a la segunda y viceversa, dejándolas en la misma columna (ver figura 2.2.b). Las condiciones de inicio son: a) El mundo es conocido y sabemos exactamente dónde hay bellotas. b) La ardilla no tiene ninguna bellota en la boca al inicio. c) El mundo está encerrado por paredes y si la ardilla choca contra una se considerará un error garrafal. Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
34
Fundamentos de programación Programa Desarrollado
d) En este punto los científicos ya entrenaron a la ardilla para ejecutar la orden giraDerecha(), por lo tanto, ya puede ser usada en el algoritmo.
*
* *
*
*
*
*
*
* *
Estado inicial (a)
* *
Estado final (b)
Figura 2.2:Segundo mundo de la ardilla Análisis: De acuerdo con la figura 2.2, inciso a, para que la ardilla cumpla con su tarea debe realizar los siguientes pasos: recoger la bellota, girar a la derecha, avanzar, dejar la bellota, girar a la izquierda, avanzar, recoger la bellota, girar a la izquierda, avanzar, dejar la bellota, voltear a la derecha y avanzar. Hasta este punto las coordenadas de la ardilla son: primera fila y tercera casilla (volteando a la derecha, como al inicio). * * * *
*
*
Si la ardilla repite otra vez este bloque de instrucciones, logrará cambiar las siguientes dos bellotas; al repetirlo nuevamente cambiaría las últimas dos, salvo que cuando la ardilla avance después de haber dejado la bellota chocará contra la pared, por lo tanto, antes de que avance –última instrucción del bloque – tenemos que verificar que no haya pared. La condición para que la ardilla repita el bloque de instrucciones es que no haya pared. De lo anterior tenemos el siguiente algoritmo representado en diagrama de flujo.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
35
Fundamentos de programación Programa Desarrollado
Algoritmo 2.2. Solución problema 2.2 Actividad 1. Representación de algoritmos En esta actividad, reflexionarás sobre el uso de los diagramas de flujo y pseudocódigos a partir de varias preguntas. Posteriormente, ingresarás un comentario al respecto en el Foro Representación de algoritmos. Evidencia de aprendizaje. Planteamiento del problema Como primera evidencia de aprendizaje para esta unidad deberás elegir un problema que se pueda solucionar mediante un programa de computadora y realizarás la descripción precisa del mismo. 2.3. Estructuras de control Los primeros lenguajes de programación de alto nivel permitían realizar “saltos” a diferentes líneas del código mediante la instrucción GOTO, esto tiene el gran inconveniente que cuando se hacía una modificación en el programa, era necesario modificar todas las instrucciones GOTO para asegurar que
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
36
Fundamentos de programación Programa Desarrollado
los saltos se hicieran a las líneas de código correctas. Además de lo tedioso que podía ser estar corrigiendo el programa, las instrucciones GOTO lo hacían difícil de leer. En 1966 Corrado Böhm y Giuseppe Jacopini demostraron que “cualquier algoritmo puede diseñarse e implementar utilizando únicamente tres tipos de estructuras de control: secuenciales, condicionales y repetitivas; esto es, sin utilizar GOTO”(Böhm & Jacopini, 1966), basándose en este resultado, a principios de los años 70´s Edsger Dijkstra se dio cuenta que la forma en la que los lenguajes de programación de alto nivel podían modificarse sin problemas era eliminando las instrucciones GOTO (o similares), así que propuso un nuevo estilo de programación al que llamó programación estructurada, ésta incluye estructuras secuenciales, selectivas y repetitivas, conocidas como estructuras de control.
2.3.1. Estructuras secuenciales Las estructuras secuenciales son un bloque de instrucciones que se ejecutan una tras otra, en el mismo orden en el que están escritas. Un ejemplo de este tipo de instrucciones son todas las que se utilizaron en el algoritmo 2.1. Veamos otro ejemplo. Problema 2.3: Ahora la ardilla se enfrenta a un nuevo mundo (ver figura 2.3) en el que su tarea consiste en recoger las dos bellotas colocadas en la posiciones indicadas por la figura 2.3.a y llevarlas a la última casilla de la primera fila, como se muestra en la figura 2.3.b. Considerando que tenemos un mapa del nuevo mundo y sabemos en qué casillas están colocadas las bellotas diseñemos un algoritmo para que la ardilla realice su cometido.
**
* * Estado inicial (a)
Estado final (b)
Figura 2.3.Tercer mundo de la ardilla
Análisis: Nuevamente el problema planteado es muy sencillo de analizar, la ardilla debe hacer los movimientos que le permitan recoger la primera bellota, después ir por la segunda y llegar a la última casilla de la prime fila. Otra posible opción es que recoja la primera bellota, la lleve a la primera casilla, regrese por la segunda bellota y también la lleve a la primera casilla. Esta última opción requiere más Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
37
Fundamentos de programación Programa Desarrollado
esfuerzo por parte de la ardilla, dado que la ardilla no tiene limitado el número de bellotas que puede llevar en la boca, entonces la primera opción es más eficiente. El algoritmo quedaría como:
Inicio avanza() giraIzquierda() avanza() avanza() recogeBellota() giraIzquierda() avanza() giraDerecha() avanza() avanza() recogeBellota() avanza() dejaBellota() dejaBellota() Fin Algoritmo 2.3. Solución problema 2.3.
Las instrucciones selectivas, más usuales, que una computadora es capaz de realizar son: Imprimir, Leer y Asignar. La representación en diagrama de flujo de estas instrucciones se ilustra en la siguiente tabla, en cuanto que la representación en diagrama de flujo se utilizan los mismos verbos y símbolos pero encerrados entre un símbolo de proceso.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
38
Fundamentos de programación Programa Desarrollado
Tipo
Pseudocódigo
Asignación
<var> ← <Expresión>
Imprimir <mensaje/variable> Entrada Salida
Diagrama de flujo <var> ← <Expresión>
imprimir var/mens
y
leer Leer <variable>
variable
Descripción Asigna el valor de la expresión a la variable <var> Envía a pantalla un mensaje o el valor de la variable indicada. En caso de que se imprima un mensaje debe estar escrito entre comillas, si es el valor de una variable sólo se pondrá el nombre de la variable (sin comillas) Lee un dato del teclado y lo almacena en la variable indicada.
Tabla 2.3 Estructuras secuenciales 2.3.2 Estructuras selectivas En esencia, las estructuras selectivas se utilizan cuando la solución de un problema conlleva tomar una decisión, ya que se ejecuta un conjunto determinado de instrucciones dependiendo de si se cumple o no una condición en un momento determinado. Por ejemplo, la ardilla solamente puede avanzar si se no hay pared, en este caso la condición es no hayPared() y la acción que se realiza es avanza(). Revisemos el siguiente ejemplo: Problema 2.4: Nuevamente la ardilla está en el mundo lineal que se ilustra en la figura 2.4.a, tiene que recoger una bellota y llevarla a la última casilla como se muestra en la figura 2.4.b, sólo que ahora no sabe con precisión en que casilla está la bellota y la única información con la que cuenta es la siguiente: a) En el tablero hay una sola bellota. Las casillas donde puede estar son la tercera o la quinta, lo cual se representa con un círculo en la figura 2.4.a. b) Al inicio la ardilla no tiene ninguna bellota en la boca. c) Es un error ordenar a la ardilla que recoja una bellota en una casilla cuando esta no contiene nada pues la ardilla no sabrá que hacer. d) La ardilla ya ha sido entrenada para decir si hay bellota.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
39
Fundamentos de programación Programa Desarrollado
* Estado inicial (a)
Estado final (b)
Figura 2.4.Cuarto mundo de la ardilla Análisis: En este caso es necesario asegurarnos que en la casilla hay una bellota, antes de ordenarle a la ardilla que la recoja, para ello vamos a utilizar una estructura selectiva, como la ardilla ya fue entrenada para decir si hay una bellota, entonces esto lo utilizaremos como condición. Ya que tenemos dos posibles lugares dónde la ardilla puede encontrar la bellota, ordenaremos a la ardilla que avance hasta la tercera casilla, si hay una bellota entonces lo recoge y después la lleva a la última casilla, sino la ardilla avanza hasta la quinta casilla y ahí recoge la bellota, esto sin preguntar si ahí se encuentra pues una de las aseveraciones en el planteamiento del problema es que en el tablero hay una bellota, así que si éste no estaba en la tercera casilla es seguro que está en la quinta.
Inicio avanza() avanza() Si hayBellota() entonces recogeBellota() avanza() avanza() avanza() dejaBellota() Sino avanza() avanza() recogeBellota() avanza() dejaBellota() Fin Si-Sino Fin Algoritmo 2.4. La ardilla toma decisiones en un mundo lineal, versión 1
Observa que tanto en el primer caso (Si) como en el segundo (Sino) cuando la ardilla está en la quinta casilla y ya recogió la bellota, las siguientes órdenes es que avance y deje la bellota (ambas están remarcadas), de tal manera que podemos modificar el algoritmo de la siguiente forma: Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
40
Fundamentos de programación Programa Desarrollado
Inicio avanza() avanza() Si hayBellota() entonces recogeBellota() avanza() avanza() Sino avanza() avanza() recogeBellota() Fin Si-Sino avanza() dejaBellota() Fin Algoritmo 2.5. La ardilla toma decisiones en un mundo lineal, versión 2 También podemos utilizar la estructura Si dos veces, una para preguntar si la bellota está en la tercera casilla y otra para preguntar en la quinta, como se muestra en el siguiente algoritmo.
Inicio avanza() avanza() Si hayBellota() entonces recogeBellota() Fin Si avanza() avanza() Si hayBellota() entonces recogeBellota() Fin Si avanza() dejaBellota() Fin Algoritmo 2.6. La ardilla toma decisiones en un mundo lineal, versión 3
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
41
Fundamentos de programación Programa Desarrollado
A diferencia de los dos algoritmos anteriores, en éste la ardilla va a verificar en las dos casillas si hay bellota, aunque la haya encontrado en la primera opción, esto implica un poco más esfuerzo para la ardilla. Por otro lado, observa que en los algoritmos 2.4 y 2.5 se definieron instrucciones para el caso que se cumple la condición (Si) y para el caso que no (Sino); en cambio, en este último algoritmo sólo se ha definido un conjunto de instrucciones que se ejecuta si la condición se cumple, de no ser así no hay instrucciones específicas y la ardilla continuará realizando las siguientes instrucciones del algoritmo. Es importante destacar que ambas estructuras son equivalentes, es decir, que los problemas que se solucionan con una también es posible hacerlo con la otra. Existen tres tipos de estructuras selectivas que se clasifican de acuerdo al número de alternativas: a) Simples (Si): involucra un único bloque de instrucciones que se ejecuta sólo si una condición se cumple. b) Dobles (Si-Sino): abarca dos bloques de instrucciones, uno se ejecuta cuando la condición es verdadera y el otro cuando es falsa. c) Múltiples (Seleccionar): tiene más de dos bloques de instrucciones que se pueden ejecutar conforme al valor que tenga una variable, cada bloque equivale a un valor diferente. En la siguiente tabla se muestra la representación en pseudocódigo y diagrama de flujo de estas estructuras. Tipo
Pseudocódigo
Diagrama de flujo
Estructuras Si <condición> entonces selectivas <instrucciones> simples Fin_Si
Si <condición> entonces Estructuras <instrucciones V> selectivas Sino dobles <instrucciones F> Fin_Si-Sino
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
Descripción
Si la condición es verdadera, se ejecuta el conjunto de instrucciones.
Si la condición se cumple se ejecuta el conjunto de instrucciones V, en caso contrario se realizan las instrucciones F.
42
Fundamentos de programación Programa Desarrollado
Seleccionar <expresión> caso <valor1>: <instrucciones1> caso <valor2>: Estructuras <Instrucciones2> selectivas . múltiples . . otro: <instruccionesOtro> Fin_Seleccionar
Compara el valor de expresión con cada uno los valores correspondientes a cada caso, es decir cada valor K y sólo si son iguales realiza las instrucciones correspondientes.
Tabla 2.4 Estructuras selectivas En la unidad cuatro estudiaremos a mayor detalle cada una de estas estructuras. Actividad 2.Diseño de un algoritmo con estructuras selectivas Diseña un algoritmo, en pseudocódigo o diagrama de flujo, usando estructuras selectivas para resolver el problema que te proporcionará tu facilitador(a). 2.3.3. Estructuras repetitivas Las estructuras repetitivas, también llamadas ciclos, permiten ejecutar varias veces un bloque de instrucciones en función de una condición. Para ilustrar esto, volvamos al problema 2.1 del subtema 2.2.1; en este mundo la ardilla debe llevar una bellota desde la primera casilla hasta la última en un mundo lineal (ver figura 2.1). Observa que una vez que la ardilla recoge la bellota y está viendo de frente, debe avanzar una y otra vez mientras no se tope con la pared, esto se puede modelar con un ciclo de la siguiente manera.
Inicio recogeBellota() giraIzquierda() giraIzquierda() giraIzquierda() Mientras no (hayPared()) hacer avanza() Fin Mientras dejaBellota() Fin Algoritmo 2.7. Solución problema 2.1 utilizando ciclos
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
43
Fundamentos de programación Programa Desarrollado
Generalmente, un ciclo se utiliza cuando descubrimos un patrón, tal como se hizo en el análisis del problema 2.2. Si observas el algoritmo 2.2, verás que al final hay una flecha que regresa a la primera instrucción, representado con ello un ciclo. La presentación en pseudocódigo de este algoritmo sería la siguiente:
Inicio Mientras no(hayPared()) hacer recogeBellota() giraIzquierda() giraIzquierda() giraIzquierda() avanza() dejaBellota() giraIzquierda() avanza() recogeBellota() giraIzquierda() avanza() dejaBellota() giraIzquierda() giraIzquierda() giraIzquierda() Si no(hayPared()) entonces avanza() Fin Si Fin Mientras Fin Algoritmo 2.8:Solución del problema 2.2 utilizando ciclos La clave para utilizar un ciclo es identificar el conjunto de instrucciones que se deben repetir y la condición para que se ejecuten. Al igual que en las estructuras selectivas, existen diferentes estructuras repetitivas que se diferencian, principalmente, por el orden en el que se evalúa la condición. Éstas son: a) Mientras-hacer: en este ciclo primero se verifica que la condición sea verdadera y en tal caso se ejecuta el bloque de instrucciones y se repite nuevamente el ciclo. b) Hacer-Mientras: en esta estructura primero se realizan las instrucciones y después se verifica la condición, si se cumple se repite el ciclo. c) Desde-mientras: funciona igual que Mientras pero tiene asociada una variable que sirve como contador para controlar el número de veces que se repite un ciclo, de tal manera que la condición involucra al contador.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
44
Fundamentos de programación Programa Desarrollado
La representación en pseudocódigo y diagrama de flujo de estas estructuras se muestran en la siguiente tabla: Tipo
Ciclo Mientras (while)
Pseudocódigo
Diagrama de flujo
Mientras<condición>hac er <instrucciones>
Descripción Verifica si la condición se cumple, en tal caso ejecuta el conjunto de instrucciones y se vuelve a repetir el ciclo.
Fin_Mientras A diferencia del Mientras¸ esta estructura primero ejecuta el conjunto de instrucciones y después verifica que la condición se cumpla, en caso de ser verdadera se repite el ciclo.
Hacer Ciclo Hacer<instrucciones> Mientras (do while) Mientras <condición>
Desde <inicialización>mientras <condición>, <incremento/decremento Ciclo Desde> mientras (for) <instrucciones> Fin_Desde
Inicializa el valor del contador, verifica si la condición se cumple y en tal caso ejecuta las instrucciones, posteriormente incrementa o decrementa la variable contador.
Tabla 2.5 Estructuras repetitivas En la unidad 4 estudiaremos con mayor detalle cada una de estas estructuras.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
45
Fundamentos de programación Programa Desarrollado
Actividad 3: Diseño de un algoritmo con estructuras repetitivas Diseña un algoritmo, en pseudocódigo o diagrama de flujo, que resuelva el problema que te presentará tu facilitador(a) utilizando ciclos. Actividad de Autoevaluación Ingresa al aula virtual para realizar el cuestionario de autoevaluación. Consideraciones específicas de la unidad Como evidencias de la unidad se proponen dos problemas en el mundo de la ardilla, el primer algoritmo tendrás que realizarlo utilizando pseudocódigo en tanto que el segundo tendrás que representarlo en diagrama de flujo. Además de las instrucciones que aparecen en la tabla 2.1 puedes utilizar la instrucción giraDerecha() que hace que la ardilla de vuelta a la derecha. Referencias:
Böhm, C., & Jacopini, G. (1966). Flow diagrams, Turing machines, and languages only with two formation rules". Communications of the ACM, 9 (5), 366-371.
Cairó, O. (2005). Metodología de la programación: Algoritmos, diagramas de flujo y programas. México, D.F.: Alfaomega.
Joyanes, L., & Zohanero, I. (2005). Programación en C. Metodología, algoritmos y estructuras de datos. España: Mc Graw Hill.
Reyes, A., & Cruz, D. (2009). Notas de clase: Introducción a la programación. México, D.F.: UACM.
Viso, E., & Pelaez, C. (2007). Introducción a las ciencias de la computación con Java. México, D.F.: La prensas de ciencias, Facultad de Ciencias, UNAM.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
46
Fundamentos de programación Programa Desarrollado
Unidad 3: Introducción al lenguaje C Propósitos En esta unidad:
Distinguirás la estructura de un programa en lenguaje C. Declararás las variables y constantes que se utilizan en un algoritmo en lenguaje C Codificarás expresiones matemáticas en lenguaje C. Utilizarás funciones de la biblioteca estándar de C para codificar instrucciones de entrada y salida y funciones matemáticas. Utilizarás un entorno de trabajo de C para escribir, compilar y ejecutar programas escritos en C.
Competencia específica Utilizar el lenguaje de programación C para resolver problemas a través de la implementación de algoritmos secuenciales. Introducción En la unidad anterior se presentó un conjunto de instrucciones que una ardilla (ficticia) podría realizar y se mostró cómo, a través de éstas, la ardilla podía resolver varios problemas siempre y cuando se definiera un algoritmo. Ahora veamos qué relación hay entre el mundo de la ardilla y las computadoras: la ardilla representa la computadora, que sólo puede ejecutar un conjunto de instrucciones definidas; además, al igual que la ardilla, la computadora por sí misma es incapaz de resolver ningún problema, para hacerlo necesita un programa que pueda seguir (ejecutar) para obtener el resultado deseado, así como la ardilla necesitaba un algoritmo que le indicara cómo realizar una tarea específica. Por lo anterior, en esta unidad se mostrará la forma en que se crean programas en el lenguaje de programación C, desarrollado por Dennis M. Ritche en el año de 1972, en los laboratorios Bell de la AT&T, y que posteriormente fue estandarizado por un comité del ANSI (por sus siglas en inglés American National Standard Institute) dando lugar al ANSI C, a través del cual se garantiza que cualquier programa creado bajo este estándar pueda ser ejecutado en cualquier computadora (Kernighan & Ritchie, 1991). A lo largo de la unidad se introducen los elementos básicos del lenguaje de programación C: tipos de datos, variables y constantes, expresiones aritméticas, funciones matemáticas y funciones de entrada y salida, con el fin de empezar a crear programas secuenciales que resuelvan problemas simples. Como primer tema analizaremos la estructura del programa “hola mundo”, pues como ya es costumbre en programación es el primer programa que se realiza cuando se aprende un nuevo lenguaje de programación. A partir de este ejemplo se revisa la estructura de un programa y los elementos que lo integran.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
47
Fundamentos de programación Programa Desarrollado
3.1. Componentes de un programa En general, “un programa es una secuencia de instrucciones mediante las cuales se ejecutan diferentes acciones de acuerdo con los datos que se estén procesando (López, 2005)”. En la unidad 1 se explicó que un programa sólo puede ser ejecutado por una computadora solamente si está escrito en lenguaje de máquina, pero existen lenguajes de programación, que son fáciles de entender para los seres humanos, mediante los cuales se pueden escribir programas más legibles conocidos como programas fuentes –en C los programas fuente tiene extensión .c–, que son traducidos a lenguaje de máquina mediante compiladores o traductores. En el caso de C es un lenguaje compilado, por lo que se genera un programa ejecutable con extensión .exe, que puede ser ejecutado cada vez que se desee sin necesidad de volver a compilar el programa fuente, a menos que se realice algún cambio. De acuerdo con su creador un programa fuente en C, cualquiera que sea su tamaño, consta de funciones y variables. Una función contiene un conjunto de instrucciones, también llamadas preposiciones o enunciados, que especifican las operaciones que la computadora debe realizar; en tanto, las variables son los espacios de memoria donde se almacenan los valores utilizados en dichas operaciones(Kernighan & Ritchie, 1991, pág. 6). Como se ha mencionado, el primer programa que se debe escribir cuando se aprende un nuevo lenguaje es “hola mundo”, así que para no perder la tradición a continuación se muestra cómo se implementa este programa en lenguaje C.
/*Directivas de preprocesador*/ #include<stdio.h> /* Definición de función Principal */ main( ) { printf(“Hola mundo… \n”); }
Programa 3.1: hola.c El programa hola.c solo tiene una función: main; generalmente se puede dar cualquier nombre a las funciones que se definan en un programa, sin embargo, main es una función especial que siempre debe aparecer en algún lugar del programa, ya que es el punto desde el cual se inicia la ejecución (equivale a la instrucción de inicio de un algoritmo). Los paréntesis que aparecen después de la palabra main indican que se trata de una función; las instrucciones que forman parte de ésta, llamadas cuerpo de la función, van encerradas entre llaves “{ }”, señalando el inicio y fin de la misma, respectivamente.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
48
Fundamentos de programación Programa Desarrollado
Las instrucciones que comienzan con “/*” y terminan con “*/”, se llaman comentarios e indican que todo lo que está escrito entre esos símbolos no son instrucciones que la computadora debe ejecutar sino información de interés para el programador; por ejemplo la primera línea de código: /*Directivas de preprocesador*/ Otro tipo de instrucciones especiales son las directivas del preprocesador, que son instrucciones que se realizan antes de la compilación del programa, un ejemplo es: #include<stdio.h> Se distinguen porque inician con el carácter gato “#”, en este caso esta instrucción le indica al compilador que debe incluir la información que está definida en el archivo de biblioteca stdio.h, en el cual se encuentran todas las funciones de salida y entrada, como printf. Los compiladores de lenguaje C ofrecen distintas directivas, sin embargo las que utilizaremos son:
#define, que sirve para definir de constantes y/o macros #include, que se utiliza para incluir otros archivos
En el cuerpo de la función main, del programa 3.1, sólo aparece una instrucción que es la invocación a la función printf con el argumento “Hola mundo… \n”. printf(“Hola mundo… \n”); Invocamos o llamamos una función cuando requerimos que se ejecute con un conjunto de datos específicos, a los cuales llamamos argumentos. Una función se invoca o llama al nombrarla, es decir, escribiendo su nombre seguido de la lista de argumentos, separados por comas y encerrados entre paréntesis. En otras palabras, los argumentos son los valores que una función necesita para realizar la tarea que tiene encomendada, por ejemplo, la función printf tiene como fin imprimir la cadena de caracteres que recibe como parámetro, en este caso particular imprimirá la frase “Hola mundo…” seguida de un salto de línea, que es lo que representa la secuencia de caracteres “\n”. Actividad 1.Introducción al lenguaje C - Presentación Como sabes, la intención de esta asignatura es que aprendas a diseñar programas en C que te sean de utilidad para resolver problemas por medio de la computadora. Para lograrlo, es necesario que perseveres y practiques constantemente hasta habituarte en el manejo de los elementos de C; con ese propósito, durante toda esta Unidad y las que siguen, te presentaremos varios ejercicios que deberás realizar como complemento de las demás Actividades y Evidencias de Aprendizaje. Para conocer los detalles ingresa al aula virtual.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
49
Fundamentos de programación Programa Desarrollado
Actividad 1. Introducción al lenguaje C –Ejercicio A El primer ejercicio consiste en la elaboración del programa hola_mundo.c. Para conocer más detalles ingresa al aula virtual. 3.1.1. Instrucciones Una instrucción o enunciado en lenguaje C se puede definir como una expresión que tiene alguna consecuencia, generalmente la consecuencia se ve reflejada en el cambio del valor que está almacenado en las variables. De acuerdo con su estructura sintáctica se pueden clasificar en dos tipos: simples y compuestas. Las instrucciones simples se distinguen porque terminan con punto y como “;”. La sintaxis es: <instrucción>; Como ejemplo de instrucciones simples tenemos la declaración de variables, la llamada de funciones y la asignación. int x; x = 2*y; printf(“Hola”); En cambio las instrucciones compuestas son un conjunto de instrucciones que se escriben entre llaves “{…}”, para formar, lo que conocemos como, un bloque de instrucciones. La sintaxis es { <instrucción>; <instrucción>; … <instrucción>; } Un ejemplo de este tipo de instrucciones es el cuerpo de la función main, del programa 3.1.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
50
Fundamentos de programación Programa Desarrollado
3.1.2. Comentarios Los comentarios son textos que sirven como información al programador y no son procesados por el compilador, es decir, no son instrucciones que debe realizar la computadora y por lo tanto no son traducidos a lenguaje de máquina. Para que un texto sea comentario debe estar entre los símbolos /* (marca el comienzo) y*/ (marca el final de comentario).Pueden ir en cualquier parte del programa. Un buen programador debe comentar sus programas para que otras personas puedan entender la lógica del programa, e incluso, los comentarios también le sirven al programador cuando en un tiempo futuro requiera realizar cambios. También es recomendable incluir al inicio del programa: el nombre del programa, el nombre del programador, una breve descripción de la tarea que realiza, las fechas de creación y de la última modificación, todo esto encerrado entre comentarios. Por ejemplo, al inicio del programa 3.1 sería conveniente incluir el siguiente comentario: /* Programa: hola.c Programador: Pedro Pérez Descripción: El programa imprime la cadena “hola mundo” Fecha de creación: Agosto, 2010 Última modificación: Septiembre, 2010 */ Los comentarios también se pueden incluir al lado de una instrucción para describir de qué se trata, por ejemplo: printf(“Hola mundo”); /* Imprime el mensaje “Hola mundo” en la pantalla*/
3.1.3. Palabras reservadas Las palabras reservadas de cualquier lenguaje de programación, se llaman así porque tienen un significado especial para el compilador, el lenguaje C tiene 32 palabras reservadas (27 fueron definidas en la versión original y cinco añadidas por el comité del ANSI: enum, const, signed, void y volatile), todas ellas escritas con minúsculas.6 En la siguiente tabla se muestran todas las palabras claves o reservadas de lenguaje C.
666
En este punto es importante destacar que el lenguaje C distingue entre mayúsculas y minúsculas.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
51
Fundamentos de programación Programa Desarrollado
asm auto break case char const
continue float register struct default for return switch do goto short typedef double if signed union else int sizeof unsigned enum long static void Tabla 3.1: Palabras reservadas de C
volatile while
Una vez que se han descrito los diferentes elementos que integran un programa de lenguaje C, en la siguiente sección se describe la estructura general de un programa en C. 3.1.4. Estructura general de un programa Si observas el programa hola.c, la primera instrucción en el programa es la directiva al preprocesador, seguida de la función main y las instrucciones que la integran, esta estructura corresponde a los programas más simples, pero es similar a la de cualquier programa en C. La forma general de cualquier programa en C es la siguiente: <instrucciones para el preprocesador> <declaraciones globales> <tipo_devuelto> main(<lista de parámetros>) { <lista de instrucciones> } Y como se ha mencionado, se pueden incluir comentarios en cualquier parte del código. A continuación se presenta un programa que calcula el área de una circunferencia dada la medida de su radio.
/* Directivas del procesador (bibliotecas) */ #include<stdio.h> /* Declaraciones globales */ const float PI = 3.1416; /* Función Principal */ main( ) { /* Declaraciones de variables locales la función main*/ float radio, area; printf(" Calcula el area de una circunferencia\n");
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
52
Fundamentos de programación Programa Desarrollado
printf(" Ingresa el radio: "); scanf("%f", &radio); area = PI * radio * radio; printf(" Area = %.2f",area); getchar(); getchar(); }
Programa 3.2: areaCircunferencia.c Por el momento, basta con que observes la estructura del programa, que se hace evidente con los comentarios, el significado de cada una de las líneas de código se irá definiendo en las siguientes secciones. Para cerrar esta sección en la siguiente figura se muestra la ejecución del programa con la entrada radio=3.
Figura 3.2: Ejecución del programa areaCircunferencia.c utilizando Dev-C++ Actividad 1. Introducción al lenguaje C –Ejercicio B En esta ocasión, lo que tienes que hacer es escribir y compilar el programa en la computadora utilizando DevC++, posteriormente ejecútalo con diferentes valores para el radio e ingresa un comentario al respecto al Foro Introducción al lenguaje C. 3.2. Tipos de datos En la Unidad 1 se mencionó que todos los datos que son procesados por una computadora se almacenan en la memoria principal y, no importa de qué tipo sean, se representan por medio de unos y ceros, sin embargo, no todos se pueden representar con el mismo número de bits7, esto sí depende del tipo que se trate. Por ejemplo, los caracteres como: „a‟, „@‟,‟Z‟, entre otros, se representan utilizando 8 bits, en cambio para representar un número decimal se utilizan, al menos, 32 bits; por lo que cuando se crea un espacio de memoria es necesario indicar qué tipo de dato se desea almacenar ahí, para que se
7
Recuerda que un bit se definió como la unidad mínima de información, esto es, 1 ó 0.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
53
Fundamentos de programación Programa Desarrollado
reserve la cantidad de celdas de memoria que se necesitan y las operaciones que se pueden realizar con ellos. En general, los tipos de datos que existen, independientemente de un lenguaje de programación, se pueden clasificar de la siguiente forma: Enteros Decimales Lógicos (verdadero o falso) Alfanuméricos (caracteres) Unidimensionales Arreglos Multidimensionales Estructuras o registros Tabla 3.2: Tipos de datos
Simples
Estructurados
Numéricos
Por el momento, sólo nos enfocaremos en los tipos de datos simples definidos en el estándar de C, en la Unidad 5 se estudiarán los datos estructurados. En la siguiente tabla se muestran los tipos de datos simples en C: Tipo char
int
Float Double
Descripción Ejemplo Su tamaño equivale a ocho ´a´, bits, capaz de contener un ´C´, ´3´ carácter del conjunto de caracteres ASCII. Un entero, normalmente ocupa mínimo 16 bits, pero 1024, su tamaño es según la -258 máquina en que se ejecute. Número de punto flotante de 10.5, precisión normal. -11.6 Punto flotante precisión
de
doble
0.00045, -0.55236
Tabla 3.3: Tipos básicos en C
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
54
Fundamentos de programación Programa Desarrollado
Es posible aumentar o disminuir la capacidad de representación de los números utilizando los modificadores long, short y unsigned. De esta manera las combinaciones que se ajustan al estándar ANSI, junto con sus rangos mínimos, son:
Tipo Bits Rango Char 8 -127 a 127 unsigned char 8 0 a 255 signed char 8 -127 a 127 Int 16 -32767 a 32767 unsigned int 16 0 a 65535 signed int 16 -32767 a 32767 short int 16 -32767 a 32767 unsigned short int 16 0 a 65535 signed short int 16 -32767 a 32767 long int 32 -2147483647 a 2147483647 signed long int 32 -2147483647 a 2147483647 unsigned long int 32 0 a 4294967295 Float 32 seis dígitos de precisión Double 64 diez dígitos de precisión long double 64 diez dígitos de precisión Tabla 3.4: Tipos básicos y modificadores Una vez que conocemos lo tipos de datos que se pueden representar en lenguaje C, es conveniente saber cómo se reservan espacios de memoria donde son almacenados, esto es justo lo que se explica en el siguiente tema. 3.3. Variables y constantes Las variables y las constantes en lenguaje C se utilizan para almacenar valores, la diferencia que existe entre ellas es que el valor almacenado en una variable puede ser modificado en cualquier instante del programa en tanto que las constantes no pueden modificarse. Formalmente, una variable es un espacio de memoria que tiene asignado un nombre (también llamado identificador) y se utiliza para almacenar un valor que puede ser modificado durante la ejecución de un programa, a este valor que se encuentra almacenado en una variable en un momento dado se le llama estado de la variable. Por lo contrario, una constante es un dato cuyo valor se establecen en tiempo de compilación y no pueden cambiar durante la ejecución del programa. Existen dos tipos de constantes: literales y simbólicas. Las segundas, al igual que las variables, también tienen asignado un nombre. A lo largo de esta sección descubrirás cómo puedes construir variables y constantes en lenguaje C, así que lo primero será listar las reglas que debes seguir para nombrarlas.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
55
Fundamentos de programación Programa Desarrollado
3.3.1. Identificadores En lenguaje C hay una serie de restricciones en cuanto a los nombres o identificadores, ya sea de variables, constantes o funciones. Éstas son: a) Los identificadores se integran por letras y dígitos pero es necesario que el nombre siempre comience con una letra, por ejemplo: enteroA, arco3, S184. b) No puede contener caracteres especiales, por ejemplo, acentos (á,í), la letra eñe (Ñ), gato (#), guión (-). El carácter de subrayado “_”es el único carácter especial que puede utilizarse, generalmente se usa para darle una mejor legibilidad al nombre de una variable. Por ejemplo: entero_A, area_Circulo, i_elemento. c) El lenguaje C distingue entre letras mayúsculas y minúsculas, esto significa que los siguientes identificadores son distintos: area, Area, AREA. d) No pueden contener espacios en blanco. e) No pueden ser palabras reservadas. Aunque no es una regla, se recomienda que los identificadores sean significativos, es decir, que el nombre indique qué dato se está almacenando ahí. Ejemplo 3.1: 1) Se requiere una variable para almacenar el radio de un círculo Las opciones sugeridas son: radio, radioCirculo, radio_circulo. 2) Se requiere un identificador para una variable que almacene el promedio de ventas anuales de una tienda departamental. Opciones sugeridas: promedioVentas, prom_Ventas, promAnual. 3) Almacenar el número telefónico de una persona. Opciones sugeridas: tel, telefono. Una vez definidas las reglas de cómo escribir los nombres de las variables y los tipos básicos que pueden tener, estás listo para descubrir cómo se crean las variables en lenguaje C. A esta acción se le denomina declaración de variables.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
56
Fundamentos de programación Programa Desarrollado
3.3.2. Declaración e inicialización de variables La declaración de una variable es una instrucción que proporciona información de la variable al compilador, para que éste reserve en memoria el espacio adecuado y la referencia (identificador) para tener acceso a ella. Las declaraciones en general tienen la siguiente sintaxis: <tipo><identificador>; Donde <tipo> se refiere un tipo básico de C y el <identificador> se refiere al nombre con el cual se identificará el espacio de memoria reservado, puede ser cualquier nombre siempre y cuando se respeten las reglas vistas previamente.Veamos los siguientes ejemplos: int edad; /* declara una variable de tipo entero con el identificador edad*/ float area; /* declara una variable de tipo float a la cual identificará por area*/ También es posible declarar una lista de variables de un mismo tipo separando los nombres con comas “,” <tipo><identificador1>, … , <identificadorN>; Podemos ver un ejemplo de este tipo de declaración en el programa que calcula el área de una circunferencia (programa 3.2), cuando declaramos las variables locales a la función main float radio, area; Siempre es posible asignarles un valor inicial a las variables cuando las declaramos, a esta operación se conoce como inicialización. La sintaxis es: <tipo><identificador>=<valor>; Del mismo modo, podemos inicializar varias variables: <tipo><identificador1> = <valor1>, … , <identificadorN> = <valor2>; Para ilustrar esto, se presentan las siguientes instrucciones: int edad = 18; float radio = 3.0, area = 0.0; En la figura 3.2 se muestra una representación gráfica de estas declaraciones e inicializaciones, la columna de Dirección representa la dirección física de los registros en la memoria RAM y si ha sido
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
57
Fundamentos de programación Programa Desarrollado
asignada a una variable también se escribe su identificador, en contenido se muestra el dato que está almacenado en dicha dirección. El estado de una variable (memoria) hace referencia al valor que hay almacenado en un momento determinado.
MEMORIA Dirección Contenido 01 02 Edad 03 04 05 …
18
Dirección 51 Radio 52 53 54 Area
Contenido 3.0
0.0
55 56 Figura 3.2: Memoria y declaración e inicialización de variables
De lo anterior tenemos que: a la variable edad le corresponde la dirección de memoria 02 y su estado es 18; a la variable radio le corresponde la dirección 51 y su estado es 3.0; y por último, a la variable area le corresponde la dirección 54 y el estado es 0.0. 3.3.3. Tipos de constantes Las constantes son expresiones con un significado invariable, en un programa puede haber dos tipos de constantes: literales y simbólicas. Las constantes literales son valores de un determinado tipo escritos directamente en un programa y pueden ser de los siguientes tipos: a) Constantes numéricas, que son números representados en sistema decimal, algunas veces se estila escribir una letra que indique el tamaño o tipo de la constante numérica: Enteros: Por ejemplo 123, 2006, -38… Enteros Largos: Se consideran números enteros que superan un entero (int) generalmente valores mayores a 32,000; se le agrega los sufijos l ó L por ejemplo: 123456789L. Enteros sin Signo: Aquí se define que el valor de la constante se va a considerar como un número positivo o mayor a cero, en estos casos se agrega el sufijo U o u así por ejemplo podemos escribir: 123456789LU. Flotantes: Los valores numéricos que impliquen precisión decimal se pueden escribir de dos formas, la primera sería: 14324.983 o 3.1416. También se puede representar en representación
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
58
Fundamentos de programación Programa Desarrollado
exponencial (e-n), por ejemplo: 1.1434E2 o 1.1432e-5. También se ocupan los sufijos f o F y l o L para especificar los tipos double. Como puedes observar, las constantes reales con representación exponencial, tienen como valor una parte entera o real en forma decimal, seguida por la letra E, seguida de una constante entera, que se interpreta como exponente de la base 10. b) Constantes carácter, que se representada internamente por el lenguaje C como un número entero corto (short int). Una constante carácter siempre debe ir entre apóstrofes, por ejemplo: „x‟, „A‟. También existen constantes carácter que aparentan ser compuestas pero sólo son representaciones de caracteres de formato o caracteres especiales, y en C se les conoce como secuencias de escape. „\n‟ Salto de línea „\t‟ Tabulador „\b‟ Espacio hacia atrás „\f‟ Salto de página „\”‟ Comillas „\\‟ Barra invertida Tabla 3.5: Secuencias de escape c) Constantes cadena, que son una secuencia de caracteres entre comillas, incluyendo secuencias de escape, por ejemplo: “hola”, “hola mundo \n”. Por otro lado, las constantes simbólicas representan datos permanentes que nunca cambian. Ahondaremos en este tema en la siguiente sección. 3.3.4. Declaración de constantes En C existen dos formas de declarar una constante simbólica. La primera es utilizando la directiva de preprocesador #define, la cual asocia un identificador a un valor constante, sin reservar espacio en memoria, por lo que no podemos decir que se declara, sólo se define. La sintaxis general es la siguiente: #define<identificador><valor_constante> Por ejemplo: #define PI 3.1416
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
59
Fundamentos de programación Programa Desarrollado
Con esta instrucción cada vez que en el programa se escriba el identificador PI éste será sustituido por el compilador con el valor de 3.1416 (no se almacena el valor 3.1416 en ningún espacio de memoria sólo se hace una sustitución textual en el momento de compilación). La segunda forma de declarar una constante simbólica es reservando espacio de memoria que tenga la restricción de sólo lectura, para impedir que el valor sea cambiado, en este caso si la declaramos. La sintaxis general es similar a la forma de declarar una variable sólo que se antepone al tipo la palabra reservada const y es obligatorio asignar el valor. const<tipo><identificador> = <valor_constante>; Por ejemplo: const float PI = 3.1416 ; La directiva #define debe ser al principio del programa antes del main, en cambio, la declaración de una constante mediante const puede ser dentro o fuera de las funciones al igual que las declaraciones de variables. Se recomienda escribir el nombre de una constante con letras mayúsculas para diferenciarlas de las variables, pero las reglas son exactamente las mismas que para los identificadores de las variables. Evidencia de aprendizaje. Programa en C. Análisis del problema En la unidad anterior describiste el problema que resolverás a lo largo del curso, como evidencia de esta unidad debes realizar el análisis del problema, definiendo claramente los datos de entrada y la salida del programa junto con su tipo de datos, además debes considerar que los identificadores respeten las reglas de C. 3.4. Expresiones matemáticas Una expresión matemática puede ser un número, una variable, una constante o la combinación de operadores y todas las anteriores. Toda expresión al ser evaluada produce un valor. Se dividen en dos tipos de acuerdo al tipo de datos que devuelven cuando son evaluadas: expresiones aritméticas cuando el resultado de la evaluación es un número y expresiones booleanas cuando el resultado de la evaluación es un valor booleano (verdadero o falso). En este punto es importante destacar que el modo en que el lenguaje C maneja los valores booleanos es por medio de valores enteros: cero equivale a falso y cualquier entero distinto de cero representa verdadero. Las expresiones matemáticas permiten modelar situaciones reales, por ejemplo, mediante las expresiones aritméticas podemos modelar la forma de calcular el área de cualquier figura, también podemos representar la forma de calcular las raíces de un polinomio de segundo grado, o calcular el
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
60
Fundamentos de programaciĂłn Programa Desarrollado
monto de una venta, etc. En cambio las expresiones booleanas son la base para construir programas que pueden tomar decisiones. Veamos los siguientes ejemplos: Ejemplo 3.2: a) La hipotenusa es igual a la raĂz cuadrada de la suma de los cuadrados de catetos. ExpresiĂłn aritmĂŠtica: CodificaciĂłn en C:
đ?&#x2018;? â&#x2020;? đ?&#x2018;&#x17D;2 + đ?&#x2018;? 2 c =sqrt(a*a + b*b);
b) Âżx es un nĂşmero par? Sabemos que un nĂşmero es par si es divisible entre 2, en otras palabras, si el residuo de la divisiĂłn entre dos es cero, lo cual se puede expresar con el operador de mĂłdulo, que devuelve el residuo de una divisiĂłn. ExpresiĂłn booleana: CodificaciĂłn en C:
đ?&#x2018;Ľđ?&#x2018;&#x161;đ?&#x2018;&#x153;đ?&#x2018;&#x2018; 2 = 0 x % 2 == 0
En el siguiente subtema se presentan los operadores bĂĄsicos del lenguaje C, tanto aritmĂŠticos como booleanos. 3.4.1. Tipos de operadores Los operadores son palabras o sĂmbolos que hacen que permiten realizar operaciones con los datos de un programa, para cada tipo de datos hay una serie de operadores definidos. Entre todos los operadores se distingue el operador de asignaciĂłn â&#x20AC;&#x153;=â&#x20AC;?, que se puede leer como â&#x20AC;&#x153;guarda un valor en la variable indicadaâ&#x20AC;?, el valor puede ser una constante literal o el resultado de una expresiĂłn. Cabe seĂąalar que este operador en pseudocĂłdigo o diagrama de flujo lo hemos representado con una flecha apuntado hacia la izquierda â&#x2020;?. Veamos algunos ejemplos: radio = 3.0; /* modifica el estado de la variable radio con el valor 3.0*/ area = PI * radio *radio; /* modifica el estado de la variable por el resultado de evaluar la expresiĂłn PI * radio * radio */
Los operadores aritmĂŠticos definidos en C son: â&#x20AC;&#x153;+â&#x20AC;? (suma), â&#x20AC;&#x153;-â&#x20AC;? (resta), â&#x20AC;&#x153;*â&#x20AC;? (multiplicaciĂłn),â&#x20AC;&#x153;/â&#x20AC;? (divisiĂłn) y â&#x20AC;&#x153;%â&#x20AC;?(mĂłdulo). Este Ăşltimo representa el residuo de dividir dos nĂşmeros enteros, por ejemplo si realizamos
EducaciĂłn Superior Abierta y a Distancia â&#x20AC;˘ Ciencias Exactas, IngenierĂa y TecnologĂa
61
Fundamentos de programación Programa Desarrollado
la división de 6 entre 15 (15/6), el cociente es 2 y el residuo es 3, al aplicar el operador módulo a estos valores tenemos: 15 % 6 → 3 21 % 4 → 1 En C también existen los operadores de incremento “++” y decremento “--“, éstos tienen el efecto de aumentar o decrementar en una unidad el valor de una variable, supongamos que estamos trabajando con la variable x: x++;/* equivale a hacer: x = x + 1;*/ x--;/* equivale a hacer: x = x – 1;*/ Por ejemplo, si el valor de x es 5 el resultado de aplicar ++ y -- es: x++; → x--; →
6 4
Los operadores que permiten construir expresiones booleanas son: Operadores relacionales, que manipulan expresiones aritméticas y son:“>” (mayor que), “<” (menor que), “>=” (mayor o igual), “<=” (menor o igual), “==” (igual), “!=” (distinto) Operadores booleanos, también llamados lógicos, manipulan únicamente expresiones booleanas y son: “!” (negación), “||” (disyunción) y “&&” (conjunción). Observa que el operador de igualdad se escribe con dos símbolos de igualdad seguidos (==). El error más común es escribir una comparación con un sólo símbolo de igualdad, recuerda que (=) es el operador de asignación y su significado es totalmente distinto. En cuanto a los operadores booleanos, su significado es el siguiente:
Negación“!”, es un operador unario que cambia el valor de verdad de la expresión a la cual se le aplica. Por ejemplo, si el valor de verdad de expresión es verdadero entonces devuelve falso, y viceversa. Por ejemplo, si x=2, y=3, z=5. !(z > x ) → !(5 > 2 )→ !(1)→ 0 (falso) !(x > y ) → !(2 > 3 )→ !(0)→ 1 (falso) En pseudocódigo o diagrama de flujo se representa con la palabra en inglés NOT.
Conjunción“&&”, es un operador binario que se evalúa como verdadero sólo cuando las dos expresiones involucradas son verdaderas, en caso contrario devuelve falso. Por ejemplo, si evaluamos las siguientes expresiones en el estado x=2, y=3, z=5.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
62
Fundamentos de programación Programa Desarrollado
(x>y) && (z>y) → (2 > 3) && (5 > 3) → 0&&1 → 0 (falso) !(x > y) && (z>y) →!(2 > 3) && (5 > 3) → ! (0) &&1 → 1&&1 → 1 (verdadero) En pseudocódigo y diagrama de flujo se representa con la palabra en inglés AND.
Disyunción“||”, también es un operador binario que devuelve únicamente devuelve falso si los dos operadores son falsos, en caso contrario devuelve verdadero. Nuevamente, tomemos el mismo estado de las variables x=2, y=3, z=5. (x>y)||(z>y) (x>y)||(y>z)
→(2>3)||(5>3) →(2>3)||(3>5)
→ 0||1 → 0||0
→ 1 (verdadero) → 0 (falso)
En pseudocódigo y diagrama de flujo se representa con la palabra en inglés OR. En C existen otro tipo de operadores, sin embargo, su estudio supera los objetivos de este curso por lo que no los revisaremos, si deseas saber más puedes consultar (Joyanes & Zohanero, 2005).
3.4.2. Evaluación de expresiones La evaluación de las expresiones depende de tres cosas, principalmente, el estado de las variables que aparecen en la expresión, el significado de los operadores y su precedencia. Esta última se refiere a la prioridad de los operadores, es decir, el orden en el que se evalúan, eliminando con esto la ambigüedad de las expresiones, por ejemplo, si tenemos la expresión: 2+3*5 Podríamos evaluarla de dos diferentes formas: La primera es hacer primero la suma 2+3 (=5) y después multiplicar el resultado por 5. De tal manera obtendríamos como resultado final 25. Otra manera sería realizar primero la multiplicación 3*5 (=15) y sumar el resultado a 2, obteniendo 17 como resultado final. Pero sabemos que en matemáticas primero se realiza la multiplicación y después la suma, en otras palabras, tiene mayor prioridad la multiplicación que la suma. Por lo tanto, el resultado correcto de la expresión 2 + 3 * 5 es 17. En la siguiente tabla se muestra la precedencia de operadores de lenguaje C que se han presentado.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
63
Fundamentos de programaciĂłn Programa Desarrollado
Operadores Prioridad ( ) Mayor -(unario), ++, -*, /, % +, <, >, >= , <= ==, != &&, || = Menor Tabla 3.6: Prioridad de operadores Los operadores que se encuentran en el mismo nivel de precedencia se ejecutan de izquierda a derecha segĂşn aparecen en la expresiĂłn. Veamos el siguiente ejemplo: Ejemplo 3.3: Dada la siguiente expresiĂłn matemĂĄtica para convertir grados centĂgrados (C) a su equivalente Fahrenheit (F), 9 đ??š = đ??ś + 32 5 Su codificaciĂłn en C es: F= (9.0/5.0)*C +32; Se escribe 9.0 y 5.0 para que la divisiĂłn devuelva un nĂşmero flotante, de lo contrario la divisiĂłn serĂĄ entera. En este caso las variables F y C, deben ser declaradas como float. Evaluando, paso a paso, la expresiĂłn en el estado de la variable C = 30 tenemos: ExpresiĂłn actual F= (9.0/5.0)*C +32; F= (9.0/5.0)*30 +32; F= 1.8*30 +32; F= 54 +32; F= 86;
Estados de las variables C F 30 Âż? Igual al anterior Igual al anterior Igual al anterior C F 30 86
Observa que el Ăşnico operador que cambia el estado de una variable es el de asignaciĂłn â&#x20AC;&#x153;=â&#x20AC;?.
EducaciĂłn Superior Abierta y a Distancia â&#x20AC;˘ Ciencias Exactas, IngenierĂa y TecnologĂa
64
Fundamentos de programación Programa Desarrollado
Ejemplo 3.4: Ahora evaluemos la expresión: (x % 2 == 0) Considerando que el estado de la variable x=24 Expresión actual x % 2 == 0 0 == 0 1
Estados de las variables X 24 Igual al anterior Igual al anterior
En este caso la evaluación de la expresión no afecta el estado de la variable, esto es porque no contiene ningún operador de asignación, sin embargo podemos decir que el resultado de su evaluación es verdadero. Actividad de Autoevaluación. Unidad 3. Para esta actividad deberás ingresar al aula a resolver un cuestionario de opción múltiple que te ayudará a identificar qué tanto dominio tienes sobre los temas que hasta ahora has estudiado. 3.5. Bibliotecas y funciones El lenguaje C en realidad es un lenguaje reducido, en comparación con otros lenguajes de programación, por ejemplo, no tiene instrucciones de estrada y salida, y tampoco cuenta con operadores o funciones para calcular la raíz cuadrada de un número o su potencia, entre otras. Sin embargo, para compensar esto el lenguaje C ofrece un vasto conjunto de bibliotecas de funciones, que para fines prácticos se pueden considerar como parte de C. Cabe mencionar que también es posible definir nuevas bibliotecas, sin embargo, el lenguaje C tiene definidas diversas funciones de uso frecuente, que para fines de este curso son más que suficiente, por lo que este tema no se estudiará en esta ocasión.8 Las funciones que más se utilizan están agrupadas en bibliotecas estándar, declaradas como archivos de cabecera, de tal manera que para utilizarlas se debe incluir en el archivo utilizando la directiva #include seguida del nombre del archivo encerrado entre “<>”
Si deseas más información se te recomienda consultar (Joyanes & Zohanero, 2005).
8
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
65
Fundamentos de programación Programa Desarrollado
Las bibliotecas estándar que usaremos en este curso son: stdio.h en esta biblioteca se encuentran definidas las funciones estándar de entrada y salida – que representan la tercera parte de la biblioteca–, por ejemplo, declara la función printf que sirve para imprimir datos en pantalla y scanf que se utiliza para leer de datos ingresados mediante el teclado. stdlib.h incluye funciones para conversión numérica, asignación de memoria y tareas similares, llamadas funciones de utilería. En esta biblioteca se declara la función system mediante la cual se envían mensajes al sistema operativo para que ejecute una tarea. math.h declara funciones matemáticas, como la función sqrt que calcula la raíz cuadrada de un número. ctype.h declara funciones para prueba de clasificación de caracteres, por ejemplo, si es un dígito o un carácter. Observa que todas las bibliotecas estándar tienen extensión “.h”9 3.5.1. Funciones matemáticas La siguiente tabla muestra algunas de las funciones predefinidas en lenguaje C declaradas en la biblioteca math.h. Función Descripción sqrt(x) Raízcuadrada exp(x) Function exponencial fabds(x) Valor absoluto log(x) Logaritmoneperiano de x Log10(x) logaritmo decimal de x floor(x) Redondeohaciaabajo ceil(x) Redondeohaciaarriba sen(x) seno de x pow(x,y) Devuelve la potencia de x elevada a la y cos(x) coseno de x sin(x) seno de x tan(x) Tangente de x
Argumento Resultado Ejemplo flotante flotante sqrt(900) = 90 flotante flotante exp(2.0)= 2.718282 entero o flotante entero o flotante fabs(-5) = 5 entero o flotate flotante log(0.5) = -0.693 entero o flotante flotante Log10(0.5) = -0.301 flotante entero floor(6.5)=6 flotante entero ceil(6.5)=7 entero o real flotante sen(0.5) = 0 entero o flotante flotante pow(5,2) = 25 flotante flotante cos(0.5) = 1 flotante Flotante sin(0.0) = 0 flotante Flotante tan(0.0) = 0
Tabla 3.7: Funciones matemáticas Con esta información es posible codificar algoritmos que requieran este tipo de operaciones. Por ejemplo, la fórmula para calcular el área de una circunferencia, que se aparece en el programa 3.2. area = PI * radio * radio;
9
En (Kernighan & Ritchie, 1991) puedes consultar las funciones que están definidas en cada una de las bibliotecas estándar.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
66
Fundamentos de programación Programa Desarrollado
Se puede codificar de la siguiente manera: area = PI * pow(radio,2); 3.5.2. Funciones de entrada y salida En los programas que hemos visto aparece la función de salida estándar printf, que se encarga de imprimir un mensaje en la pantalla. La sintaxis general es: printf(<cadena_de_control>, <lista_de_identificadores>); Donde <cadena_de_control> representa el mensaje de texto que se desea desplegar en el monitor y siempre tiene que ir en comillas, opcionalmente puede incluir secuencias de escape o especificadores de control. Y <lista_de_identificadores> es una lista con los identificadores de las variables o las expresiones que serán desplegadas, separadas por comas. Las secuencias de escape se mostraron en la tabla 3.5. Los especificadores de conversión se utilizan para imprimir valores dentro de la cadena de control especificados por una variable, una constante o una expresión. En la siguiente tabla se muestran los que más se usan. Especificador %d %i %ld %f %lf %c %s
Acción Insertar un entero (int) Insertar un entero tipo (int) Insertar un entero tipo (long) Insertar un número flotante tipo (float) Insertar un número de tipo (double) Insertar un caracter (char)
Insertar una cadena(char [ ]) Tabla 3.8: Especificadores de conversión
Ejemplo 3.5: Suponiendo que el estado de las variables es radio=3 y area=28.27, printf(“El area del circulo con radio %d es %f \n”,radio,area); La salida de la instrucción anterior sería: El area del circulo con radio 3 es 28.27
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
67
Fundamentos de programación Programa Desarrollado
Observa que se imprime el texto tal cual pero en vez de imprimir el especificador de conversión %d se imprime el valor de la primera variable que es radio y en el lugar del especificador %f se imprime el valor del siguiente argumento que es la variable area. Ahora, si tenemos la instrucción: printf(“El perimetro es %.2f \n”, PI*2*radio); La salida sería: El perimetro es 18.85 En este caso en el lugar del convertidor %.2f se imprime el resultado de evaluar la expresión PI*2*radio que es el segundo argumento, el número .2 que aparece en el convertidor indica que sólo deben imprimirse dos decimales. En lenguaje C la lectura de datos por medio del teclado se realiza con la función scanf, en la cual se deben de especificar de ante mano los tipos de datos que se desea recibir, además de los identificadores de las variables donde se desean almacenar. La sintaxis de esta función es: scanf(<cadena_de_control>,<lista_de_direcciones_de_variables>); Donde <cadena_de_control> es una cadena con los códigos que controlarán la forma como se recibirán los datos desde teclado y la <lista_de_direcciones_de_variables> es una lista con las localidades de memoria de las variables donde se almacenarán los datos que el usuario del programa introduzca a través del teclado. Dos observaciones importantes: en la especificación de la cadena de control se utilizan los mismos especificadores de conversión que para la función printf encerrados entre comillas y en la lista de direcciones los identificadores de las variables, anteponiéndoles a cada uno un símbolo de amperson “&”, en el mismo orden que los especificadores de tipos que les corresponden. Ejemplo 3.6: Suponiendo que se desea leer la base y la altura de un rectángulo y guardarlas en las variables de tipo int llamadas basen y altura, de tal manera que el usuario ingrese los valores separados por una coma, digamos “5,2” entonces la instrucción sería: scanf(“%d,%d”, &base, &altura);
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
68
Fundamentos de programación Programa Desarrollado
Nota: Es frecuente que las personas olviden escribir el & antes del identificador de una variable, al utilizar la función scanf, cuestión que no es supervisada por el compilador y genera un error en el momento que se ejecuta el programa. Actividad 2. Funciones de entrada y salida Esta actividad consiste en diseñar un programa en C para resolver un problema dado, para conocer el problema y los detalles de la actividad, ingresa al aula virtual. 3.6. Codificación de algoritmos Para cerrar esta unidad desarrollemos un programa en C que resuelva el siguiente problema: Descripción del problema: Se requiere un programa que se encargue de la venta de boletos en un cine. El sistema debe calcular el monto que se debe pagar por una cantidad determinada de boletos tomando en cuenta que el costo de cada boleto es de 45 pesos. También se encargará de cobrar, es decir, dado el pago debe calcular el cambio indicando el tipo y número de billetes o monedas que devolverá de cada denominación. Para evitarse problemas de cambio, los ejecutivos de CineESAD han decidido no aceptar monedas de denominación menor a 1 peso y tampoco billetes de denominación mayor a 500 pesos. También se debe suponer que siempre hay suficientes billetes y monedas de cualquier denominación para devolver el cambio. Análisis: Los datos de entrada son el número de boletos (nboletos) y el monto del pago (pago), la salida del programa es el monto que se debe pagar por los boletos (total) y el monto del cambio (cambio), indicando el tipo y número de cada uno de los billetes o monedas que se devolverán. Notemos que el precio de los boletos siempre es el mismo, así que se puede declarar como una constante, llamémosla PRECIO. Así que para calcular el monto que el cliente debe pagar tenemos la siguiente fórmula: total = nboletos * PRECIO Y el monto del cambio se calcula con la siguiente fórmula: cambio = pago – total Para calcular cuántos billetes o monedas se tienen que devolver, se utilizarán los operadores de módulo y división. Por ejemplo, si el cambio es 360 se puede calcular el número de billetes de 100 dividiendo 360 entre 100, lo cual resulta ser 3 que corresponde al número de billetes, el resto del cambio es igual a 360 módulo 100, en este caso es 60.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
69
Fundamentos de programación Programa Desarrollado
Por último, los billetes sólo pueden ser de $500, $200, $100, $50 y $20 y las monedas sólo son de $10, $5, $2 y $1. Por el momento supondremos que el usuario siempre ingresa datos correctos. Diseño del algoritmo: En la siguiente tabla se muestra el algoritmo que resuelve el problema. Constantes: PRECIO = 45 Variables: nboletos: entero, representa el número de boletos que quiere el cliente. total: entero, es la cantidad de dinero que el cliente debe pagar. pago: entero, monto del pago del cliente. cambio: entero, monto del cambio. Inicio Imprimir “ Proporciona el número de boletos” Leer nboletos total = nBoletos * PRECIO Imprimir “Proporciona tu pago” Leer pago cambio = pago – total Imprimir “Tu cambio es”, cambio Imprimir “El número de billetes de 200 pesos es”, cambio/200 cambio = cambio módulo 200 Imprimir “El número de billetes de 100 pesos es”, cambio/100 cambio = cambio módulo 100 Imprimir “El número de billetes de 50 pesos es”, cambio/50 cambio = cambio módulo 50 Imprimir “El número de monedas de 10 pesos es”, cambio/10 cambio = cambio módulo 10 Imprimir “El número de monedas de 5 pesos es”, cambio/5 cambio = cambio módulo 5 Imprimir “El número de monedas de 2 pesos es”, cambio/2 cambio = cambio módulo 2 Imprimir “El número de monedas de 1 peso es”, cambio Fin
Algoritmo 3.1: ventaBoletos (pseudocódigo)
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
70
Fundamentos de programación Programa Desarrollado
Nota: Observa que no es necesario utilizar variables para el número de billetes o monedas de las diferentes denominaciones, pues sólo se utiliza una vez el resultado del cálculo así que se puede imprimir directamente el resultado del mismo. Para verificar que el algoritmo funciona, en la siguiente tabla se realiza una prueba de escritorio considerando que los datos de entrada son 5 boletos y el monto del pago son 500 pesos. En la primera columna aparece la instrucción que se ejecuta, en la siguiente el dato que suponemos se ingresa, después están las operaciones que se realizan en la ALU, en la cuarta columna se muestra los valores de las variables después de que se ha realizado la instrucción y en la última columna se indica el mensaje que se imprimirá en la pantalla, cuando sea el caso. Por otro lado, incluimos en la tabla de estado de la memoria la constante PRECIO sombreando el espacio correspondiente para indicar que no puede ser modificado.
Instrucción
Dato de entrada
Operaciones
Inicio
-
-
PRECIO 45
nBoletos -
total -
pago -
cambio -
-
-
-
PRECIO 45
nBoletos -
total -
pago -
cambio -
Proporciona el número de boletos
5
-
PRECIO 45
nBoletos 5
total -
pago -
cambio -
-
-
total = 5*45 =225
PRECIO 45
nBoletos 5
total 225
pago -
cambio -
-
-
-
PRECIO 45
nBoletos 5
total 225
pago -
cambio -
Proporciona tu pago
500
-
PRECIO 45
nBoletos 5
total 225
pago 500
cambio -
-
-
cambio = 500-225 = 275
PRECIO 45
nBoletos 5
total 225
pago 500
cambio 275
-
-
-
PRECIO 45
nBoletos 5
total 225
pago 500
Cambio 275
Tu cambio es 275
275/200 = 1
PRECIO 45
nBoletos 5
total 225
pago 500
Cambio 275
El número de billetes de $200 es 1
Imprimir “Proporciona el número de boletos”. Leer nBoletos total = nBoletos*PRECIO Imprimir “Proporciona tu pago” Leer nBoletos cambio = pago total Imprimir “Tu cambio es”, cambio. Imprimir “El número de billetes de $200 es”, cambio/200
-
Estado de la memoria (variables y constantes)
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
Dato de salida
71
Fundamentos de programación Programa Desarrollado
cambio = cambio módulo 200
-
cambio = 275 mod 200 =75
PRECIO 45
nBoletos 5
total 225
pago 500
Cambio 75
-
nBoletos 5
total 225
pago 500
Cambio 75
El número de billetes de $100 es 0
Imprimir “El número de billetes de $100 es”, cambio/100
-
75/100 = 0
PRECIO 45
cambio = cambio módulo 100
-
cambio = 275 mod 100 =75
PRECIO 45
nBoletos 5
total 225
pago 500
Cambio 75
-
Imprimir “El número de billetes de $50 es”, cambio/50
-
75/50= 1
PRECIO 45
nBoletos 5
total 225
pago 500
Cambio 75
El número de billetes de $50 es 1
cambio = cambio módulo 50
-
cambio = 75 mod 50 =25
PRECIO 45
nBoletos 5
total 225
pago 500
Cambio 25
-
Imprimir “El número de billetes de $20 es”, cambio/20
-
25/50= 0
PRECIO 45
nBoletos 5
total 225
pago 500
Cambio 25
El número de billetes de $50 es 0
cambio = cambio módulo 20
-
cambio = 25 mod 20 =5
PRECIO 45
nBoletos 5
total 225
pago 500
Cambio 5
-
nBoletos 5
total 225
pago 500
Cambio 25
El número de monedas de $10 es 0
Imprimir “El número de monedas de $10 es”, cambio/10
-
5/10= 0
PRECIO 45
cambio = cambio módulo 10
-
cambio = 5 mod 10 =5
PRECIO 45
nBoletos 5
total 225
pago 500
Cambio 5
-
-
5/5= 1
PRECIO 45
nBoletos 5
total 225
pago 500
Cambio 5
El número de monedas de $5 es 1
-
cambio = 5 mod 5 =0
PRECIO 45
nBoletos 5
total 225
pago 500
Cambio 0
-
-
0/2= 0
PRECIO 45
nBoletos 5
total 225
pago 500
Cambio 0
El número de monedas de $2 es 0
-
cambio = 0 mod 2 =0
PRECIO 45
nBoletos 5
total 225
pago 500
Cambio 0
Imprimir “El número de monedas de $5 es”, cambio/5 cambio = cambio módulo 5 Imprimir “El número de monedas de $2 es”, cambio/2 cambio = cambio módulo 2
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
-
72
Fundamentos de programación Programa Desarrollado
Imprimir “El número de monedas de $1 es”, cambio
-
Fin
-
-
PRECIO 45
nBoletos 5
total 225
pago 500
Cambio 0
El número de monedas de $1 es 0
-
PRECIO 45
nBoletos 5
total 225
pago 500
Cambio 0
-
Implementación: Por último, sólo queda codificar el algoritmo en lenguaje C.
/*
Descripción: Simulador de la caja de cobro de un cine.*/
/* Directivas al procesador */ #include<stdio.h>/* Funciones de entrada y salida */ #include<stdlib.h>/* Funciones del sistema */ /* Función Principal */ main( ) { /*Declaración de variables y constantes */ constint precio = 45; intnBoletos, total, pago, cambio; /*Mensaje de bienvenida*/ printf("********** Venta de boletos CineESAD************\n\n"); /*Datos de entrada*/ printf("Proporcione el numero de boletos que desea comprar:\t"); scanf("%d",&nBoletos); /*Calculamos el total de la venta*/ total = nBoletos*precio; printf("El total es *** %d pesos *** \n\n",total); /*Leemos el pago y calculamos el cambio*/ printf("Indique el monto de su pago: "); scanf("%d",&pago); /*Calculamos el cambio y lo devolvemos*/ cambio = pago - total; printf("\n\n El monto de su cambio es %d\n",cambio); printf("\n\t%d billetes de $200", cambio/200); cambio = cambio%200; printf("\n\t%d billetes de $100", cambio/100); cambio = cambio%100;
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
73
Fundamentos de programación Programa Desarrollado
printf("\n\t%d billetes de cambio = cambio%50; printf("\n\t%d billetes de cambio = cambio%20; printf("\n\t%d monedas de cambio = cambio%10; printf("\n\t%d monedas de cambio = cambio%5; printf("\n\t%d monedas de cambio = cambio%2; printf("\n\t%d monedas de
$50", cambio/50); $20", cambio/20); $10", cambio/10); $5", cambio/5); $2", cambio/2); $1", cambio);
printf("\n\nCineESAD le agradece su preferencia\n\n"); system("pause");/*hará una pausa antes de terminar la ejecución*/ }/*fin main*/
Programa 3.3: ventaBoletos.c El resultado de la ejecución del programa utilizando los mismos datos de entrada de la prueba de escritorio es:
Figura 3.3: Ejecución del programa ventaBoletos.c
Actividad 1. Introducción al lenguaje C –Ejercicio C Escribe, compila y ejecuta el programa ventaBoletos.c que acabamos estudiar e ingresa al foro para exponer tus comentarios al respecto. Consulta el aula para más detalles.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
74
Fundamentos de programación Programa Desarrollado
Actividad 3. Análisis, algoritmo y codificación de un programa en C Realiza el análisis, diseño e implementación de un programa que resuelva el problema que tu Facilitador(a) proporcionará. Utiliza lo aprendido hasta el momento para hacer el algoritmo.
Consideraciones específicas de la unidad Para continuar ejercitándote en el desarrollo de las habilidades en programación se te recomienda realizar más ejercicios, puedes consultar los libros (Joyanes & Zohanero, 2005) y (López, 2005).
Referencias:
Böhm, C., & Jacopini, G. (1966). Flow diagrams, Turing machines, and languages only with two formation rules". Communications of the ACM, 9 (5), 366-371.
Cairó, O. (2005). Metodología de la programación: Algoritmos, diagramas de flujo y programas. México, D.F.: Alfaomega.
Guerrero, F. (s.f.). mailxmail.com. Recuperado http://www.mailxmail.com/curso-introduccion-lenguaje-c
Joyanes, L., & Zohanero, I. (2005). Programación en C. Metodología, algoritmos y estructuras de datos. aspaño: Mc Graw Hill.
Kernighan, B., & Ritchie, D. (1991). El lenguaje de programción C. México: Prentice-Hall Hispanoamericana.
López, L. (2005). Programación estructurada en lenguaje C. México: Alfaomega.
Reyes, A., & Cruz, D. (2009). Notas de clase: Introducción a la programación. México, D.F.: UACM.
Villela, H. T. (20 de agosto de http://www.fismat.umich.mx/mn1/manual/.
2010).
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
el
15
Manual
de
de
8
C.
de
2010,
Obtenido
de
de
75
Fundamentos de programación Programa Desarrollado
Unidad 4: Estructuras de control Propósitos En esta unidad: Construirás expresiones booleanas para modelar situaciones reales. Diseñarás algoritmos para resolver problemas que impliquen la toma de decisiones, utilizando estructuras selectivas. Diseñarás algoritmos para resolver problemas que realicen una misma tarea varias veces usando estructuras repetitivas. Codificarás en lenguaje C algoritmos estructurados. Competencia específica Utilizar estructuras de control selectivas y repetitivas para resolver problemas simples a través del desarrollo de programas en lenguaje C. Introducción En la segunda unidad, mediante el mundo de la ardilla, aprendiste que cualquier algoritmo puede ser escrito utilizando únicamente tres tipos de instrucciones, conocidas como estructuras de control: secuenciales (cuando se ejecutan una tras otra), selectivas (cuando se ejecutan dependiendo de una condición) y repetitivas (que se ejecutan varias veces en función de una condición); su objetivo es controlar el flujo de ejecución de un programa, es decir, el orden en que se ejecutan las instrucciones. Considerando que en la unidad anterior diseñaste algoritmos secuenciales y los codificaste en lenguaje C, para obtener el programa deseado que diera solución al problema en cuestión, podemos decir que solamente te falta saber cómo funcionan y cómo se codifican en lenguaje C las otras dos estructuras para poder diseñar algoritmos estructurados. Así que esto es justamente el tema de esta unidad, aquí estudiarás con más detalle los tipos y funcionamiento de las estructuras selectivas y repetitivas, introducidas en la unidad 2. Para su mejor comprensión, esta unidad está dividida en dos partes: en la primera revisarás algunos problemas donde la solución implica tener que elegir el camino que se debe seguir para llegar al resultado deseado, los cuales se solucionan utilizando estructuras selectivas, por lo cual se analizarás a mayor profundidad el significado (semántica) de cada estructura y verás la forma de codificarla (sintaxis) en lenguaje C. La segunda parte está dedicada a las estructuras repetitivas, para las cuales se sigue la misma estrategia, verás cómo se pueden solucionar problemas utilizando este tipo de estructuras y también analizarás su semántica y aprenderás su sintaxis en lenguaje C. De esta manera, al finalizar la unidad podrás construir programas que incluyan cualquier tipo de estructura de control.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
76
Fundamentos de programación Programa Desarrollado
4.1. Estructuras selectivas Para diseñar programas capaces de tomar decisiones se requiere de las estructuras de control selectivas, también llamadas condicionales. Éstas llevan a cabo su función (controlar el flujo del programa) mediante una condición que se representa utilizando expresiones booleanas, de tal manera que cuando la condición se cumple (es verdadera) se ejecuta un conjunto de instrucciones definidas para este caso y, dependiendo del tipo de estructura, es posible que se ejecute otro conjunto de instrucciones distinto para el caso contrario (cuando la condición es falsa); e incluso, es posible definir diferentes conjuntos de instrucciones para valores distintos que pudiera tomar una variable. Es así que dependiendo de su estructura se han definido tres tipos: simples, dobles y múltiples. Para el estudio de cada estructura selectiva, a continuación, se dedican tres sub-secciones, una para cada una, en las cuales entenderás cómo funcionan y la forman en que se codifican en lenguaje C. 4.1.1. Estructura selectiva simple (if) La estructura de decisión simple, como su nombre lo indica, permite decidir entre ejecutar o no un bloque de acciones; en pseudocódigo se propuso la palabra reservada Si para su representación y en lenguaje C esta estructura se codifica mediante la sentencia de control if, tal como se muestra en la siguiente tabla. Pseudocódigo
Diagrama de Flujo
Código en C if(<condición>)
Si <condición> entonces <instrucciones> Fin Si
<instrucciones>
Tabla 4.1: Representaciones de la estructura condicional simple La <condición> puede ser cualquier expresión booleana y las <instrucciones>, llamadas cuerpo del Si (if), bien puede ser una sola instrucción o un bloque de instrucciones en cuyo caso van entre llaves {}. La manera en la que se ejecuta una instrucción Si (if) es la siguiente: se evalúa la condición que aparece entre paréntesis y si es verdadera (tiene un valor diferente de cero) entonces se ejecutan las instrucciones del cuerpo del Si (if), en caso de no serlo no se ejecuta y continúa el flujo de ejecución. NOTA: En lenguaje C, cuando el cuerpo de una estructura tiene más de una instrucción éstas deben ir encerradas entre llaves.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
77
Fundamentos de programación Programa Desarrollado
Para ilustrar las representaciones y el funcionamiento de la estructura selectiva simple se presenta el siguiente problema, con el algoritmo en pseudocódigo, el diagrama de flujo y el programa en lenguaje C. Problema 4.1: Se requiere un programa que lea un valor entre 0 y 360 y determine el tipo de ángulo, considerando que:
Angulo agudo: Mayor a cero y menor de 90 grados Angulo reto: Es igual a 90 grados Angulo obtuso: Es mayor que 90 pero menor a 180 grados Angulo llano: Es igual a 180 grados Angulo cóncavo: Es mayor a 180 pero menor a 360 grados
El análisis del problema se resume en la siguiente tabla. Análisis del problema
Datos de entada: ángulo
Salida: Mensaje 1: “Agudo” Mensaje 2: “Recto” Mensaje 3: “Obtuso” Mensaje 4: “Llano” Mensaje 5: “Cóncavo”
Método: Realizar comparaciones utilizando la estructura de selección simple para determinar el tipo de ángulo, se requiere una por cada tipo
Tabla 4.2: Análisis del problema 4.1 Lo primero que se requiere es leer el valor del ángulo, posteriormente, verificar de qué tipo es para imprimir el mensaje indicado. A continuación se muestra el algoritmo, tanto en pseudocódigo como en diagrama de flujo:
Inicio Imprimir "Ingrese la medida del angulo (grados): " Leer angulo Si angulo≤0 OR angulo≤360 entonces Imprimir “No tiene clasificación" Fin_Si Si angulo>0 AND angulo<90 entonces Imprimir "El ángulo es agudo" Fin_Si Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
78
Fundamentos de programación Programa Desarrollado
Si angulo=90 entonces Imprimir "El ángulo es recto" Fin_Si Si angulo>90 AND angulo<180 entonces Imprimir “El ángulo es obtuso" Fin_Si Si angulo =180 entonces Imprimir "El ángulo es llano" Fin_Si Si angulo>180 AND angulo<360 entonces Imprimir “El ángulo es concavo" Fin_Si Fin Algoritmo 4.1.a: Tipo de ángulo - pseudocódigo Observa que, para hacer más legible el algoritmo en pseudocódigo, se han dejado sangrías para indicar qué instrucciones forman el cuerpo de cada una de las estructuras Si y se han encerrado con un rectángulo, esto se adoptará para cualquier bloque de instrucciones que corresponda al cuerpo de una estructura.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
79
Fundamentos de programación Programa Desarrollado
Algoritmo 4.1.b: Tipo de ángulo – diagrama de flujo Para reafirmar el funcionamiento de la estructura condicional simple y verificar que el algoritmo propuesto sea correcto, en la siguiente tabla se muestra su ejecución paso a paso, tomando comodatos de entrada 120 grados.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
80
Fundamentos de programación Programa Desarrollado
Tabla 4.3: Prueba de escritorio del algoritmo 4.1
Al ejecutar paso a paso el algoritmo la única condición que satisface el estado de la memoria es la que sombreamos (angulo>90 AND angulo<180), por lo tanto, la única instrucción que se toma en cuenta es la del cuerpo del Si correspondiente. El último paso es la codificación. Observa que el cuerpo de cada una de las estructuras consta de una instrucción por lo tanto no es necesario encerrarla entre llaves {}. /* Programa: tipoAngulo.c Descripción: Determina el tipo de angulo (agudo, recto, obtuso, llano
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
81
Fundamentos de programación Programa Desarrollado
o cóncavo) */ #include<stdio.h> #include<stdlib.h> /* Función Principal*/ main () { /*Inicio de la función Principal*/ /*Declaración de variables */ intangulo; /*Mensaje de bienvenida*/ printf ("\nEste programa determina de que tipo es el angulo dado."); /*Instrucciones */ printf ("\n\nIngrese la medida del angulo (grados): "); scanf ("%d",&angulo); if (angulo<=0 || angulo>=360) printf ("\n No tiene clasificación"); if (angulo>0 &&angulo<90) printf ("\n El angulo es agudo"); if (angulo==90) printf ("\n El angulo es recto"); if (angulo>90 &&angulo<180) printf ("\nElangulo es obtuso"); if (angulo ==180) printf ("\n El angulo es llano"); if (angulo>180 &&angulo<360) printf ("\nElangulo es concavo"); printf ("\n\n\t"); system ("pause"); }
/*Fin de la función Principal*/ Programa 4.1: tipoAngulo.c
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
82
Fundamentos de programación Programa Desarrollado
A continuación se muestra la pantalla correspondiente a la ejecución del programa anterior introduciendo el mismo ángulo que se utilizó en la prueba de escritorio.
Figura 4.1: Ejecución del programa tipoAngulo.c Actividad 1. Estructuras de control –Ejercicio A Al igual que en la Unidad anterior, en esta ocasión, contarás con un foro para publicar y comentar tus actividades, las cuales te servirán de práctica para mejorar en el desarrollo de programas en C. Recuerda que estas actividades no necesitas enviarlas al (a la) facilitador(a), pero sí debes subirlas al Foro y comentar los aportes de tus compañeros(as). Para iniciar el trabajo en el foro realiza una prueba de escritorio del algoritmo que resuelve el problema 4.1 presentado en esta sección (algoritmo 4.1.a y algoritmo 4.1.b) considerando que el valor del ángulo es 98 grados. Posteriormente escribe, compila y ejecuta el programa tipoAngulo.c (programa 4.1) en la computadora con el mismo valor del ángulo. Finalmente, ingresa un comentario respecto a los resultados obtenidos. 4.1.2. Estructura selectiva doble (if-else) Las estructuras selectivas dobles nos permiten elegir alguna de dos posibles acciones a realizar dependiendo de la condición. En pseudocódigo se propone usar las palabras reservadas Si-Sino y en C se codifican mediante la sentencia if-else, tal como se muestra en la siguiente tabla. Pseudocódigo
Diagrama de Flujo
Si (<condición>) entonces <instruccionesV> sino <instruccionesF> Fin Si-Sino
Lenguaje C if(<condición>) <instruccionesV> else <instruccionesF>
Tabla 4.4: Representaciones de la estructura condicional doble
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
83
Fundamentos de programaciĂłn Programa Desarrollado
Al igual que en la estructura selectiva simple, la <condiciĂłn> representa una expresiĂłn booleana y, las <instruccionesV> y <instruccionesF> puede ser una o varias, a las primeras se les llama cuerpo del Si (if) y las segundas son el cuerpo del Sino (else). Esta estructura de control ejecuta sĂłlo uno de los dos cuerpos de instrucciones: cuando la condiciĂłn es verdadera se ejecutan las <instrucciuonesV> y en caso contrario se ejecutan las <instruccionesF>. En el desarrollo del siguiente problema se ejemplifican las representaciones y el funcionamiento de ĂŠsta estructura. Problema 4.2: Se requiere un programa que simule el cĂĄlculo y muestre las raĂces reales para una ecuaciĂłn de segundo grado de la forma: đ?&#x2018;&#x17D;đ?&#x2018;Ľ 2 + đ?&#x2018;?đ?&#x2018;Ľ + đ?&#x2018;? = 0. Para resolver este problema se utilizarĂĄ la fĂłrmula general: đ?&#x2018;Ľ=
â&#x2C6;&#x2019;đ?&#x2018;? Âą đ?&#x2018;? 2 â&#x2C6;&#x2019; 4đ?&#x2018;&#x17D;đ?&#x2018;? 2đ?&#x2018;&#x17D;
Por lo que los datos que requerimos son los coeficientes de la ecuaciĂłn (a, b y c) y el resultado deseado serĂĄn las raĂces. TambiĂŠn se debe considerar que un polinomio tenga raĂces reales se debe cumplir la condiciĂłn:
đ?&#x2018;? 2 â&#x2030;Ľ 4đ?&#x2018;&#x17D;đ?&#x2018;? De lo contrario el resultado de la raĂz cuadrada serĂa un nĂşmero imaginario. Para esto se propone una estructura selectiva doble para verificar que existan raĂces reales. El algoritmo en pseudocĂłdigo es el siguiente:
Inicio Imprimir â&#x20AC;&#x153;Ingresa los coeficientes a, b y c:â&#x20AC;? Leer a, b, c detâ&#x2020;?đ?&#x2018;? 2 â&#x2C6;&#x2019; 4đ?&#x2018;&#x17D;đ?&#x2018;? Si (det â&#x2030;Ľ 0 ) entonces x1â&#x2020;? x2 â&#x2020;? Imprimir â&#x20AC;&#x153;Las raĂces son: â&#x20AC;?, x1 , x2
EducaciĂłn Superior Abierta y a Distancia â&#x20AC;˘ Ciencias Exactas, IngenierĂa y TecnologĂa
84
Fundamentos de programaciĂłn Programa Desarrollado
Si no Imprimir â&#x20AC;&#x153;No existen raĂces realesâ&#x20AC;? Fin_Si-Sino Fin Algoritmo 4.2.a: EcuaciĂłn de segundo grado - pseudocĂłdigo Observa que en el algoritmo se utiliza la variable auxiliar det, la razĂłn es porque el cĂĄlculo del determinante (đ?&#x2018;? 2 â&#x2C6;&#x2019; 4đ?&#x2018;&#x17D;đ?&#x2018;?) se emplea en mĂĄs de un lugar del algoritmo, por lo tanto, se recomienda guardar este resultado para no volverlo a calcular. Ahora, la representaciĂłn del mismo algoritmo en diagrama de flujo se muestra a continuaciĂłn.
Algoritmo 4.2.b: EcuaciĂłn de segundo grado â&#x20AC;&#x201C; diagrama de flujo Para validar el algoritmo, veamos su ejecuciĂłn paso a paso con el polinomio đ?&#x2018;Ľ 2 + 5đ?&#x2018;Ľ + 4 = 0.
EducaciĂłn Superior Abierta y a Distancia â&#x20AC;˘ Ciencias Exactas, IngenierĂa y TecnologĂa
85
Fundamentos de programación Programa Desarrollado
Tabla 4.5: Prueba de escritorio del algoritmo 4.2 Para la codificación en lenguaje C se debe notar que el cuerpo del Si (if) tiene un bloque de tres instrucciones, por lo que deberán ir encerradas entre llaves {}, en cambio el cuerpo del Sino (else) sólo tiene una instrucción por lo que no son necesarias. /* Programa: ecuacion.c Descripción: Solución de ecuaciones de segundo grado utilizando */ /* Bibliotecas */ #include<stdio.h>/* Biblioteca de entrada y salida estándar */ #include<stdlib.h>/* Biblioteca para las funciones del sistema */ #include<math.h>/* Biblioteca para utilizar funciones matemáticas: pow para calcular la potencia sqrt para calcular la raíz cuadrada*/ /* Función Principal*/ main ( ) { /*Declaración de variables */ double a, b, c, x1, x2, det; /* Mensaje de bienvenida */ printf("El siguiente programa calcula grado\n"); printf("\n\t\t ax^2 + bx + c = 0");
las
raices
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
de
un
polinomio
de
segundo
86
Fundamentos de programaciĂłn Programa Desarrollado
/* Datos de entrada */ printf ("\nIntroduzca los coeficientes de a,b y c:"); scanf ("%lf,%lf,%lf",&a,&b,&c); det = pow (b,2)-4*a*c; /* Verificamos if (det>= 0) { x1=(-b x2=(-b printf } else printf printf system }
que la ecuaciĂłn tenga raices reales */
+ sqrt(det))/2*a; - sqrt(det))/2*a; ("\n La raices son: %.2lf, %.2lf",x1, x2);
("\nNo existen raices reales."); ("\n"); ("pause");
Programa 4.2: ecuacion.c La ejecuciĂłn del programa con los mismos datos de entrada de la prueba de escritorio es la siguiente.
Figura 4.2: EjecuciĂłn del programa ecuacion.c
Actividad 1. Estructuras de control â&#x20AC;&#x201C;Ejercicio B Realiza una prueba de escritorio del algoritmo que resuelve el problema 4.2 considerando la ecuaciĂłn 2đ?&#x2018;Ľ 2 + 5đ?&#x2018;Ľ + 3 = 0. Enseguida escribe y compila el programa ecuacion.c (programa 4.2) en la computadora y ejecĂştalo con la misma ecuaciĂłn para verificar los resultados. Ingresa un comentario respecto a los resultados obtenidos en el Foro Estructuras de control y discute si es posible resolver este problema utilizando estructuras selectivas simples.
EducaciĂłn Superior Abierta y a Distancia â&#x20AC;˘ Ciencias Exactas, IngenierĂa y TecnologĂa
87
Fundamentos de programación Programa Desarrollado
4.1.3. Estructura selectiva múltiple (switch-case) Las estructuras selectivas múltiples permiten escoger uno de varios caminos posibles. Para la estructura condicional múltiple se proponen las palabras clave Seleccionar-caso en pseudocódigo, misma que se implementa en lenguaje C utilizando las palabras reservadas switch-case. Esta secuencia se utiliza cuando existen múltiples posibilidades para la evaluación de una expresión matemática (generalmente una variable), pues de acuerdo al valor que tome la expresión será el conjunto de instrucciones que se ejecute. Pseudocódigo Casos para<expresión> caso<valor1>: <instruccionesCaso1> caso<valor2>: <instruccionesCaso2> … otros casos: <instruccionesOtros> Fin_Casos
Lenguaje switch (<expresión>) { case<valor1>: <instrucciones1>; break; case<valor2>: <instrucciones2>; break; default: <instruccionesOtras> } Diagrama de Flujo
Tabla 4.6: Representaciones de la estructura condicional múltiple En este caso la <expresión> no es booleana sino aritmética y de tipo entero, así cada caso corresponde a un valor que puede resultar de su evaluación. De esta forma, el flujo de control que sigue la ejecución de una instrucción Seleccionar-casos (switch-case) es el siguiente: se evalúa la <expresión> y si el valor corresponde al valor de un caso, es decir a un <valori>, se ejecuta el bloque de <instruccionesi> hasta encontrar el final de la instrucción, que en el caso de C está representado por la palabra reservada break, terminando ahí la ejecución de la instrucción. Cuando el valor no corresponde a ningún caso se ejecuta el bloque de instrucciones correspondiente a otros casos (default). El
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
88
Fundamentos de programación Programa Desarrollado
conjunto de todos los casos, incluyendo el default, conforman el cuerpo de la estructura Seleccionarcasos (switch-case). Problema 4.3: Se requiere un programa que dada una calificación con número despliegue un mensaje, de acuerdo con la siguiente información: 0-6: Reprobado 7: Suficiente, Aprobado 8: Bien, Aprobado 9: Notable, Aprobado 10: Sobresaliente, Aprobado En este caso es conveniente utilizar una estructura selectiva múltiple, en donde la expresión que se evalúe sea la calificación del estudiante y se defina un caso por cada una de las calificaciones posibles. Es claro, que la entrada únicamente es la calificación y la salida es el mensaje correspondiente. De lo anterior el algoritmo en pseudocódigo y diagrama de flujo quedaría de la siguiente forma. Inicio Imprimir “ Inserte una calificación: " Leer nota Seleccionar (nota) caso 0: caso 1: caso2: caso 3: caso 4: caso 5: caso 6: Imprimir “Reprobado" caso 7: Imprimir "Suficiente, Aprobado" caso 8: Imprimir "Bien, Aprobado" caso 9: Imprimir “Notable, Aprobado” caso 10: Imprimir “Sobresaliente, Aprobado” otros casos: Imprimir "Esa nota es incorrecta" Fin_Casos Fin Algoritmo 4.3.a: Conversión de calificación numérica a letra - pseudocódigo
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
89
Fundamentos de programaciĂłn Programa Desarrollado
Algoritmo 4.3.b: ConversiĂłn de calificaciĂłn numĂŠrica a letra â&#x20AC;&#x201C; diagrama de flujo Observa que tanto en el diagrama de flujo como en el algoritmo, hay siete casos (0 â&#x2030;¤ đ?&#x2018;&#x203A;đ?&#x2018;&#x153;đ?&#x2018;Ąđ?&#x2018;&#x17D; â&#x2030;¤ 6) en los que la instrucciĂłn a ejecutar es la misma, por lo que se agrupan, mĂĄs no se puede poner una condiciĂłn que los contenga, como se harĂa en las estructuras vistas en las subsecciones anteriores, asĂ que en el pseudocĂłdigo se especifica cada valor antecedido por la palabra caso pero sĂłlo se escribe una vez la instrucciĂłn y, de manera similar, se listan todos los valores. Para aclarar el funcionamiento de esta estructura y verificar si el algoritmo funciona adecuadamente, en la siguiente tabla se muestra una prueba de escritorio cuando la nota es igual a 8.
EducaciĂłn Superior Abierta y a Distancia â&#x20AC;˘ Ciencias Exactas, IngenierĂa y TecnologĂa
90
Fundamentos de programación Programa Desarrollado
Tabla 4.7: Prueba de escritorio del algoritmo 4.3 Es importante señalar que, a diferencia de las estructuras anteriores, el cuerpo de una estructura selectiva múltiple siempre debe ir encerrado entre llaves {} cuando se codifica en C, más no así las instrucciones que se definen para cada caso, ya que estás se acotan por las palabra reservadas case y break, por tal motivo no debes olvidar escribir el break al final de cada caso de lo contrario también se ejecutarán las instrucciones de los casos que aparezcan después.
/* * * * * * *
Programa: calificacion.c Descripción: Dada una calificación con número despliega un mensaje 0,1,2,3,4,5,6 - Reprobado 7 - Suficiente, Aprobado 8 - Bien, Aprobado 9 - Notable, Aprobado 10 - Sobresaliente, Aprobado*/
#include<stdio.h> #include<stdlib.h> /*Función principal*/ main() { /*Declaración de variables*/ int nota;
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
91
Fundamentos de programación Programa Desarrollado
/*Mensaje de bienvenida */ printf("\nEl siguiente programa lee una calificacion con \ndetermina que tipo de calificacion es\n"); /*Datos de entrada*/ printf("\nInserte una calificacion numérica: "); scanf("%d",&nota); /*Comparación*/ switch(nota) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: printf("\n\n\t\"Reprobado\""); break; case 7: printf("\n\n\t\"Suficiente, Aprobado\""); break; case 8: printf("\n\n\t\"Bien, Aprobado\""); break; case 9: printf("\n\n\t\"Notable, Aprobado\""); break; case 10: printf("\n\n\t\"Sobresaliente, Aprobado\""); break; default: printf("\n\n\t\"Esa nota es incorrecta\""); } printf ("\n\n\t\t"); system ("pause"); } Programa 4.3: calificacion.c
número,
En la siguiente figura se muestra la ejecución de este programa con el valor de entrada igual a 8.
Figura 4.3: Ejecución del programa calificacion.c
A lo largo de esta sección has estudiado los tres tipos de estructuras selectivas y por medio de los ejemplos presentados te has dado cuenta de la importancia y utilidad de estas estructuras, sin ellas
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
92
Fundamentos de programación Programa Desarrollado
sería imposible construir programas que implicaran la toma de decisiones. Sin embargo, todavía existen problemas que requieren de otro tipo de estructuras que permitan repetir una tarea un número determinado de veces, la siguiente sección está dedicada a este tema. Actividad 1. Estructuras de control –Ejercicio C Realiza una prueba de escritorio del algoritmo que resuelve el problema 4.3 presentado en esta sección (algoritmo 4.3.a y algoritmo 4.3.b) considerando que el valor de entrada es igual a 10. Después escribe y compila el programa calificacion.c (programa 4.3) en la computadora y ejecútalo con el mismo valor para comparar el resultado. Finalmente, reflexiona si es posible resolver el problema planteado utilizando estructuras selectivas simples o dobles e ingresa tu comentario en el Foro Estructuras de control Actividad 2: Estructuras selectivas Realiza el análisis, diseño e implementación de un algoritmo que resuelva el problema que se te presenta mediante el uso de las estructuras selectivas, para conocer el problema y los detalles de la actividad, ingresa al aula virtual.
4.2. Estructuras repetitivas En la mayor parte del diseño o implementación de las soluciones que se plantea a problemas específicos nos encontramos con instrucciones que deben ejecutarse un número determinado de veces, si hacemos un análisis más profundo de estas situaciones, en la mayorías de las ocasiones nos encontramos que las instrucciones son las mismas, pero que los datos varían, esto se hace posible utilizando las estructuras repetitivas, generalmente llamadas ciclos. Existen varias estructuras de repetición implementadas por los diferentes lenguajes de programación, todas con la misma idea: repetir un conjunto de instrucciones, llamadas cuerpo del ciclo, dependiendo de condición. En la mayoría de los ciclos el cuerpo se repiten siempre y cuando la condición se cumpla, sin embargo, también existe una estructura repetitiva que se repite en tanto que no se cumple la condición. En esta sección sólo nos enfocaremos en las primeras que son las que están definidas en el lenguaje C y en la mayoría de los lenguajes estructurados y orientados a objetos actuales. Cabe mencionar que a cada una de las veces que se repite el ciclo se le conoce como iteración. Cuando se utilizan ciclos dentro de un programa, te puedes enfrentar a dos posibles situaciones: Que conozcas desde el diseño cuántas veces deben repetirse las instrucciones (repetición definida), Que el número de veces que se deban repetir las instrucciones dependa de un valor que se conoce hasta el momento de la ejecución del ciclo (repetición indefinida).
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
93
Fundamentos de programación Programa Desarrollado
En el primer caso se necesitará una variable que funja como un contador, en la cual se registre el número de iteraciones que se vayan ejecutando. En cambio, en las repeticiones indefinidas generalmente se controlan mediante interruptores o banderas, o bien, con valores centinela. Con los anterior puedes darte cuenta que para las estructuras de control repetitivas es muy importante el uso de variables auxiliares y que por la frecuencia con la que se utilizan dentro de un algoritmo y por la función que realizan dentro del mismo toman un nombre especial: contadores, acumuladores e interruptores. Un contador es una variable comúnmente de tipo entero destinada a almacenar un valor que se irá incrementando o decrementando en una cantidad constante. Se suelen utilizar mucho en procesos repetitivos definidos, para contabilizar el número de veces que se repite un conjunto de acciones o eventos, es decir en los cuerpos de las instrucciones repetitivas. Sobre una variable contadora se realizan dos operaciones básicas: inicialización e incremento o decremento, según sea el caso. Todo contador se debe inicializar con un valor inicial (0, 1...) contador = Valor_Inicial Cada vez que aparezca el evento a contar se ha de incrementar o decrementar en una cantidad fija (I, D respectivamente) el valor del contador. contador = contador+ I; contador = contador- D; Los contadores más utilizados tienen incrementos o decrementos de uno en uno, es por ello que la simplificación de dichas expresiones es: Expresión contador=contador +1; contador=contador -1;
Expresión Simplificada en lenguaje C contador++ contador--
En contraste, un interruptor o bandera es una variable que puede tomar dos posibles valores a lo largo de la ejecución del programa, éstos son: 1 (encendido/abierto) y 0 (apagado/cerrado), de ahí su nombre. Y se utilizan principalmente para registrar la ocurrencia o no de un suceso. Por último, un acumulador es una variable cuyo objetivo es acumular cantidades sucesivas obtenidas al realizar la misma operación. El uso más habitual de un acumulador es obtener sumas y productos. Al igual que con los contadores, para poder utilizar un acumulador hay que realizar sobre ellos dos operaciones básicas: inicialización e incremento.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
94
Fundamentos de programación Programa Desarrollado
En el caso de obtener sumas el acumulador se inicializa en cero y en el caso de los productos en uno, para no afectar el resultado. SumaTotal=0; ProductoFinal=1; Una vez obtenido y almacenado en una variable la cantidad a acumular la añadimos a la variable acumulador:
Variable Acumulador
SumaTotal ProductoFinal
= =
SumaTotal ProductoFinal
Cantidad a Acumular
+ *
cantidad; cantidad;
En resumen, los contadores permiten llevar la cuenta del número de iteraciones que se realizan en un ciclo (definido o indefinido), y en el caso específico de ciclos definidos son el medio por el cual se controla el fin del ciclo. Por otro lado los acumuladores nos permiten guardar resultados parciales de operaciones que se realizan como parte del cuerpo de un ciclo (puede ser definido o indefinido). En este punto, es importante señalar que en lenguaje C hay tres diferentes estructuras repetitivas: while (Mientras-hacer), for (Desde-mientras) y do-while (Hacer-mientras), con todas ellas es posible modelar ciclos definidos o indefinidos, pues las tres son equivalente, es decir, cualquiera de ellas se puede expresar en términos de las otras. En los siguientes subtemas estudiarás a profundidad cada una de ellas y verás su equivalencia. 4.2.1. Estructura Mientras (while) La estructura repetitiva Mientras, codificada en lenguaje C con la palabra reservada while, controla las repeticiones a partir de una condición que se evalúa al inicio del ciclo, de esta manera en cada iteración primero se evaluará la condición y mientras resulte verdadera se repetirá el ciclo. En la siguiente tabla se muestran las representaciones del ciclo Mientras (while).
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
95
Fundamentos de programación Programa Desarrollado
Pseudocódigo Mientras
Diagrama de Flujo
Lenguaje C while (<condición>)
<condición>hacer
<instrucciones> Fin mientras
Condición
F <instrucciones>;
V instrucciones
Tabla 4.8: Representaciones de la estructura repetitiva Mientras (while) La manera en la que se ejecuta una instrucción Mientras (while) es la siguiente: las <instrucciones> del cuerpo del ciclo se ejecutan mientras la <condición> es verdadera, cuando esto no se cumple se termina el ciclo; de esta forma, si la primera vez que se evalúa la condición esta es falsa, el cuerpo del ciclo no se ejecuta ni una sola vez. Para ejemplificar cómo se construye un ciclo indefinido utilizando un valor centinela, se propone el siguiente problema. Problema 4.4: Se requiere un programa que calcule el promedio de temperaturas que registra una ciudad, las temperaturas se introducirán en grados Farenheit °F y no se conoce de antemano el número de temperaturas que el usuario introducirá. Para resolver el problema planteado se podría pedir el número de temperaturas que se desean registrar para calcular el promedio, pero esto equivale a una estructura de repetición definida, si decidiéramos dejar abierto este dato hasta el momento de la ejecución del programa, tendríamos que construir una condición que haga que el ciclo se repita mientras que el usuario desea ingresar temperaturas. Pero ¿cómo se puede resolver esto? En casos como este se propone utilizar un valor centinela que indique el fin de la captura de datos. Claramente el valor centinela debe ser seleccionado de tal forma que no se confunda con algún valor de entrada aceptable, por ejemplo podríamos considerar que dado que existe un límite mínimo de temperaturas en grados Farenheit, a saber -460°F, el valor centinela sería cualquier número inferior a éste, es claro que no existe una temperatura más baja, sin embargo el límite máximo es difícil de definir ya que en forma experimental se obtienen en los laboratorios temperaturas de miles de grados, mientras que en una explosión atómica se alcanzan temperaturas de millones de grados. Se supone que la temperatura en el Sol alcanza los mil millones de grados (Pérez, 1992, pág. 325).
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
96
Fundamentos de programaciĂłn Programa Desarrollado
Para calcular el promedio, debemos realizar la suma de todas las temperaturas (đ?&#x2018;Ąđ?&#x2018;&#x2019;đ?&#x2018;&#x161;đ?&#x2018;?đ??š1 + đ?&#x2018;Ąđ?&#x2018;&#x2019;đ?&#x2018;&#x161;đ?&#x2018;?đ??š2 + â&#x20AC;Ś , + đ?&#x2018;Ąđ?&#x2018;&#x2019;đ?&#x2018;&#x161;đ?&#x2018;?đ??šđ?&#x2018;&#x203A; ) y dividirlas entre el nĂşmero total de temperaturas que se hayan leĂdo, digamos đ?&#x2018;&#x203A;. Lo anterior se expresa con la siguiente fĂłrmula. đ?&#x2018;Ąđ?&#x2018;&#x2019;đ?&#x2018;&#x161;đ?&#x2018;?đ??šđ?&#x2018;&#x2013; đ?&#x2018;?đ?&#x2018;&#x;đ?&#x2018;&#x153;đ?&#x2018;&#x161;đ?&#x2018;&#x2021; â&#x2020;? đ?&#x2018;&#x203A; AsĂ que en este caso se usarĂĄ un ciclo que vaya leyendo una a una las temperaturas (almacenĂĄndolas en la variable đ?&#x2018;Ąđ?&#x2018;&#x2019;đ?&#x2018;&#x161;đ?&#x2018;?đ??š) y acumulando la suma en la variable đ?&#x2018; đ?&#x2018;˘đ?&#x2018;&#x161;đ?&#x2018;&#x17D;đ??š, estas acciones se repetirĂĄn hasta que el usuario introduzca un nĂşmero menor a -460. De esta manera, la condiciĂłn de tĂŠrmino es: đ?&#x2018; đ?&#x2018;˘đ?&#x2018;&#x161;đ?&#x2018;&#x17D;đ??š â&#x2030;Ľ â&#x2C6;&#x2019;460; por lo que antes de iniciar el ciclo se debe pedir la primera temperatura, para que se compare con la condiciĂłn y si es mayor a -460 se acumule en la suma. AdemĂĄs, se utilizarĂĄ un contador para registrar el nĂşmero de temperaturas que se lean. Finalmente, cuando se termina el ciclo se divide el resultado de la suma de las temperaturas entre el valor del contador. Lo anterior se expresa en el siguiente pseudocĂłdigo. Inicio câ&#x2020;?0, sumaFâ&#x2020;?0 Imprimir "Ingrese la primer temperatura registrada en grados Fahrenheit:" Leer tempF Mientras (tempFâ&#x2030;Ľ-460) câ&#x2020;?c+1 sumaF=sumaF+tempF Imprimir "Ingrese la siguiente temperatura en grados Fahrenheit (un nĂşmero mayor a -460) para calcular el promedio " Leer tempF Fin Mientras promFâ&#x2020;?sumaF/c Imprimir â&#x20AC;&#x153;El promedio de las temperaturas esâ&#x20AC;? promF Fin Algoritmo 4.4.a: Promedio temperaturas - pseudocĂłdigo
EducaciĂłn Superior Abierta y a Distancia â&#x20AC;˘ Ciencias Exactas, IngenierĂa y TecnologĂa
97
Fundamentos de programación Programa Desarrollado
La representación del algoritmo en diagrama de flujo que se muestra en la siguiente figura:
Algoritmo 4.4.b: Promedio temperaturas – diagramas de flujo En la siguiente tabla se muestra una prueba de escritorio para las temperaturas 75, 78, 79 y para concluir el ciclo -2000.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
98
Fundamentos de programación Programa Desarrollado
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
99
Fundamentos de programación Programa Desarrollado
Tabla 4.9: Prueba de escritorio del algoritmo 4.4 En la tabla 4.9 se puede observar como el mismo conjunto de instrucciones se repite tres veces (3 iteraciones), en cada una se valida la condición y el ciclo termina sólo cuando ésta no se satisface por el estado de las variables implicadas en la expresión booleana. Una vez que se ha ilustrado el funcionamiento del ciclo Mientras y verificado que si funciona, el siguiente paso es la codificación, para la cual se determinó utilizar una variable para representar el valor centinela que controla el ciclo. /* Programa: promTemp.c Descripción: Calcula el promedio de las temperaturas que el usuario ingresa. */ #include<stdio.h> #include<stdlib.h> #define centinela -460 /* Función principal */ main () { /*Declaración de acumuladores y contadores*/ float tempF,promF, sumaF=0; int c=0; /* Lectura de la primera temperatura */ printf ("Programa que calcula el promedio de temperaturas en grados Fahrenheit\n\n\n"); printf ("\n Ingrese la primer temperatura registrada:");
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
100
Fundamentos de programación Programa Desarrollado
scanf ("%f",&tempF); /* Codificación del ciclo */ while (tempF>= centinela) { /* Se registra la temperatura que se leyó */ c = c + 1; /* Se acumulala temperatura en la suma */ sumaF=sumaF+tempF; /* Se lee la siguiente temperatura */ printf ("\n\nIngrese la siguiente temperatura (si desea terminar ingrese un número menor a %d): ", centinela); scanf ("%f",&tempF); } /* Promedio de Temperaturas Fahrenheit */ promF=sumaF/c; printf ("\nPromedio de temperaturas Celsius=%.2f\n", promF); system ("pause"); } Programa 4.4: promTemp.c Por último, en la siguiente figura se muestra la ejecución del programa con los mismos datos que se utilizaron en la prueba de escritorio.
Figura 4.4: Ejecución del programa promTemp.c
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
101
Fundamentos de programación Programa Desarrollado
Actividad 1. Estructuras de control –Ejercicio D Realiza una prueba de escritorio del algoritmo que resuelve el problema 4.4 presentado en esta sección (algoritmo 4.4.a y algoritmo 4.4.b) considerando que los valores de entrada son 80, 100, 250, -1000. Después escribe y compila el programa promTemp.c (programa 4.4) en la computadora y ejecútalo con los mismos valores para comparar el resultado. Posteriormente reflexiona si es posible resolver este problema utilizando únicamente estructuras selectivas e ingresa tus comentarios en el Foro Estructuras de control. 4.2.2. Estructura Desde-mientras (for) El ciclo Desde-mientras, en inglés y lenguaje C for, evaluará una condición y mientras ésta sea verdadera se ejecutará el conjunto de instrucciones definidas en el cuerpo de la estructura, generalmente las repeticiones se controlan por un contador, ya que como parte de su sintaxis tiene la opción de inicializar una variable (el contador) e incrementarlo o decrementarlo. Este tipo de estructura es conveniente utilizarla cuando se conoce de antemano el número de veces que se debe repetir el ciclo (ciclos definidos). Sus representaciones se muestran en la siguiente tabla. Pseudocódigo
Diagrama de Flujo
Desde <inicialización>Mientras<condición>, <incr/decr> <Instrucciones> Fin desde
Lenguaje C for (<inicialización>;<condición>; <inc/dec>) <instrucciones> Tabla 4.8: Representaciones de la estructura repetitiva Desde-mientras (for)
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
102
Fundamentos de programación Programa Desarrollado
En este caso, primero se realiza la <inicialización> que corresponde a la asignación de un valor inicial de una variable (el contador), posteriormente se evalúa la <condición> si es verdadera se ejecutan las <instrucciones> del cuerpo del ciclo y, posteriormente, se incrementa o decrementa el contador, según sea el caso, para después volver a repetir el ciclo, excepto por la <inicialización> que sólo se ejecuta una vez. Es importante señalar que si te centras en la representación en diagrama de flujo de este ciclo podrás darte cuenta que se parece al diagrama del ciclo while, salvo por la inicialización y el incremento (o decremento); de hecho si partes del diagrama de flujo para la codificación puedes utilizar un while. De igual manera, un ciclo while se puede representar con un ciclo for cuya <inicialización> e <incremento/decremento> son vacíos, sólo se define la condición. Con lo anterior se muestra la equivalencia de las dos estructuras. Para ejemplificar las representaciones, codificación y funcionamiento de esta estructura se presenta el siguiente problema desarrollado. Problema 4.5: Se requiere un programa que calcule el total de la nómina de los trabajadores de una empresa. El problema es similar al que se presentó en la sección anterior, se debe leer el pago de cada trabajador y realizar la suma de cada uno de éstos, para lo cual se puede utilizar un acumulador. La diferencia es que en este caso no se utilizará un valor centinela para terminar la lectura de los pagos, pues se preguntará al usuario al inicio del programa cuántos trabajadores hay, así el número de iteraciones quedará determinado antes de iniciar el ciclo. De lo anterior tenemos que si el número de empleados es n entonces el ciclo debe repetirse n-veces, para lo cual se utilizará un contador c que debe tomar los valores 1,2,…, n, así que el ciclo debe repetirse siempre que c ≤ n. En cuanto a la suma de los pagos, se utilizará un acumulador, al cual llamaremos nom, que se inicializará en cero dado que se trata de una suma. Observa la solución del problema.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
103
Fundamentos de programación Programa Desarrollado
Inicio Imprimir "Ingrese el total de empleados: " Leer n Desde c=1 , nom=0, Mientras (c<=n), c=c+1 Imprimir “Ingresa el salario del trabajador”, c Leer sal nom=nom+sal Fin desde Imprimir “La nómina a pagar es en total $”, nom Fin Algoritmo 4.5.a: Nómina - pseudocódigo
Algoritmo 4.5.b: Nómina – diagrama de flujo En la siguiente tabla se muestra la ejecución paso a paso del ciclo suponiendo que se quiere calcular la nómina de tres empleados y ya se ha leído el dato y registrado en la variable n, la cual no cambia su valor a lo largo de la ejecución del ciclo.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
104
Fundamentos de programación Programa Desarrollado
Tabla 4.9:Prueba de escritorio del algoritmo 4.4 Por lo tanto, la salida del algoritmo es: “La nómina a pagar es $45”. La codificación sería la siguiente. /* Programa: nomina.c Descripción: calcula la nómina a pagar de n trabajadores */ /*directivas de preprocesador*/ #include<stdio.h> #include<stdlib.h>
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
105
Fundamentos de programación Programa Desarrollado
/*Función Principal*/ main () { /* Declaración de las variables */ int n,c; float nom,sal; /* Lectura del número de empleados */ printf ("Calculo de la Nomina\n\n "); printf ("Ingrese el total de empleados: "); scanf ("%d",&n); /*Ciclo definido de 1 hasta el número de empleados ingresados*/ for (nom=0,c=1;c<=n;c=c+1) { printf ("\nIngresa el salario del trabajador %d: ", c); scanf ("%f",&sal); /*Acumulador de salários*/ nom=nom+sal; } printf(“\n La nomina a pagar es $&.2f”, nom); } Programa 4.5: nomina.c En la siguiente figura se muestra la ejecución del programa con los mismos datos de entrada que se utilizaron en la prueba de escritorio.
Figura 4.6: Ejecución del programa nomina.c
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
106
Fundamentos de programación Programa Desarrollado
Actividad 1. Estructuras de control –Ejercicio E Realiza una prueba de escritorio del algoritmo que resuelve el problema 4.5 presentado en esta sección (algoritmo 4.5.a y algoritmo 4.5.b) para calcular la nómina de 4 trabajadores con salarios igual a: $2000.00, $5000.00, $3000.00 y $1000.00. Posteriormente, escribe y compila el programa nomina.c (programa 4.4) en la computadora y ejecútalo con los mismos valores para comparar el resultado. Analiza cómo podrías resolver este problema utilizando la estructura Mientras (while) e ingresa tus comentarios al respecto en el Foro Estructuras de control. 4.2.3 Estructura Hacer-mientras (do-while) A diferencia de las estructuras repetitivas anteriores, en las cuales las condiciones se evalúan al principio del ciclo, por lo que las instrucciones que se repiten se ejecuten de 0 hasta N veces, en la estructura Hacer-mientras (do-while) la evaluación se lleva acabo al final, esto implica que el conjunto de instrucciones que se repite se ejecuta al menos una vez. Pseudocódigo
Diagrama de Flujo
Hacer <instrucciones> Mientras
Lenguaje C do <instrucciones>; while(<condición>);
<condición>Fin
Tabla 4.9: Representaciones de la estructura repetitiva Hacer-mientras (do-while) Observa que en el código en C, la única estructura de control, de todas las que hemos visto, que tiene punto y coma después de la expresión o condición es el do-while. Por el funcionamiento de la estructura, el caso típico del uso del do-while son los menús. Para ejemplificar lo anterior se propone el siguiente problema. Problema 4.6: Se requiere un programa que imprima un menú con las siguientes opciones, el cual se repita en tanto no se elige la opción d (Salir). a. Calcular la fuerza b. Calcular la aceleración c. Calcular la masa d. Salir
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
107
Fundamentos de programaciĂłn Programa Desarrollado
AdemĂĄs, dependiendo de la opciĂłn que elija el usuario se deberĂĄ realizar la tarea indicada utilizando la segunda ley de Newton que dicta: â&#x20AC;&#x153;La aceleraciĂłn que un cuerpo adquiere es directamente proporcional a la resultante de las fuerzas que actĂşan en ĂŠl, y tiene la misma direcciĂłn en el sentido que en dicha resultanteâ&#x20AC;? đ?&#x2018;&#x201C;đ?&#x2018;˘đ?&#x2018;&#x2019;đ?&#x2018;&#x;đ?&#x2018;§đ?&#x2018;&#x17D; = đ?&#x2018;&#x161;đ?&#x2018;&#x17D;đ?&#x2018; đ?&#x2018;&#x17D; â&#x2C6;&#x2014; đ?&#x2018;&#x17D;đ?&#x2018;?đ?&#x2018;&#x2019;đ?&#x2018;&#x2122;đ?&#x2018;&#x2019;đ?&#x2018;&#x;đ?&#x2018;&#x17D;đ?&#x2018;?đ?&#x2018;&#x2013;Ăłđ?&#x2018;&#x203A; En este caso, para resolver la parte del menĂş se utilizarĂĄ un switch-case, en el que cada opciĂłn del menĂş corresponda a un caso, asĂ las instrucciones que lo forman deben ser: la lectura de los datos correspondientes y la operaciĂłn apropiada (que se define despejando la variable en cuestiĂłn de la fĂłrmula dada). Para que el menĂş se repita se plantea un ciclo while que se ejecute mientras la opciĂłn sea distinta de 4 (Salir). De esta forma el algoritmo se presenta a continuaciĂłn en sus dos representaciones. Inicio Hacer Imprimir "Realiza CĂĄlculos trabajando la 2a. Ley de Newton" Imprimir " ------------------------------------------------" Imprimir " a. Fuerza." Imprimir " b. AceleraciĂłn." Imprimir " c. Masa." Imprimir " d. Salir." Imprimir " Elegir una OpciĂłn: " Leeropc Selecciona (opc) Caso 1: Imprimir "Ingresa La masa:â&#x20AC;? Leer m Imprimir â&#x20AC;&#x153;Ingresa la aceleraciĂłn:â&#x20AC;? Leer a f = m*a Imprimir â&#x20AC;&#x153;Fuerza = â&#x20AC;?, f Caso 2: Imprimir "Ingresa la fuerza:â&#x20AC;? Leer f Imprimir â&#x20AC;&#x153;Ingresa la masa:â&#x20AC;? Leer m a = f/m Imprimir â&#x20AC;&#x153;AceleraciĂłn = â&#x20AC;?, a Caso 3:Imprimir "Ingresa la fuerza:â&#x20AC;? Leer f Imprimir â&#x20AC;&#x153;Ingresa la aceleraciĂłn:â&#x20AC;? Leer a m = f/a Imprimir â&#x20AC;&#x153;Masa = â&#x20AC;?, m
EducaciĂłn Superior Abierta y a Distancia â&#x20AC;˘ Ciencias Exactas, IngenierĂa y TecnologĂa
108
Fundamentos de programación Programa Desarrollado
Caso 4: Imprimir "Adios" Otro: Imprimir " Opción inválida" Fin_Selecciona Mientras (opc!=4) Fin Fin Algoritmo 4.6.a: Segunda ley de Newton - pseudocódigo A continuación se presenta el diagrama de flujo, salvo que únicamente se ha dejado indicado en donde van las instrucciones de los tres primeros casos, ya definidas en el pseudocódigo.
Algoritmo 4.6.b: Segunda ley de Newton – diagrama de flujo En el diagrama de flujo se puede observar claramente que el ciclo se ejecutará mientras el usuario no elija la opción d, que corresponde a salir. Por lo que no se deja como ejercicio al lector la validación del algoritmo.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
109
Fundamentos de programación Programa Desarrollado
La codificación del algoritmo se muestra enseguida. /* Programa: newton.c Descripción: Muestra un menú para calcular fuerza o masa, conforme a la segunda ley de Newton */ /*directivas de preprocesador*/ #include <stdio.h> #include <stdlib.h> #include <conio.h>
la
aceleración,
/*Función Principal*/ main () { /*Declaración de variables*/ char opc; float f,m,a; /*Ciclo para repetir el menú mientras que la opción no sea salir*/ do {/*Impresión del menú*/ system ("cls");/*Instrucción para borrar la pantalla*/ printf ("\n Realiza Calculos trabajando la 2a. Ley de Newton"); printf ("\n ------------------------------------------------"); printf ("\n a. Fuerza. \n b. Aceleracion \n c. Masa \n d. Salir"); printf ("\n Elige una opcion: "); /*Instrucción que lee una variable de tipo carácter*/ opc=getche(); /*Estructura de Selección Múltiple*/ switch (opc) { case 'a': printf ("\n\nIngresa la masa: "); scanf("%f",&m); printf ("\nIngresa la aceleracion: "); scanf("%f",&a); f=m*a; printf("\nLa fuerza es %.2f\n\n\t",f); system ("pause"); break; case 'b': printf ("\n\nIngresa la fuerza: "); scanf("%f",&f); printf ("\nIngresa la masa: "); scanf("%f",&m);
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
110
Fundamentos de programación Programa Desarrollado
a=f/m; printf("\nLaaceleracion es %.2f\n\n\t",f); system ("pause"); break; case 'c': printf ("\n\nIngresa la fuerza: "); scanf("%f",&f); printf ("\nIngresa la aceleración: "); scanf("%f",&m); m=f/a; printf("\nLa masa es %.2f\n\n\t",f); system ("pause"); break; case 'd': printf ("\n\nAdios\n"); system ("pause"); break; default: printf ("\n\n Opcion Invalida"); }/*Fin dela Selección Múltiple*/ }while (opc!='d'); }/*Fin*/ Programa 4.5: newton.c En la siguiente figura se muestra la ejecución de una iteración del ciclo, en la cual la opción elegida es la primera.
Figura 4.6: Ejecución del programa newton.c
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
111
Fundamentos de programación Programa Desarrollado
Observa que dentro del cuerpo del ciclo se definió una estructura selectiva, es decir, que las instrucciones del cuerpo de cualquier estructura compuesta, sea repetitiva o selectiva, puede contener a otras. Uno de los casos más utilizados es el anidamientos de los if´s, de lo cual hablaremos en la siguiente sección. Pero antes de dar por terminada esta sección se propone la siguiente actividad. Actividad 1. Estructuras de control –Ejercicio F Realiza una prueba de escritorio del algoritmo que resuelve el problema 4.6 presentado en esta sección (algoritmo 4.4.a y algoritmo 4.4.b) considerando que se muestran en la ejecución del programa en la figura 4.6, y considerando que la siguiente opción del usuario es salir. Posteriormente escribe y compila el programa newton.c (programa 4.6) en la computadora y ejecútalo con los mismos valores para comparar el resultado. Finalmente, reflexiona si las estructuras de control repetitivas presentadas en esta unidad son equivalente, es decir, cualquier de ellas se puede representar con las otras e ingresa tus conclusiones en el Foro Estructuras de control. 4.3. Estructuras anidadas Las estructuras de control selectivas y repetitivas se consideran compuestas ya que se forman a partir de otras instrucciones que son las que se ejecutaran de acuerdo a una condición dada. Es importante remarcar que las instrucciones que forman el cuerpo de una estructura pueden ser también estructuras compuestas, como se demostró en la solución del último problema visto (ver algoritmo 4.6 y programa 4.6), en el cual un switch está dentro de un while. Así que es posible anidar cualquier tipo de estructura, sin embargo, lo más común es anidar instrucciones if, pues se utilizan cuando se tienen varios casos, por ejemplo, si revisamos nuevamente el problema 4.1, donde se quiere determinar el tipo de ángulo, es mejor solución utilizar if-anidados para resolverlo porque así no se evalúan condiciones que, una vez que se ha definido el tipo de ángulo, son innecesarias. Para ilustrar lo anterior, a continuación se muestra el pseudocódigo y su codificación para la solución del mismo problema. Inicio Imprimir "Ingrese la medida del angulo (grados): " Leer angulo Si angulo≤0 OR angulo≤360 entonces Imprimir “No tiene clasificación" Sino Si angulo<90 entonces Imprimir "El ángulo es agudo" Sino Si angulo=90 entonces Imprimir "El angulo es recto" Sino Si angulo<180 entonces
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
112
Fundamentos de programación Programa Desarrollado
Imprimir “El angulo es obtuso" Sino Si angulo =180 entonces Imprimir "El angulo es llano" Sino Imprimir “El angulo es concavo" Fin_Si-Sino Fin_Si-Sino Fin_Si-Sino Fin_Si-Sino Fin_Si-Sino Fin Algoritmo 4.7: Tipo de ángulo (versión 2)- pseudocódigo (Fuente: elaboración propia) Si realizas la prueba de escritorio con el ángulo igual a 90 grados, podrás darte cuenta que a diferencia de la primera versión del algoritmo donde se evalúan todas las condiciones, aquí sólo se evalúan las tres primeras, en los dos primeros Si es falsa y por lo tanto se ejecutan las instrucciones del Sino correspondiente, pero en el tercer Si anidado la condición es verdadera y se imprime el tipo de ángulo, posteriormente se acaba el anidamiento. El programa en C es el siguiente: main () { /*Declaración de variables */ intangulo; /*Mensaje de bienvenida*/ printf ("\nEste programa determina de que tipo es el angulo dado."); /*Instrucciones */ printf ("\n\nIngrese la medida del angulo (grados): "); scanf ("%d",&angulo); if (angulo<=0 || angulo>=360) printf ("\n No tiene clasificación"); else if (angulo<90) printf ("\n El angulo es agudo"); else if (angulo==90) printf ("\n El angulo es recto");
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
113
Fundamentos de programación Programa Desarrollado
else if (angulo<180) printf ("\nElanguloesobtuso"); else if (angulo ==180) printf ("\n El angulo es llano"); else printf ("\nElangulo es concavo"); printf ("\n\n\t"); system ("pause"); } Programa 4.7: tipoAngulo2.c La ejecución con el ángulo igual a 90 grados se muestra en la siguiente figura.
Figura 4.7: Ejecución del programa tipoAngulo2.c Con este ejemplo se da por terminada esta unidad, ahora ya conoces todas las estructuras y has visto cómo funcionan y qué tipo de situaciones se puede modelar con ellas. Aunque cabe destacar que para solucionar cualquier problema basta con que sepas utilizar el ciclo while y la estructura selectiva ifelse, pues ya se mencionó que todos los ciclos son equivalentes y con la estructura if-else, puedes modelar un switch-case anidando if´s. Actividad 1. Estructuras de control –Ejercicio G Realiza una prueba de escritorio del algoritmo que resuelve el problema 4.1, en su versión de if´s anidados, presentado en esta sección (algoritmo 4.7), considerando que el valor del ángulo es 90 grados. Posteriormente escribe, compila y ejecuta el programa tipoAngulo2.c (programa 4.7) en la computadora con el mismo valor del ángulo para verificar tu resultado.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
114
Fundamentos de programación Programa Desarrollado
Actividad 3: Estructuras repetitivas Realiza el análisis, diseño de un algoritmo (en pseudocódigo y diagrama de flujo) y codificación de un programa que resuelva el problema que te proporcionará tu Facilitador(a). Utiliza estructura(s) repetitiva(s). Para conocer los detalles de la actividad, ingresa al aula virtual. Evidencia de aprendizaje.Programa en C. Estructuras de control Con ayuda de tu facilitador deberás acotar el problema que describiste en la evidencia de la unidad 2, de tal manera que la solución sólo implique el uso de estructuras de control. Para conocer los detalles de la actividad, ingresa al aula virtual. Consideraciones específicas de la unidad Para cumplir con los objetivos de esta unidad te recomendamos que realices las actividades señaladas como opcionales de cada subtema, las cuales consisten en pruebas de escritorio y codificación, compilación y ejecución de los programas que se realizaron a lo largo de esta unidad. Referencias:
Joyanes, L., & Zohanero, I. (2005). Programación en C. Metodología, algoritmos y estructuras de datos. aspaño: Mc Graw Hill.
Kernighan, B., & Ritchie, D. (1991). El lenguaje de programción C. México: Prentice-Hall Hispanoamericana.
López, L. (2005). Programación estructurada en lenguaje C. México: Alfaomega.
Pérez, H. (1992). Física General (Primera Edición ed.). México: Publicaciones Cultura.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
115
Fundamentos de programación Programa Desarrollado
Unidad 5: Estructuras de datos Propósitos En esta unidad: Determinarás las estructuras de datos involucradas en la solución de un problema. Diseñarás soluciones empleando arreglos y estructuras (registros). Utilizarás arreglos y estructuras (registros) en programas escritos en lenguaje C. Competencia específica Utilizar estructuras de datos para almacenar y manipular los datos de un programa por medio del desarrollo de programas en lenguaje C. Introducción En muchas ocasiones nos vemos en la necesidad de procesar datos que están relacionados entre sí, a este tipo de datos se le conoce como estructurados, ya que están compuestos de un conjuntos de datos básicos (recuerda la clasificación de datos presentada en la unidad 3 en la tabla 3.2 Tipo de datos). Por ejemplo pensemos en el nombre completo de una persona, que está compuesto nombre, apellido paterno y apellido materno, o bien, en una dirección, formada por nombre de la calle, número y código postal, en este último caso no sólo está formada por varios datos simples sino que además podemos considerarlos de diferentes tipos (Figura 5.3).
Figura 5.3: Ejemplos de datos Estructurados Con este tipo de datos será útil poder hacer referencia a ellos bajo un mismo identificador, y así tratarlos como una unidad. Una estructura de datos es un mecanismo de agrupación de datos que facilitan el manejo de datos estructurados y que se caracteriza por la forma en que se acede a sus elementos. Pensemos en otro ejemplo en el cual se tienen datos relacionados, supongamos que nos enfrentamos al siguiente problema:
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
116
Fundamentos de programación Programa Desarrollado
Problema 5.1: Se requiere un programa para llevar el registro de calificaciones de un grupo de diez estudiantes y generar reportes que incluyan datos como el promedio del grupo, la calificación máxima, el número de estudiantes que tienen una calificación superior al promedio del grupo, entre otros. En este caso, a diferencia de los ejemplos anteriores, es claro que las calificaciones de cada estudiante se puede tratar como un dato simple e independiente de los otros, sin embargo las operaciones que se desean realizar serán las mismas para todo el conjunto de calificaciones, de tal forma que habría que escribir una serie de instrucciones secuenciales para ingresar cada dato y procesarlo. Por ejemplo, para ingresar los datos se requiere leer una por una cada calificación, para obtener el promedio se tendría que hacer la suma de todas y después dividirlas entre 10, hasta aquí no se ha complicado mucho, pero imagina todas las comparaciones que debes hacer para identificar cuál es la calificación mayor. Es claro que este método resulta de lo más ineficiente, y por supuesto si consideramos la posibilidad de modificar el programa para que sea capaz de procesar 60 o más calificaciones, el programa además de extenderse, implica reestructurarlo en su totalidad y que éste sea más complejo que la versión anterior. En cambio si consideramos a todos las calificaciones como un dato estructurado podemos hacer uso de una estructura de dato que nos facilite su manipulación. Existen diferentes tipos de estructuras de datos, cada una caracterizada por la forma de acceso a sus elementos, y el tipo que estos pueden tener, así tenemos arreglos, listas, colas, tablas, pilas, entre otros. No obstante, para esta unidad nos centraremos sólo en las estructuras de datos que implementa el lenguaje C de forma directa: los arreglos y las estructuras. 5.1. Arreglos El uso de arreglos facilita y hace más eficiente la declaración y manipulación de una colección de datos de un mismo tipo que están relacionados entre sí, como es el caso de las calificaciones en el Problema1, ya que todas las calificaciones se pueden considerar como valores enteros. 5.1.1. Definición y tipos de arreglos “Un arreglo se define como una colección finita, homogénea y ordenada de elementos. Finita ya que para todo arreglo debe especificarse el número máximo de elementos que podrá contener; la homogeneidad se refiere a que todos los elementos deben ser del mismo tipo, y ordenada porque es posible determinar cuál es el primer elemento, cual el segundo, y así hasta el enésimo elemento”(Cairo Osvaldo, Guardati Buemo Silvia, 1993). La posición que ocupa un elemento dentro de un arreglo se le denomina formalmente índice y siempre es un número entero. El tamaño o longitud de un arreglo se define como el número de elementos que lo constituyen. La dimensión de un arreglo está relacionada con el número de índices necesarios para especificar a una elemento en particular.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
117
Fundamentos de programación Programa Desarrollado
Podemos clasificar a los arreglos de acuerdo a su dimensión como unidimensionales o multidimensionales. Los arreglos unidimensionales(también llamados lineales) reciben su nombre debido a que cualquier elemento es referenciado por un único índice, por ejemplo retomando el caso de las calificaciones del problema 5.1, éstas pueden ser almacenadas en un arreglo unidimensional como el que se muestra en la Figura 5.4, en donde el nombre del arreglo es lista y los nombres de las variables donde se almacenan las calificaciones son: lista[0], lista[1], lista[2], lista[3], lista[4] …, lista[9]. En este caso el nombre en común es lista y lo único que cambia para cada elemento es el número que le corresponde a cada variable según la posición que ocupa en la lista. Observa que un solo índice es suficiente para diferenciar a un elemento de otro.
Figura 5.4 Representación gráfica de un arreglo unidimensional
Por otro lado los arreglos multidimensionales son aquellos para los cuales un solo índice no es suficiente para poder referenciar a un elemento individual, los arreglos bidimensionales son el caso más comúnmente utilizado de arreglos multidimensionales y por tanto los únicos que presentaremos. “Un arreglo bidimensional es un conjunto de datos homogéneos, finito y ordenado, donde se hace referencia a cada elemento por medio de dos índices. El primero de los cuales generalmente se utiliza para indicar renglón y el segundo para indicar columna” (Cairo Osvaldo, Guardati Buemo Silvia, 1993) Un arreglo bidimensional también puede verse como una tabla de valores, o bien como un arreglo de arreglos, de ahí la necesidad de dos índices, en la Figura I.5 se muestra un ejemplo gráfico de un arreglo bidimensional, en la cual del lado derecho podemos ver al arreglo como una tabla y del lado izquierdo representado como un arreglo de arreglos, Observa que cada renglón de la tabla es cada uno
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
118
Fundamentos de programación Programa Desarrollado
de los elementos del arreglo de arreglos. Es claro que con un solo índice no podríamos identificar a un único elemento ya que solo podríamos ubicar toda una columna o todo un renglón, en cambio la combinación de renglón-columna si nos identifica a un elemento en particular.
Figura I.5Representación gráfica de un arreglo bidimensional 5.1.2. Declaración e inicialización En lenguaje C los índices de los arreglo siempre empiezan en cero, es decir, al primer elemento del arreglo le corresponde la posición 0, al segundo la posición 1, al tercero la posición 2 y así sucesivamente hasta llegar al elemento TAM-1, donde TAM corresponde al tamaño del arreglo. La declaración de un arreglo consiste en reservar espacio de memoria suficiente para el conjunto de datos homogéneos. La declaración de una variable de tipo arreglo sigue las mismas reglas que para las variables simples; con la diferencia de que ahora será necesario especificar el tamaño del arreglo, esto se hace escribiendo el tamaño del arreglo encerrado entre corchetes [ TAM ], después del identificador. La sintaxis para la declaración de un arreglo unidimensional en lenguaje C es la siguiente: <tipo><nombre>[<tamaño>]; Y para un arreglo bidimensional es: <tipo><nombre>[<tamaño1>] [<tamaño2>];
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
119
Fundamentos de programación Programa Desarrollado
El tipo de dato para los arreglos puede ser cualquier tipo básico, es decir entero, flotante o carácter (en C int, float, double o char ). De todos ellos los arreglos de tipo carácter (char) tienen un tratamiento especial, ya que un arreglo de este tipo se considerara una cadena. Debido a la importancia que tienen las cadenas en la programación más adelante los trataremos de manera particular. Al igual que las variables simples, un arreglo puede inicializarse al momento de ser declarado, para ello se utiliza el operador asignación “=”, pero como un arreglo almacena a un conjunto de datos, es necesario inicializarlo con un conjunto de valores, los cuales se indican mediante llaves, separando por comas cada elemento del conjunto de valores iniciales, la sintaxis se muestra a continuación: <tipo><nombre>[<tamaño>]={<valor0>,<valor1>,…,<valorTAM-1>}; La asignación de cada valor inicial se hace consecutivamente desde el elemento 0, por tanto no es posible asignar valores a elementos salteados. Veamos como ejemplo la declaración del arreglo unidimensional lista (Figura 5.4) planteado para las calificaciones del problema1. Inicializando sus elementos en la declaración queda como: int lista[10] = {9,10,8,5,9,6,7,9,4,8}; En el caso de los arreglos bidimensionales la sintaxis es la siguiente: <tipo><nombre>[<tamaño1>][<tamaño2>]={ {<valor00>,<valor01>,…,<valor0(TAM21)>}, {<valro10>,<valor11>,…,<valor1(TAM21-1)>},…, {<valor(TAM1-1)0>,<valor (TAM2-1)1>,…,<elem(TAM1-1)(TAM2-1)>} }; Veamos ahora como queda la declaración del arreglo bidimensional tabla mostrado en la Figura I.5, inicializando su valores: int tabla[5][3]={{9,10,8},{5,9,6},{7,9,4},{8,9,6},{7,9,4}}; Aunque también es posible declararlo de la siguiente forma: int tabla[5][3]={9,10,8,5,9,6,7,9,4,8,9,6,7,9,4}; Esta es debido a que como ya se dijo antes un arreglo bidimensional se pude ver como un arreglo de arreglos.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
120
Fundamentos de programación Programa Desarrollado
Por otro lado, en lenguaje C siempre es necesario especificar el tamaño del arreglo al momento de declararlo, sin embargo esto se puede hacer de forma explícita o implícita.
Explícitamente es cuando se especifica el tamaño dentro de los corchetes que siguen al identificador, como en los ejemplos anteriores.
De forma implícita se hace cuando el arreglo es inicializado con un conjunto de valores, y se omite el tamaño dentro de los corchetes, entonces el compilador asume el tamaño del arreglo igual al tamaño del conjunto de valores iniciales, de tal forma que la declaración del arreglo lista puede quedar como: int lista[] = {9,10,8,5,9,6,7,9,4,8};
Observa que en este caso no se escribe el tamaño dentro de los corchetes, pero como hay 10 elementos en el conjunto de valores iniciales, el compilador de C asume un tamaño 10 para el arreglo. Para los arreglos bidimensionales, sólo es posible especificar una dimensión de forma implícita, el tamaño de renglones siempre debe hacerse de forma explícita. La asignación de un conjunto de valores al arreglo, en una sola operación de asignación, únicamente es posible en su declaración, si se intenta realizar en otro momento el compilador marcará un error, ya que en cualquier otra parte del programa sólo se podrán asignar valores simples a cada uno de los elementos por separado. Es importante señalar que cuando se desea inicializar el arreglo al declararlo, es posible inicializar sólo algunos de sus elementos, pero en este caso se tendría que especificar explícitamente el tamaño, además se debe recordar que la asignación de valores iniciales es consecutiva desde el elemento 0. Los elementos para los cuales no se indique un valor inicial, automáticamente se inicializan en cero. Por ejemplo la declaración int lista[10] = {5}; Reservará espacio en memoria para los 10 elementos del arreglo de los cuales al primer elemento se le asignará un 5 y al resto se les asignará un cero. En el caso de los arreglos bidimensionales es posible declara sólo algunos elementos por renglón, siempre y cuando los elementos sean consecutivos, como en el caso de los unidimensionales. Por ejemplo la siguiente declaración para el arreglo tabla: int tabla[5][3]={{9,10},{5},{7,9,4},{8,9,}};
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
121
Fundamentos de programación Programa Desarrollado
Daría como resultado la siguiente asignación de valores iniciales
[0] [1] [2] [3] [4]
[0] [1] [2] 9 10 0 5 0 0 7 9 4 8 9 0 0 0 0
En el caso de que la declaración fuera: int tabla[5][3]={9,10,5,7,9,4,8,9,}; Entonces la asignación de valores iniciales se haría de la siguiente forma
[0] [1] [2] [3] [4]
[0] [1] [2] 9 10 5 7 9 4 8 9 0 0 0 0 0 0 0
5.1.3. Acceso a los elementos de un arreglo Para referirse a un elemento del arreglo es necesario indicar el nombre del arreglo seguido del índice o índices correspondientes al elemento que deseamos acceder. Para ello se debe seguir la siguiente sintaxis. Elementos de un arreglo unidimensional: <nombre del arreglo>[<índice>]; Elementos de un arreglo bidimensional: <nombre del arreglo>[<índice de renglón>][<índice de columna>]; Observa que para cada índice se utilizan corchetes separados. Cada elemento del arreglo se puede tratar igual que a cualquier otra variable, es decir, podemos asignarle un valor, incluir en una expresión algebraica o lógica, imprimir en pantalla su valor, asignarle desde el teclado un valor, etc.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
122
Fundamentos de programación Programa Desarrollado
Veamos algunos ejemplos: Instrucción tabla[0][2] = 8; printf(“%d”,lista[4]); scanf(“%d”,&tabla[0][0]); lista[1]++;
Descripción Asignar el valor de 8 al tercer elemento del primer renglón de arreglo tabla Imprimir en pantalla el quinto elemento del arreglo lista Lee un entero desde teclado y asignarlo en la primera posición del arreglo tabla. Incrementar en uno el valor del segundo elemento del arreglo lista
5.1.4. Ciclos y arreglos Los arreglos y los ciclos están estrechamente relacionados, podríamos afirmar que en cualquier programa que se emplee un arreglo éste será manipulado por medio de una estructura repetitiva. Anteriormente mencionamos que un arreglo se utiliza cuando queremos almacenar y manipular datos relacionados entre sí y, generalmente, cuando tenemos un arreglo debemos ejecutar el mismo conjunto de operaciones sobre cada uno de sus elementos. En lenguaje C el índice del elemento se puede especificar mediante una expresión, es decir una variable, una constante o como el resultado de una operación, lo que hace posible ir cambiando el índice de un elemento dentro de un ciclo sin tener que escribir una serie de instrucciones secuenciales para realizar la misma operación sobre cada uno de los elementos del arreglo. La forma general de procesar un arreglo unidimensional por medio de un ciclo se muestra en la Figura I.6, observa cómo la variable contador pos del ciclo, también se utiliza como índice para el elemento del arreglo, de tal forma que en cada iteración se haga referencia a un elemento diferente del arreglo.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
123
Fundamentos de programación Programa Desarrollado
Figura I.6Procesamiento de arreglos unidimensionales mediante ciclos No es difícil intuir que para el caso de los arreglos bidimensionales será necesario no solo un ciclo sino un par de ciclos anidados, ya que tenemos dos dimensiones, cada uno de los ciclos se encargará de variar a un índice, la estructura general para estos ciclos se muestra en la Figura I.7. Dos ciclos están anidados cuando está uno dentro de otro, de tal forma que por cada iteración del externo, el interno completa todo un ciclo. Considerando esto, observa que en la Figura I.7 se toma como contador a la variable i para el ciclo externo, la cual también se utiliza como índice de renglón. Asimismo, se utiliza a la variable j como contador para el ciclo interno, además de índice de columna, de esta manera se está recorriendo el arreglo por renglón.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
124
Fundamentos de programación Programa Desarrollado
Figura I.7Procesamiento de arreglos bidimensionales mediante ciclos anidados Si analizamos el diagrama de flujo podemos observa que para la primera iteración del ciclo externo, la variable i tiene el valor de 0 mientras que j toma los valores desde 0 hasta TAMC-1 (TAMC es el número total de columnas) de tal forma que el renglón se mantiene fijo mientras nos movemos en todas las columnas, en la siguiente iteración cambia el renglón ya que i toma el valor de 1 y recorremos nuevamente todas las columnas, este proceso se repite hasta el valor final de i que es TAMF-1 (TAMF es el número de renglones). Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
125
Fundamentos de programaciĂłn Programa Desarrollado
Ejemplo 5.1: Veamos cĂłmo utilizar arreglos en la soluciĂłn de un problema, resolviendo como ejemplo parte del problema 1, enfocĂĄndonos Ăşnicamente en la lectura de las 10 calificaciones y el cĂĄlculo del promedio. Para almacenar las calificaciones se puede utilizar un arreglo unidimensional de tipo entero, serĂĄ necesario pedir al usuario que ingrese las 10 calificaciones para poder realizar las operaciones necesarias para el cĂĄlculo del promedio, es decir, la suma de las misma y la divisiĂłn entre el total de calificaciones, para finalmente imprimir en pantalla el promedio, adicionalmente se imprimirĂĄ tambiĂŠn la lista de calificaciones ingresadas. No existe ninguna restricciĂłn que sea necesaria considerar. Cada uno de los procesos que se van a realizar sobre las calificaciones, es decir leerlas, sumarlas e imprimirlas en pantalla se pueden implementar mediante ciclos, en vez de tener que escribir 10 veces la misma expresiĂłn para cada una de las 10 calificaciones. La lectura y la suma de las calificaciones se pueden implementar dentro del mismo ciclo. De esta manera podemos resumir el anĂĄlisis del problema de la siguiente forma: Datos de entada: Calificaciones de los 10 estudiantes (calif [ ]) Salida: Promedio de calificaciones (prom) MĂŠtodo: prom =
9 đ?&#x2018;&#x2013;=0 đ?&#x2018;?đ?&#x2018;&#x17D;đ?&#x2018;&#x2122;đ?&#x2018;&#x2013;đ?&#x2018;&#x201C;
[đ?&#x2018;&#x2013;]
10
La soluciĂłn del problema representada en pseudocĂłdigo se muestra en el siguiente algoritmo.
EducaciĂłn Superior Abierta y a Distancia â&#x20AC;˘ Ciencias Exactas, IngenierĂa y TecnologĂa
126
Fundamentos de programación Programa Desarrollado
Inicio suma ← 0 Desde i ← 0 mientras i<10, i ← i+1 Imprimir “Ingresa la calificación” i Leer calif[i] suma← suma+calif[i] Fin Desde prom ← prom/10 Imprimir “Las calificaciones ingresadas fueron:” Desde i ← 0 mientras i<10, i ← i+1 Imprimir “Calificación” i “:” calif[i] Fin Desde Imprimir “Calificación promedio = ” prom Fin Algoritmo 5.2. Promedio de calificaciones La codificación del algoritmo anterior es la siguiente: /*Directivas de preprocesador*/ #include <stdio.h> #include <stdlib.h> /* Definimos como constante simbólica el tamaño del arreglo*/ #define TAM 10 /* Definición de función principal */ main( ) { /*Declaración del arreglo calificaciones*/ int calif[TAM]; double prom = 0; int i; printf("*******************************************\n”); printf(“* El siguiente programa calcula el promedio de *\n"); printf(“* un grupo de diez estudiantes *\n”); printf("********************************************\n”); /*Lectura y suma de las calificaciones*/ for(i=0; i < TAM; i++) { printf("Proporciona la calificación %d: ",i+1); scanf(“%d”, &calif[i]); prom = prom + calif[i];
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
127
Fundamentos de programación Programa Desarrollado
} /*Cálculo e impresión del promedio*/ prom = prom/TAM; /*Impresión de las calificaciones*/ printf("\nLas calificaciones ingresadas fueron: \n"); for(i=0; i < TAM; i++) printf("\nCalificacion %d: %d",i+1, calif[i]); printf("\n\n\tPromedio = %.2f\n\n", prom); system("pause"); } Programa 5.1: promCalificaciones.c En la siguiente figura se muestra una ejecución del programa.
Figura 5.8: Ejecución del programa promCalificaciones.c Observa que el tamaño del arreglo se especifica por medio de una constante simbólica, utilizando la directiva #define, esto facilita el cambiar el tamaño del arreglo sin tener que hacer cambios en todo el código.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
128
Fundamentos de programaciĂłn Programa Desarrollado
Actividad 1. Foro Estructuras de Datos â&#x20AC;&#x201C;Ejercicio A Realiza una prueba de escritorio con los datos que se muestran en la ejecuciĂłn del programa promCalificaciones.c (figura 5.6) y posteriormente escribe, compila y ejecuta el programa en la computadora. Reflexiona cĂłmo solucionarĂas el problema si no contaras con los arreglos y quĂŠ pasarĂa si en vez de calcular el promedio de 10 calificaciones tuvieras que hacerlo para 50, quĂŠ se deberĂa modificar en cada el programa que se presentĂł en esta secciĂłn y quĂŠ tendrĂas que modificar sino contaras con los arreglos. Ingresa tus conclusiones al Foro Estructuras de Datos A continuaciĂłn se presenta otro ejemplo para ilustrar el uso de arreglos bidimensionales. Ejemplo 5.2: Se requiere un programa que calcule el determinante de una matriz de 2x2. Considerando la siguiente informaciĂłn. Dada la siguiente matriz:
Su determinante se define como:
â&#x2C6;&#x2020;=a00a11-a01a10
AnĂĄlisis del problema: Para este problema se puede utilizar un arreglo bidimensional de 2 renglones y 2 columnas para almacenar los valores de la matriz, los cuales se pueden solicitar al usuario utilizando la estructura de ciclos anidados presentada en la Figura I.7, nuestro dato de salida serĂĄ el valor del determinante y adicionalmente tambiĂŠn se mostrarĂĄ en pantalla la matriz ingresada. Datos de entada: Elementos de la matriz (A[ ][ ]) Salida: Valor del determinante (det) MĂŠtodo: đ?&#x2018;&#x2018;đ?&#x2018;&#x2019;đ?&#x2018;Ą = đ??´[0][0] â&#x2C6;&#x2014; đ??´[1][1] â&#x2C6;&#x2019; đ??´[0][1] â&#x2C6;&#x2014; đ??´[1][0]
La soluciĂłn del problema se da en el siguiente diagrama de flujo.
EducaciĂłn Superior Abierta y a Distancia â&#x20AC;˘ Ciencias Exactas, IngenierĂa y TecnologĂa
129
Fundamentos de programación Programa Desarrollado
Algoritmo 5.3: Determinante de una matriz 2x2
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
130
Fundamentos de programación Programa Desarrollado
La codificación del algoritmo se deja como ejercicio al lector, sin embargo, en la siguiente figura se muestra un ejemplo de ejecución del programa. /* Directivas al preprocesador #include <stdlib.h> #include <stdio.h>
*/
/* Constantes con el tamaño de la matriz */ #define TAM 2 /* Función principal */ main() { int i, j; float det; float A[TAM][TAM]; /*declaración de la matriz*/ /* Mensaje de bienvenida */ printf("***************************************\n"); printf("* Determinante de una matriz A de 2x2 *\n"); printf("***************************************\n"); /* Lectura de la matriz A */ for(i=0; i<TAM; i++) for(j=0; j<TAM; j++){ printf("\nProporciona el elemento A[%d][%d]: ", i,j); scanf("%f", &A[i][j]); } det = A[0][0]*A[1][1] - A[0][1]*A[1][0]; printf("\nA: \n\t"); /* Impresión de la matriz A */ for(i=0; i<TAM; i++){ for(j=0; j<TAM; j++) printf("%8.2f", A[i][j]); printf("\n\t"); } printf("\n\n\t\tDeterminante = %.2f\n\n", det); system("pause"); } Programa 5.2: determinantes.c
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
131
Fundamentos de programación Programa Desarrollado
En la siguiente figura se muestra una ejecución del programa.
Figura 5.9: Ejecución del programa determinante.c Actividad 1. Foro Estructuras de Datos –Ejercicio B Realiza una prueba de escritorio con los datos que se muestran en la ejecución del programa determinante.c (figura 5.7) y posteriormente escribe, compila y ejecuta el programa en la computadora. Comparte tu experiencia en el Foro. 5.1.5 Cadenas Una cadena es una serie de caracteres tratados como una sola unidad. Una cadena puede incluir letras, dígitos y varios caracteres especiales(Deitel H. M., Deitel P. J., 1995). En algunos lenguajes de programación existe un tipo de dato específico para definir a las cadenas, sin embargo, en lenguaje C las cadenas se implementan por medio de arreglos de tipo carácter ya que no existe un tipo específico para ellas, pero existe todo un conjunto de funciones estándar definidas en la biblioteca string.h mediante las cuales es posible realizar las operaciones más comunes, por ejemplo: copiarlas, concatenarlas, compararlas, entre otras. Además es posible imprimirlas y leerlas de forma similar que un dato simple. En lenguaje C toda constaten de tipo cadena se indica entre comillas dobles, por ejemplo: “Calle 2 #135”
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
132
Fundamentos de programación Programa Desarrollado
Una cadena en C termina siempre con el carácter nulo „\0‟ (cuyo valor ascii es cero) que representa el fin de cadena. Al declarar arreglos de tipo char que sean una cadena se pueden inicializar directamente con una constante cadena de la siguiente forma: char cad[50]=”saludo”; Al inicializar una variable cadena de esta manera, se agrega automáticamente el símbolo de carácter nulo para indicar el fin de cadena, es decir, en la posición 6 del arreglo cad se encuentra almacenado el fin de cadena „\0‟. De forma general, es importante señalar que en un arreglo de tamaño N es posible almacenar correctamente una cadena de máximo N-1 caracteres. De tal forma que en el arreglo cad se puede almacenar una cadena de máximo 49 caracteres. Las cadenas en C pueden ser asignadas a un arreglo de tipo char utilizando la función scanf mediante el especificador de formato %s, por ejemplo la línea de código: scanf(“%s”,cad); De esta manera se lee desde el teclado una cadena y se guarda en el arreglo cad, sólo que en este caso no se incluye el operador & antes del nombre del arreglo, pues el identificador del arreglo almacena la dirección del primer elemento del mismo. La función gets() también nos permite leer del teclado una cadena y asignarla a un arreglo de tipo char, por ejemplo la instrucción: gets(cad); Lee una cadena desde el teclado y la almacena en el arreglo cad. Una diferencia importante entre usar scanf y gets es que con la primera la lectura de la cadena se da por terminada cuando el usuario presiona [Enter] o Espacio, mientras que la segunda termina la lectura de la cadena únicamente cuando el usuario presiona [Enter], tal como se muestra en los siguientes ejemplos: Cadena ingresada Instrucción Contenido del arreglo cad[] “Calle 2 #135” scanf(“%s”,c cad[]: ad); C a l l e / / … / 0 0 0 “Calle 2 #135” gets(cad); cad[]: C a l l e 2 # 1 3 5 / … / 0 0
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
133
Fundamentos de programación Programa Desarrollado
Similarmente, para imprimir en pantalla una cadena se puede utilizar la función printf con el especificador de formato %s, o bien, la función puts, nuevamente ambas funciones tienen un comportamiento similar con la única diferencia de que puts incluye siempre un salto de línea al final, esto se ilustra a continuación. Código c Impresión de cadena con printf
Ejecución
#include <stdio.h> #include <stdlib.h> main(){ char mensaje[30]=”Mar profundo ”; printf(“%s”,mensaje); system(“pause”); }
Impresión de cadena con puts #include <stdio.h> #include <stdlib.h> main(){ char mensaje[30]=”Mar profundo ”; puts(mensaje); system(“pause”); }
Las funciones que nos permiten el manejo de cadenas se encuentran en la biblioteca estándar string.h, para ilustrar algunas se muestra el siguiente programa en C. Ejemplo 5.3: El programa siguiente verifica si una clave (password) de 8 caracteres alfanuméricos ingresado por el usuario es correcta. /*Directivas de preprocesador*/ #include <stdio.h> #include <stdlib.h> #include <string.h> /* se incluye cadenas */ main( ) { /* Declaración de variables */ char pwscorrecto[9]=”jk278la0”;
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
la
biblioteca
de
/* Clave correcta */
134
Fundamentos de programación Programa Desarrollado
char pwsingresado[9]; /* para leer la clave que ingrese el usuario */ char nombre[10]; /* Para leer el nombre del usuario */ char mensaje[50]=”Bienvenido ”; /* Lectura de datos */ printf(“Nombre: "); gets(nombre); /* Lectura de una cadena con espacios */ printf(“pasword: "); scanf(“%s”,pwsingresado); /* Lectura de una cadena sin espacios*/ if (!strcmp(pwscorrecto,pwsingresado)){ /* comparación de claves, si la función strmp regresa 0 son i iguales */ printf(“pasword correcto \n”); strcat(mensaje,nombre); /* pega al final de mensaje el nombre del usuario*/ puts(mensaje); /* impresión de la cadena con salto de línea*/ } else { strcpy(mensaje, “Acceso denegado”); /* copia la cadena acceso denegado al mensaje */ puts(mensaje); /* imprime la cadena*/ } system("pause"); } Programa 5.3: password.c En la siguiente figura se muestran dos ejecuciones del programa
a) Clave inválida b) Clave válida Figura 5.10: Ejecución del programa password.c (Fuente: elaboración propia utilizando DevC++) Con esto se concluye la sección de arreglos, recuerda que un arreglo es un conjunto de dato del mismo tipo. En la siguiente sección verás cómo puedes agrupar datos de diferente tipo. Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
135
Fundamentos de programación Programa Desarrollado
5.2. Estructuras Las estructuras en C al igual que los arreglos nos permiten tratar a un conjunto de datos bajo un mismo identificador pero a diferencia de los arreglos las estructuras son conjuntos de datos contiguos en memoriano homogéneos de tal forma que una estructura puede estar formada por datos de diferentes tipos. Una de las aplicaciones para las estructuras es para la manipulación de registros que se recuperan o se almacenan en una base de datos. 5.2. Definición, declaración e inicialización “Una estructura es una colección de una o más variables, de tipos posiblemente diferentes, agrupadas bajo un nombre para manejo conveniente (en algunos lenguajes también se conocen como registros). Las estructuras permiten tratar a un grupo de variables relacionadas como una unidad, en vez de que se traten en forma separada (Kernighan & Ritchie, 1991, pág. 141)”. La definición de una estructura en C inicia con la palabra reservada struct seguida del identificador para el tipo de estructura y de un bloque de definiciones de variable que constituyen el conjunto de elementos que forman parte de ella, la sintaxis para definir la estructura es la siguiente: struct<identificadorEstructura>{ <tipo1><identificadorE1>; <tipo2><identificadorE2>; <tipoN><identificadorEN>; } Observa que se utiliza la palabra reservada struct para iniciar la definición y que las declaraciones para los elementos de la estructura se encierran entre llaves. Una estructura puede contener a N elementos de diferentes tipos, de cualquiera de los tipos básicos, o incluso un arreglo, veamos un ejemplo: struct paciente { int nss; /* número de seguro social */ char apellido[50]; char nombre[20]; int edad; float estatura; char sexo; }
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
136
Fundamentos de programación Programa Desarrollado
En este ejemplo se está definiendo la estructura paciente que tiene seis elementos: dos enteros (nss y edad), dos cadenas (apellido y nombre), un flotante (estatura) y un carácter (sexo). Sin embargo la definición anterior no reserva espacio en memoria para la estructura, más bien define un tipo de dato, por lo tanto para poder utilizar la estructura, es necesario declarar una variable de este tipo, es aquí cuando se reserva espacio en memoria. La sintaxis para hacer esta declaración es la siguiente: struct<identificadorEstructura><identificador_var>; Por ejemplo la declaración: struct paciente paciente1, paciente2; Declara a las variables paciente1 y paciente2, las cuales son del tipo paciente y por tanto para cada una de ellas se reserva espacio en memoria suficiente para cada uno de sus seis elementos. Otra forma válida de hacer la declaración es haciéndola seguida a la definición de la estructura, para el ejemplo anterior puede escribirse como sigue: struct paciente { int nss; char apellido[50]; char nombre[20]; int edad; float estatura; char sexo; } paciente1, paciente2; En este caso el identificador para el tipo de estructura puede omitirse, pero entonces la única forma de declarar variables para ese tipo de estructura es en su definición, y no en una declaración por separado, de tal forma que nuestro ejemplo puede quedar como sigue: struct { int nss; char apellido[50]; char nombre[20]; int edad; float estatura; char sexo; } paciente1, paciente2; Por otro lado, al igual que los arreglos, también se pueden inicializar los elementos de una estructura en el momento de la declaración de una variable del tipo de la estructura en cuestión, éstos deben estar encerrados entre llaves y separados por comas. La sintaxis general es la siguiente: Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
137
Fundamentos de programación Programa Desarrollado
struct<identificadorEstructura><identificador_var> = { <valorE1>,<valor2>,
,<valorN> };
Por ejemplo : struct paciente paciente1 = {1240, “PicaPiedra”, “Pedro”, 45, 1.80, „M‟}; Sólo en el momento de la declaración es posible asignar todos los valores de una estructura (al igual que con los arreglos), así que si después se quiere modificar tendrán que hacerse las modificaciones de forma separada en cada uno de sus elementos, como se muestra en el siguiente subtema. Actividad 2. Arreglos y estructuras. Retoma el programa que has trabajado para las evidencias de aprendizaje anteriores y realiza una versión preliminar del mismo pero ahora incorporando lo que has aprendido en esta unidad. Tu facilitador(a) te orientará si tienes dudas. Con esta actividad podrás prepararte para la entrega de tu evidencia de aprendizaje de la unidad. 5.2.2. Acceso a sus elementos Para referenciar un elemento de la estructura se utiliza el operador punto “.” con la siguiente sintaxis: <idenficador_var>.<idenficadorEi> Este operador seguido del identificador del elemento, referencia el elemento indicado, de tal forma que la sentencia para asignar al paciente1 un nss de 23442145 será: paciente1.nss = 23442145; Ahora, si se quiere asignar a la misma variable el nombre “Pablo”, la instrucción sería: paciente1.nombre = “Pablo”; Del mismo modo se realiza la impresión o lectura del elemento de la estructura, sin perder de vista su tipo. Para ilustrar esto se propone el siguiente ejemplo. Ejemplo 5.4: En el siguiente programa se declara una estructura de tipo perro, que tiene los siguientes elementos: Elemento Tipo Raza char[] Edad int Peso float
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
138
Fundamentos de programación Programa Desarrollado
Posteriormente se declaran dos variables de éste tipo, una se inicializa en la declaración y a la otra se le asignan valores desde el teclado, ambos se muestran al final en pantalla. #include <stdio.h> #include <stdlib.h> #include <conio.h> main(){ /* Declaración de la estructura perro*/ struct perro{ char raza[20]; int edad; float peso; } fido, pluto = {"labrador", 7, 20} ; /* inicialización de la variable pluto*/ printf("***********************************"); printf("\n* Comparando perros *"); printf("\n***********************************"); printf("\n\nIngresa la raza de fido:"); scanf("%s",&fido.raza); /* lectura de un elemento */ printf("Ingresa la edad de fido en a%cos:", 164); scanf("%d",&fido.edad); /* lectura de un elemento */ printf("Ingresa el peso de fido en kilos de fido:"); scanf("%f",&fido.peso); /* lectura de un elemento */ /* impresión de los elementos de las estructuras */ printf("\nFido es de raza %s, tiene %d a%cos kilos\n",fido.raza,fido.edad,164,fido.peso); printf("\nPluto es de raza %s, tiene %d a%cos kilos\n",pluto.raza,pluto.edad,164,pluto.peso);
y
pesa
%.2f
y
pesa
%.2f
/* comparación de los nombres que son cadenas */ if(!strcmp(pluto.raza,fido.raza)) printf("\nPluto Y Fido son de la misma raza \n"); else printf("\nFido y Pluto son de razas distintas\n"); /* comparación de elementos de tipo numérico */ if(pluto.peso > fido.peso)
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
139
Fundamentos de programación Programa Desarrollado
printf("Pluto es m%cs pesado que Fido\n",160); else if(pluto.peso < fido.peso) printf("Fido es m%cs pesado que Pluto\n",160); else printf("Fido y Pluto pesan lo mismo\n"); if(pluto.edad > fido.edad) printf("Pluto es mas viejo que Fido\n"); else if(pluto.edad < fido.edad) printf("Fido es mas pesado que Pluto\n"); else printf("Fido y Pluto tienen la misma edad \n"); getch(); } Programa 5.4: perros.c Nota: Observa que en este caso, para poder imprimir la letra ñ se utilizó su código Ascii (164) para lo cual en la cadena de control del printf se escribió %c en donde se desea imprimir la ñ. Este mismo truco se hizo para acentuar la letra a. En la siguiente figura se muestra una ejecución del programa anterior.
Figura 5.11: Ejecución del programa perros.c Actividad 1. Foro Estructuras de Datos –Ejercicio C Escribe, compila y ejecuta en la computadora el programa perros.c. Posteriormente, analiza cuáles son las principales diferencia entre las estructuras y los arreglos e ingresa tus comentarios en el Foro Estructuras de Datos. Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
140
Fundamentos de programación Programa Desarrollado
Para concluir con este capítulo veamos el siguiente ejemplo donde se utilizan estructuras y arreglos: Ejemplo 5.5:Se requiere un programa que permita registrar los datos de los perros que ingresan a refugio para perros, y poder desplegar los datos de alguno de los perros, a cada perro se le asigna una clave numérica consecutiva. Los datos que se registran del perro son: la fecha de ingreso (cadena) nombre (cadena) raza (cadena) color (cadena) edad (entero) peso (flotante) El refugio tiene capacidad máxima para 100 perros. Para la solución del problema se puede plantear un menú que permita registrar a un perro, o bien, desplegar los datos del perro solicitados. En este caso tenemos como datos de entrada la opción del menú que elija el usuario. En el caso de que sea un registro tendremos también se tienen como datos de entrada los datos del perro. Para la opción de despliegue se tendrá que dar como datos de entrada la clave del perro y la salida serán los datos correspondientes a la clave. Para desplegar y repetir el menú se requiere un ciclo y una estructura condicional que maneje las opciones del menú. Para almacenar los datos del perro, se puede utilizar una estructura similar al ejemplo anterior. Mediante un arreglo de estas estructuras estaremos en capacidad para manipular los datos de varios perros, el tamaño de este arreglo tendrá que ser igual a la capacidad del refugio (100 perros), de tal forma que el índice del arreglo que toca a cada perro corresponderá con su clave. Una restricción que hay que tomar en cuenta es que se debe verificar que no se sobre pase la capacidad de los 100 peros, tanto al ingresar datos como al recuperarlos, para ello se llevará un contador (c) que actualice el número de perros ingresados. Inicio c←0 Hacer Imprimir “Refugio para perros -Ladrido Feliz- ” Imprimir “1) Registrar un perro ” Imprimir “2) Buscar un perro ” Imprimir “3) Salir ” Imprimir “Elige una opción: ” Leer op Casos para op Caso 1: Si c≥100 entonces
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
141
Fundamentos de programación Programa Desarrollado
Imprimir “El refugio está lleno” Si no Imprimir “Ingresa los datos del perro:” Imprimir “Clave:” c Imprimir “fecha de ingreso[dd/mm/aa]: ” Leer perros[c].fecha Imprimir “color: ” Leer perros[c].color Imprimir “nombre: ” Leer perros[c].nombre Imprimir “raza: ” Leer perros[c].raza Imprimir “edad: ” Leer perros[c].edad Imprimir “peso: ” Leer perros[c].peso c ← c+1 Fin si-si no Caso2: Imprimir “Clave: ” Leer clave Mientras clave≥100 v clave <0 hacer Imprimir “La calve no es válida, ingresa nuevamente la clave:” Leer clave Fin mientras Imprimir “nombre:”, perros[clave].nombre Imprimir “fecha de ingreso:”, perros[clave].fecha Imprimir “color: ”, perros[clave].color Imprimir “raza: ”, perros[clave].raza Imprimir “edad: ”, perros[clave].edad Imprimir “peso: ”, perros[clave].peso Caso 3: Otro caso: Imprimir ”Opción no válida” Fin casos Mientras op≠3 Fin Hacer-mientras Fin Algoritmo 5.3. Registro perros
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
142
Fundamentos de programación Programa Desarrollado
La prueba de escritorio se deja como ejercicio al lector. En cuanto a la codificación del algoritmo se muestra a continuación. #include <stdio.h> #include <stdlib.h> #include <conio.h> main(){ /* Declaración del arreglo de tipo estructura perro */ struct perro{ char fecha[10]; char raza[30]; char color[50]; char nombre[30]; int edad; float peso; } perros[100]; int c=0, op, clave; do{
/* Inicio del ciclo que imprime el menú*/ printf( "\n----------------------------------------\n"); printf( "\nRefugio para perros -Ladrido Feliz- \n" ); printf( "\n----------------------------------------\n"); printf( "1) Registrar un perro \n" ); printf( "2) Buscar un perro \n" ); printf( "3) Salir \n" ); printf( "Elige una opci%cn:",162 );
scanf("%d",&op); switch (op){ case 1: /*Opción Registrar perro */ printf( "\n------------------------------\n"); if(c>=100) /* Verifica si hay espacio */ printf("El refugio esta lleno\n"); else{ /*Si hay espacio pide los datos del perro y Y los guarda en el registro c del arreglo */ printf( "Ingresa los datos del perro:"); printf( "Clave:%.3d\n", c); printf( "fecha de ingreso[dd/mm/aa]: "); scanf( "%s", perros[c].fecha); printf( "nombre: "); fflush(stdin); gets( perros[c].nombre); printf( "color: ");
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
143
Fundamentos de programación Programa Desarrollado
gets( perros[c].color); printf( "raza: "); gets( perros[c].raza); printf( "edad: "); scanf("%d" ,&perros[c].edad); printf( "peso: "); scanf("%f" ,&perros[c].peso); c++; } break; case 2: /* Opción buscar perro */ printf( "\n-------------------------------\n"); printf( "Clave: "); scanf("%d",&clave); /* verifica que la clave sea válida */ while(clave>=100 || clave <0){ printf("La calve no es válida, ingresa nuevamente la clave:"); scanf("%d",&clave); } /* Imprime los datos del perro correspondiente a la clave */ printf("nombre:%s\n",perros[clave].nombre); printf( "fecha de ingreso: %s\n", perros[clave].fecha); printf( "color: %s\n", perros[clave].color); printf( "raza: %s\n", perros[clave].raza); printf( "edad: %d a%cos\n", perros[clave]edad,164); printf( "peso: %.2f kilos\n", perros[clave].peso); break; case 3: /* Caso salir, no hace nada */ break; default: /* Caso opción inválida */ printf( "Opcion no valida\n"); } }while (op!=3); /* El ciclo do-while se repite mientras la opción no sea salir (3) */ }
Programa 5.5: registroPerros.c
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
144
Fundamentos de programación Programa Desarrollado
Evidencia de aprendizaje. Programa en C. Avance de solución del problema implementando las estructuras de datos Con ayuda de tu facilitador deberás acotar el problema que describiste en la evidencia de la unidad 1, de tal manera que la solución involucre a las estructuras de datos vistas en esta unidad. Para conocer los detalles de la actividad, ingresa al aula virtual. Consideraciones específicas de la unidad Para alcanzar los objetivos de esta unidad te recomendamos que escribas y compiles los programas que se desarrollaron a lo largo de la misma y realices una prueba de escritorio de cada uno de ellos, tal como se sugiere en las actividades opcionales. Referencias:
Cairo Osvaldo, Guardati Buemo Silvia. (1993). Estructura de Datos. México: McGraw-Hill.
Deitel H. M., Deitel P. J. (1995). Cómo programar en C/C++. México: Prentice Hall.
Joyanes, L., & Zohanero, I. (2005). Programación en C. Metodología, algoritmos y estructuras de datos. aspaño: Mc Graw Hill.
Kernighan, B., & Ritchie, D. (1991). El lenguaje de programción C. México: Prentice-Hall Hispanoamericana.
López, L. (2005). Programación estructurada en lenguaje C. México: Alfaomega.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
145
Fundamentos de programación Programa Desarrollado
Unidad 6: Funciones Propósitos En esta unidad: Identificarás los sub-problemas en que puede dividirse un problema. Diseñarás algoritmos modulares para solucionar un problema Construirás funciones en lenguaje C que realicen tareas específicas
Competencia específica Implementar funciones para resolver problemas a través del desarrollo de programas modulares escritos en lenguaje C. Introducción Hasta esta etapa del curso, has aprendido a utilizar las estructuras de control para diseñar soluciones de problemas simples. También has conocido diferentes formas de representar los datos involucrados en un problema, desde simples hasta estructurados (como arreglos, cadenas y estructuras). Sin embargo, todas las soluciones propuestas constan únicamente de un módulo (función), llamado principal (en C, main); lo cual no es conveniente cuando se trata de problemas complejos que requieran de una serie de tareas para lograr su solución, pues ésta sería muy grande y, por lo tanto, difícil de corregir o modificar. En estos casos lo recomendable es crear módulos independientes que realicen cada una de las tareas específicas y que en conjunto implementen la solución del problema. A esta metodología se le llama diseño modular, y está inspirado en la estrategia “divide y vencerás”. En esta unidad se explicarán las funciones, que son el medio por el cual se implementan los módulos en lenguaje C. Se presentará la sintaxis para crear una función y la forma en la que se utilizan. Además, se resolverá un problema utilizando el diseño modular para ejemplificar el tema. 6.1. Diseño descendente La descomposición de un programa en módulos más pequeños se conoce como el método de divide y vencerás (divide and conquer) o diseño descendente (top-down). Consiste en dividir un problema en unidades más pequeñas sucesivas hasta que sean directamente ejecutadas por el procesador, en otras palabras, la solución del problema se divide una y otra vez hasta que esté expresada en términos de estructuras de control, cada uno de los niveles o pasos sucesivos se conoce como refinamiento (stepwise). La metodología del diseño descendente consiste en efectuar una relación entre las etapas de estructuración de manera que se relacionen entre sí a través de entradas y salidas de datos. Es decir,
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
146
Fundamentos de programación Programa Desarrollado
se descompone el problema en etapas de estructuración jerárquicas, de forma que se pueda considerar cada estructura desde dos puntos de vista: ¿qué hace? y ¿cómo lo hace? Con lo anterior podemos decir que: un módulo se caracteriza por realizar una tarea específica, posee sus propios datos de entrada – llamados parámetros de entrada – y su resultado – llamado salida o valor de retorno –. El diseño de cada módulo debe ser independiente de los otros; si es necesario que exista comunicación entre ellos, ésta únicamente podrá realizarse a través de los parámetros de entrada y del valor de retorno. En este sentido, puede ser visto, por otros módulos, como una caja negra que hacia el exterior sólo muestra qué hace y qué necesita, pero no cómo lo hace. La creación de un modulo conlleva dos partes: la definición del módulo y la llamada o invocación (ejecución). La primera consta de tres partes: Definir los parámetros de entrada; Definir el valor de retorno; Escribir todas las instrucciones que le permitirán llevar a cabo la tarea, es decir, un algoritmo. La llamada o invocación a un módulo es el proceso de ejecutar el conjunto de instrucciones definidas en el módulo dado un conjunto de entradas específico. La forma general de invocar un módulo es escribiendo su nombre y entre paréntesis los valores de cada uno de los parámetros de entrada, respetando el orden que con el que se definió. No existe un método para saber en cuánto módulos se debe dividir un problema, sin embargo es importante tener en cuenta los siguientes principios del diseño modular: Las partes altamente relacionadas deben pertenecer a un mismo módulo. Las partes no relacionadas deben residir en módulos diferentes. Para ejemplificar esta forma de resolver problemas y cómo implementarla, se presenta la siguiente situación: Problema 6.1: Realiza el análisis y diseño de un programa que lea las temperaturas promedio mensuales registradas en una ciudad a lo largo de un año y calcule el promedio anual. Además, debe convertir las temperaturas mensuales dadas en grados Celsius a grados Fahrenheit al igual que el promedio. Empecemos por hacer un bosquejo de los pasos que se tienen que realizar para llegar al resultado deseado. 1. Leer las doce temperaturas promedio mensuales 2. Calcular el promedio anual de las temperaturas 3. Convertir las temperaturas promedio mensuales de Celsius a Fahrenheit 4. Convertir el promedio anual de temperaturas a Fahrenheit 5. Imprimir las temperaturas mensuales en grados Fahrenheit y el promedio anual de las temperaturas, en Celsius y Fahrenheit.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
147
Fundamentos de programación Programa Desarrollado
Para registrar las temperaturas mensuales proponemos utilizar un arreglo de tamaño 12. Y de acuerdo con lo anterior, proponemos tres módulos: El primero encargado de leer las temperaturas mensuales dadas en grados Celsius, este módulo necesita el nombre del arreglo donde va a almacenar los datos. Otro módulo encargado de calcular el promedio de las temperaturas, que recibe como parámetros de entrada el arreglo con las temperaturas mensuales y devuelve el promedio en grados Celsius. El último módulo sólo convierte grados Celsius a grados Fahrenheit. Esta información se resume en el diagrama modular que se muestra a continuación.
Figura 6.12: Diagrama modular del problema 6.1 Es mediante un diagrama modular como se representan de manera gráfica los módulos que integran la solución del problema. Y una vez que se han definido, el siguiente paso es diseñar el algoritmo de cada uno de ellos. En primer lugar se muestra el pseudocódigo de los módulos secundarios.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
148
Fundamentos de programación Programa Desarrollado
Módulo leerTemps(temp[ ]) Inicio Desde mes ← 1 mientras mes ≤ 12, mes ← mes + 1 Imprimir “Proporciona la temperatura del mes”, mes Leer temps[mes-1] Fin_Desde Fin
Algoritmo 6.4: Algoritmo del módulo leerTemps(temp[]) Observa que el ciclo del módulo leeTemps se inicia con mes igual a 1 y termina cuando mes es 13, se propone así porque se pide la temperatura de los mes 1, 2, 3,.. 12, así que la variable mes guardara el número de mes correspondiente a cada lectura, sin embargo para almacenar la temperatura en la posición del arreglo indicada se resta uno (temps[mes-1]), así se guarda desde la posición 0 y hasta la posición 11.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
149
Fundamentos de programación Programa Desarrollado
Módulo promTemps(temp[]) Inicio suma ← 0 Desde mes ← 0 mientras mes ≤ 11, mes ← mes + 1 suma ← suma + temps[mes] Fin_Desde Regresa (suma/12) Fin
Algoritmo 6.2: Algoritmo del módulo promTemps(temp[]) En contraste con el ciclo del módulo leerTemp, en este módulo el contador del ciclo se inicia en 0 y termina en 11 (aunque el valor que tiene al finalizar el ciclo es 12) pues se utiliza para ir sumando cada uno de los elementos del arreglo, así que la variable mes indicará cada una de las posiciones del arreglo. Módulo aFahrenheit(tempC) Inicio tempF = 9 5 tempC + 32 Regresa tempF Fin
Algoritmo 6.2: Algoritmos de módulos secundarios del problema 6.1 (pseudocódigo)
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
150
Fundamentos de programación Programa Desarrollado
A partir de los módulos secundarios presentados se puede plantear el módulo principal. Módulo Principal Inicio /* Lectura de las temperaturas, invocando al módulo leerTemps */ Imprimir “Ingresa los promedios de temperaturas mensuales” leerTemps(temps[]) /* Cálculo del promedio utilizando el módulo promTemps */ promC ← promTemps(temps[]) /* Conversión del promedio a grados Fahrenheit, invocando al módulo aFahrenheit */ promF ← aFahrenheit(promC) /* Conversión de las temperaturas mensuales a grados Fahrenheit */ Desde mes ← 0 mientras mes ≤ 11, mes ← mes + 1 tempsF[mes] ← aFahrenheit(temps[mes]) Fin_Desde /* Impresión de temperaturas mensuales en Fahrenheit */ Desde mes ← 1 mientras mes ≤ 12, mes ← mes + 1 Imprimir “Temperatura en Fahrenheit del mes”, mes, “ es: ”, tempF[mes-1] Fin_Desde /* Impresión del promedio en grados Celsius y grados Fahrenheit */ Imprimir “ El promedio en grados Celsius es: “, promC Imprimir “El promedio en grados Fahrenheit es: “, promF Fin Algoritmo 6.4: Algoritmo del módulo principal del problema 6.1 (pseudocódigo) Por esta ocasión se deja como ejercicio al lector que realice las representaciones en diagrama de flujo del módulo principal, considerando que el símbolo que se utiliza para llamar a módulos que no devuelven ningún valor, como es el caso se leerTemps se muestra a continuación: leerTemps(temp[])
Esto no es caso, del resto de los módulos secundarios que sí devuelven un valor, así que se utiliza el símbolo de proceso (rectángulo). Con el ejemplo anterior resaltan indudablemente varias ventajas que proporciona un diseño modular: 1. Es posible reutilizar código, ésta indudablemente es una de las más importantes ya que no es necesario escribir el mismo código cada vez que deseamos realizar una tarea semejante. Por
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
151
Fundamentos de programación Programa Desarrollado
ejemplo, el módulo aFahrenheit se utiliza 13 veces (12 en el ciclo y una para convertir el promedio) y sólo basto definirlo una vez. 2. Fácil detección y corrección de errores, dado que el problema fue divido en pequeños módulos cada uno responsable de una tarea, si en algún momento existiera un error en la solución global, basta identificar cuál de las tareas es la que no se está resolviendo adecuadamente y corregir únicamente aquellos módulos involucrados. 3. Fácil modificación o extensión, si se requiere modificar una tarea del problema o agregar una nueva, no será necesario rediseñar todo el algoritmo, basta con hacer las modificaciones en los módulos pertinente. 4. Un problema se vuelva más sencillo de solucionar si pensamos de manera modular. Una vez que se ha ilustrado como realizar una solución modular, lo siguiente es explicar cómo se codifica cada uno de los módulos, tema que se abordará en las siguientes secciones. } Actividad 1. Foro Funciones En esta actividad reflexionarás sobre las ventajas del diseño descendente y las funciones en Lenguaje C a partir de la solución modular del problema que planteaste en las unidades anteriores. Conforme avances en el diseño modular del mismo ingresa tus comentarios al respecto en el Foro Funciones. 6.2. Definición, declaración e invocación de funciones en C En el caso particular de C, un módulo se implementa como una función, recuerda que en la unidad 3 se explico que un programa en C está integrado de varias funciones, donde una función se define como una porción de código (un conjunto de instrucciones agrupadas por separado) enfocado a realizar una tarea en específico, resaltando la función principal main. Al igual que la función principal, cada una de las funciones existe de manera independiente, tiene sus propias variables, instrucciones y un nombre que las distingue de las otras. Además de los parámetros de entrada (también llamados argumentos) que recibe y el tipo de dato que regresa. La forma general para definir una función es: <tipo de dato retorno><identificador de la función>( <parámetros de entrada>) { <instrucciones de la función> return<expresión>; }
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
152
Fundamentos de programación Programa Desarrollado
El <tipo de dato retorno> indica el tipo de dato que la función devuelve (puede ser cualquiera de los tipos básicos), para lo cual se utiliza la palabra reservada return. Cuando la función no va a devolver ningún dato se especifica mediante el tipo void y no debe incluir la palabra reservada return. El <identificador de la función> es el nombre que le vamos a dar a la función y mediante el cual vamos a hacer referencia a ella. Se deben seguir las mismas reglas que los identificadores de las variables y se recomienda que sea nemónicos. Enseguida del nombre y entre paréntesis va la lista de parámetros, que consiste de una lista de declaraciones de variables locales que van a contener los datos de entrada para la función, se debe especificar explícitamente el tipo y nombre para cada uno, separados por comas, aún cuando sean del mismo tipo: tipo1 param1, tipo2 param2,…, tipoN paramN. Por último, las instrucciones del cuerpo de la función van entre llaves. La primera línea de la definición de una función se conoce como encabezado de la función (en inglés header). Para ilustrar esto, a continuación se muestra la codificación del módulo aFahrenheit definido en la sección anterior.
float aFahrenheit(float tempC) { return ((9.0/5.0)*tempC+32); } Programa 6.1: Codificación del módulo aFahrenheit La llamada o invocación a una función se realiza cuando se requiere que se ejecuten las instrucciones del cuerpo con valores de entrada determinados. Para invocar a una función se tiene que escribir el nombre seguido de los valores que deben coincidir con el orden, número y tipo de los parámetros de entrada dados en la definición de la función y deben estar encerrados entre paréntesis. La sintaxis general para invocar una función ya sea predefinida o definida por el programador, es la siguiente:
<identificador de la función>( <lista de valores>);
Los parámetros de entrada de una función son valores, por lo que pueden estar determinados por: valores constantes (8,‟a‟, 5.2, “cadena constante”) o una variable (lo que realmente se pasa a la función
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
153
Fundamentos de programación Programa Desarrollado
es el valor almacenado) o una expresión (el parámetro de entrada real es el resultado de la evaluación). Por ejemplo, la llamada a la función que definimos se remarcar en la siguiente instrucción: promF = aFahrenheit(promC);
Al igual que las variables una función debe de ser declarada antes de utilizarse, es decir, antes de invocarla. La declaración de una función se realiza escribiendo el prototipo de la función. El prototipo de una función coincide con el encabezado de la misma terminando con punto y como (;) El prototipo de una función sólo indica al compilador que existe y cómo es, más no lo que hace por lo tanto se debe definir después. Por ejemplo, el prototipo de la función antes definida sería: float aFahrenheit(float tempC); Cabe señalar que en el prototipo de las funciones se puede omitir los identificadores de los parámetros, más no los tipos. Para ilustrar todo lo anterior, a continuación se muestra la codificación del algoritmo modular diseñado en la sección anterior.
/* Programa: promedioTemp.c * Descripción: Calcula el promedio de las temperaturas promedio * mensuales registrada a lo largo de un año*/ /* Biblioteca */ #include<stdio.h> #include<stdlib.h> /* Variables globales */ int meses = 12; /* Prototipos de las funciones */ /* Función que lee las temperaturas promedio mensuales registradas en un año*/ void leerTemps( float temps[]); /* Función que calcula el promedio de las temperaturas promedio mensuales registradas en un año*/ float promTemps( float temps[]); /* Función que convierte de grados Celsius a grados Fahrenheit */
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
154
Fundamentos de programación Programa Desarrollado
float aFahrenheit(float tempC); /* Función principal */ main() { /* Declaración de variables locales a main */ float temps[12], tempsF[12], promF, promC; int mes; /* Lectura de las temperaturas, invocando a leerTemps*/ printf(“Ingresa los promedios de temperaturas mensuales\n”); leerTemps(temps); /* Cálculo del promedio utilizando la función promTemps */ promC = promTemps(temps); /* Conversión del promedio a grados Fahrenheit, invocando al módulo aFahrenheit */ promF = aFahrenheit(promC); /* Conversión de las temperaturas promedio grados Fahrenheit, invocando al módulo aFahrenheit */ for(mes = 0; mes<=11; mes++) tempsF[mes] = aFahrenheit(temps[mes]);
mensuales
a
/* Impresión de temperaturas promedio mensuales en grados Fahrenheti*/ for(mes = 1; mes<=12; mes++) printf(“\n La temperatura en grados Fahrenheit del mes %d es %.2f: ”, mes, tempsF[mes-1]); /* Impresión del promedio */ printf(“\n\n El promedio anual en grados Celsius es: %.2f ”, promC); printf(“\n El promedio anual en grados Fahrenheit es: %.2f ”, promF); system(“pause”); }
/* fin main */
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
155
Fundamentos de programación Programa Desarrollado
/* Definición de funciones */ void leerTemps (float temps[]) { /* Definición de variables locales a leerTemps */ int mes; for(mes = 1; mes<=12; mes++) { printf(“\n Ingresa la temperatura promedio del mes %d: ”, mes); scanf(“%f”, &temps[mes-1]); } } /* fin leerTemps */ float promTemps (float temps[]) { /* Definición de variables locales a promTemps */ int mes; float suma=0; for(mes = 0; mes<=11; mes++) suma = suma + temps[mes];
}
return (suma/12); /* fin leerTemps */
float aFahrenheit(float tempC) { return ((9.0/5.0)*tempC+32); } /* fin aFahrenheit */
Programa 6.1: promedioTemp.c
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
156
Fundamentos de programación Programa Desarrollado
Figura 6.2: Ejecución del programa promedioTemp.c Actividad 2. Funciones En esta actividad presentarás una versión preliminar del programa que has trabajado como parte de las evidencias de aprendizaje anteriores, el cual, ahora debe incorporar módulos para hacer más eficiente su funcionamiento. En el aula virtual encontrarás más detalles.
6.3. Alcance de las variables El alcance de las variables es la parte del programa dentro de la cual se pueden utilizar. Cuando son declaradas fuera del cuerpo de cualquier función se denominan variables globales y pueden ser utilizadas en cualquier punto del programa a partir del lugar donde fueron declaradas, en cambio cuando son declaradas dentro del cuerpo de alguna función se denominan variables locales a ésta, es Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
157
Fundamentos de programación Programa Desarrollado
decir sólo dentro de esa función pueden ser utilizadas. Las variables locales que tienen en el mismo nombre pero fueron declaradas en diferentes funciones, no tienen relación, son espacios de memoria totalmente independientes uno de otro. Podemos decir que, son como dos personas diferentes que tienen el mismo nombre. Por otro lado las variables que se ponen como argumentos en la declaración de una función se consideran locales a estas. Para ejemplificar lo anterior, se muestra el siguiente programa, en el cual se distinguen con diferentes colores el alcance de las variables. #include<stdio.h> #include<stdlib.h> int TAM = 5;
Variable global
void inicializaA(int A[]) { Variable local int i; for (i=0; i<TAM; i++) A [i] = 0; }
Variable local a inicializaA Referencia a una variable global
main() Declaración de { variables locales a main int i; int A[] = {1,1,1,1,1}; printf(“Arreglo antes de la llamada a inicializaA: A = [”); for (i=0; i<TAM; i++) { if(i< TAM -1) printf(“%d ,”,A[i]); else printf(“%d ]\n\n\t”,A[i]); } inicializaA(A); printf(“Arreglo despues de la llamada a inicializaA: A = [”); for (i=0; i<TAM; i++) { if(i< TAM -1) printf(“%d ,”,A[i]); else printf(“%d ]\n\n\t”,A[i]); } system(“pause”); } Programa 6.2: porReferencia.c
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
158
Fundamentos de programación Programa Desarrollado
Al utilizar variables globales todas las funciones pueden manipularlas, sus valores permanecen mientras el programa está en ejecución. Sin embargo su uso puede promover errores de tipo lógico, ya que al modificar el valor de una variable dentro de una función puede afectar el resultado de otra. Por ejemplo, supongamos que la función inicializaA() modifica el valor de la variable TAM que almacena el número de elementos del arreglo A, este cambio repercutirá en los ciclos de la función main, los cuales imprimen el arreglo A. En este caso se producirá un error en la ejecución, pues si el valor es menor a cinco no se imprimirán todos los valores y se es mayor entonces habrá elementos indefinidos. Detectar y corregir este tipo de errores puede ser una tarea nada fácil, por lo que no se recomienda el uso de variables globales, lo cual no ocurre si son constantes. Las variables locales por otra parte favorecen mucho la reutilización de código y la modularidad, ya que cada función declara y manipula sus propias variables sin depender de lo que ocurra en otras funciones, esto no significa que al utilizar solamente variables locales no sea posible compartir datos entre las diferentes funcione, esto se hace mediante sus datos de entrada y retorno, una posible desventaja es que el valor de las variables locales se pierde cada vez que la función termina. 6.4. Paso de parámetros EL paso de parámetros se refiere a la forma en la que se transfieren como parámetro una variable a una función, esencialmente, si se le otorgan o no permisos para modificar los valores originales. Cuando no se le otorga permisos para que la modifique se dice que es paso de parámetros por valor, pues en este caso sólo se transfiere el valor de la variable, el cual se almacena en una variable local de la función que se está llamando. En cambio, cuando la función puede modificar el valor de la variable se dice que es un paso de parámetro por referencia, pues en este caso no se pasa sólo el valor sino la dirección de memoria que le corresponde a la variable. En los siguiente subtemas se explica más a detalle los dos tipos de paso de parámetro. 6.4.1. Por valor Cuando se realiza una llamada a una función por valor y en ésta aparece una variable como uno de los argumentos, en realidad no se está pasando la variable sino una copia del valor que ésta contiene, lo cual implica que si dentro de la función se modifica el argumento esto no se ve reflejado en el programa desde el cual se hizo la llamada, pues son localidades de memoria diferentes (recuerda que en cada llamada a una función se crean nuevas variables y se destruyen una vez finaliza la ejecución). #include<stdio.h> #include<stdlib.h> void inicializa(int a) { a = 0;
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
159
Fundamentos de programación Programa Desarrollado
printf("\nEl valor de la variable local \"a\" es %d\n\n",a); } main() { int a=10; /* Llamada a la función incializa */ printf("\nEl valor de \"a\" antes de la llamada es %i\n\n", a); inicializa(a); printf("\nEl valor de \"a\" despues de la llamada es %i\n\n", a); system("pause"); } Programa 6.3: porValor.c La ejecución del programa es:
Figura 6.3: Ejecución del programa pasoValor.c En la ejecución puedes ver que la variable local a main no se modifica, esto es porque se pasa una copia del valor que almacena cuando se realiza la llamada a la función inicializa(a). Este valor se guarda en un espacio de memoria, también llamado a, que es una variable local a la función y que existe mientras ésta se ejecuta. Observa que el cambio si se realiza en la variable local de la función inicializa. 6.4.2. Por referencia La llamada a una función por referencia sí modifica el valor de la variable, pues lo que realmente se está pasando es la dirección de memoria asignada a la variable para que la función pueda modificar el valor. En C los arreglos siempre se pasan por referencia, ya que el nombre del arreglo en realidad almacena la dirección de memoria donde se encuentra almacenado el primer elemento del arreglo. De esta manera cuando se realiza una llamada a una función y se escribe el identificador de un arreglo como
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
160
Fundamentos de programación Programa Desarrollado
parámetro, se está pasando la dirección. Para ejemplificar lo anterior se muestra la ejecución del programa pasoReferencia.c que se presentó en un subtema anterior.
Figura 6.4: Ejecución del programa pasoRefencia.c
En la ejecución del programa se observa que después de la llamada a la función cambia el estado del arreglo A. Finalmente, cabe mencionar que para realizar la llamada por referencia de una variable de tipo básico en lenguaje C es necesario pasar la dirección de la variable para lo cual se utiliza el operador & seguido del nombre de la variable (&nombre), como se hace en la función scanf, este operador regresa la dirección de memoria que le corresponde a la variable indicada. Por otra parte, para almacenar la dirección de memoria de una variable se utiliza una variable de tipo apuntador. Una variable apuntador se encarga de almacenar una dirección de memoria, la declaración de una variable apuntador es similar a la de cualquier otra variable, con la diferencia que se debe escribir un asterisco entre el tipo de la variable y el identificador. El tema de los apuntadores es muy interesante, sin embargo, no es uno de los objetivos de este curso. Para que apliques lo aprendido en esta unidad y a lo largo del curso se propone la siguiente evidencia de aprendizaje. Evidencia de aprendizaje: Programa en C. Entrega final del programa modular que soluciona el problema planteado Esta es la última evidencia, deberás realizar el diseño modular del problema original que describiste en la evidencia de la unidad dos, así como la codificación de tu solución. Para conocer los detalles ingresa al aula virtual. Consideraciones específicas de la unidad Te sugerimos que escribas, compiles y ejecutes los programas que se desarrollaron a lo largo de esta unidad para que comprendas mejor los contenidos y te apropies de ellos.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
161
Fundamentos de programación Programa Desarrollado
Referencias
Deitel H, M., & Deitel P, J. Cómo programar en C/C++. México: Prentice Hall.
Joyanes, L., & Zohanero, I. (2005). Programación en C. Metodología, algoritmos y estructuras de datos. aspaño: Mc Graw Hill.
Kernighan, B., & Ritchie, D. (1991). El lenguaje de programción C. México: Prentice-Hall Hispanoamericana.
López, L. (2005). Programación estructurada en lenguaje C. México: Alfaomega.
Pérez, H. (1992). Física General (Primera Edición ed.). México: Publicaciones Cultura.
Educación Superior Abierta y a Distancia • Ciencias Exactas, Ingeniería y Tecnología
162