Colección Lectura de Cátedras
Caminando junto al Lenguaje C
Caminando junto al Lenguaje C
Autor: Martin Goin
San Carlos de Bariloche, 2015
Índice
Agradecimientos y Dedicatorias .................................................................................................. 8 Prólogo ........................................................................................................................................ 9 Contenido del Libro ................................................................................................................... 10 Capítulo I: Introducción al Lenguaje de Programación............................................................. 13 Conceptos básicos de programación .................................................................................. 13 Lenguaje de Programación ................................................................................................. 14 Fases para la creación de un programa ............................................................................... 19 Comencemos a programar .................................................................................................. 22 Lenguaje de programación C ............................................................................................. 24 Capítulo II: Pseudocódigo ......................................................................................................... 27 Algoritmos (Primeros pasos) .............................................................................................. 27 Variables y Constantes ....................................................................................................... 31 Identificadores para las variables y las constantes: ................................................... 32 Estructuras de Control ........................................................................................................ 33 Estructura de Control de Decisión: ........................................................................... 33 Operadores de Relación ...................................................................................................... 45 Operadores Lógicos ............................................................................................................ 48 Ejercicios: Pseudocódigo – Estructura de Control de Decisión ......................................... 52 Estructura de Control de Repetición ......................................................................... 55 Variables Contadoras y Sumadoras: ......................................................................... 59 Máximos y mínimos ........................................................................................................... 65 Ejercicios: Pseudocódigo – Estructura de Control de Repetición ...................................... 75 Capítulo III: Codificación.......................................................................................................... 75 Inclusión de Librerías: ........................................................................................................ 79 Declaración de Constantes: ................................................................................................ 81 Comienzo del Programa: .................................................................................................... 81 Tipos de Datos .......................................................................................................... 82 Cuerpo del Programa: ......................................................................................................... 85
Comentarios en la codificación ................................................................................. 89 Codificación en estructura de control de decisión .................................................... 91 Codificación en estructura de control de repetición.................................................. 98 La función getchar() ................................................................................................ 109 Librería ............................................................................................................. 111 Ejercicios: Pasar de Pseudocódigo a Código ................................................................... 113 Ejercicios: Para usar Librería ........................................................................... 113 Capítulo IV: Arreglos, Vectores o Matrices ............................................................................ 115 Vectores ............................................................................................................................ 116 Función rand() ......................................................................................................... 123 Vectores paralelos ................................................................................................... 125 Máximos y Mínimos con Vectores ......................................................................... 127 Ordenamiento en vectores....................................................................................... 129 Ordenamiento con vectores paralelos ..................................................................... 134 Ejercicios: Vectores .......................................................................................................... 136 Cadena de Caracteres ....................................................................................................... 139 Ingreso de texto por teclado .................................................................................... 140 Funciones para Cadena de Caracteres ..................................................................... 142 Ejercicios: Cadena de Caracteres ..................................................................................... 146 Matrices ............................................................................................................................ 147 Ejercicios: Matrices .......................................................................................................... 154 Capítulo V: Funciones ............................................................................................................. 157 Modularizar ...................................................................................................................... 157 Función ............................................................................................................................. 158 Definición de una función ....................................................................................... 159 Variables Globales y Locales .................................................................................. 169 Procedimiento ................................................................................................................... 171 Menús ............................................................................................................................... 179 Ejercicios: Funciones y Procedimientos ........................................................................... 183 Recursividad ..................................................................................................................... 186 Ejercicios: Recursividad ................................................................................................... 188
Estructura de datos ........................................................................................................... 189 Ejercicios: Estructura de Datos ........................................................................................ 194 Capítulo VI: Planilla de Cálculo - CALC ................................................................................ 195 Funciones del Calc ........................................................................................................... 198 Algunas funciones predefinidas: ...................................................................................... 201 Funciones lógicas Y, O ........................................................................................... 209 Referencias Relativas y Absolutas ................................................................................... 209 Ordenar datos en una planilla ........................................................................................... 212 BUSCARV ....................................................................................................................... 213 Crear Gráficos .................................................................................................................. 214 Ejercicios: Planilla de Cálculo - CALC ........................................................................... 216 Bibliografía .............................................................................................................................. 219
Agradecimientos y Dedicatorias
A mis seres queridos: mi hijo Fran, mi amor Ira, mi madre Marilú y mi padre Luis.
A mi entorno laboral: aquellos colegas que luchan por mejorar la educación.
Y a mis queridos/as alumnos/as que tuve, tengo y tendré a lo largo de mi docencia.
Caminando Junto al Lenguaje C
8
Prólogo
Este material de lectura tiene por objetivo presentar a los estudiantes la posibilidad de aprender y manejar de modo progresivo un lenguaje de programación, atendiendo principalmente a los aspectos prácticos del uso de algoritmos, sin descuidar los conceptos teóricos de cada tema. En particular se apunta a dar a conocer el Lenguaje C, muy utilizado en las cátedras universitarias. El libro que expone numerosos ejemplos, intenta ayudar y acompañar al lector a resolver los problemas planteados, es ideal para aquellos estudiantes que incursionan por primera vez en el mundo de la programación. El ejemplar funciona como un tutorial que explica paso a paso las bases de la programación de modo muy sencillo y está orientado a los primeros cursos de grado para carreras como ingeniería, profesorados, licenciaturas, tecnicaturas y otras disciplinas que incluyan materias de programación.
9
Martin Goin
Contenido del Libro
El material se divide en 6 capítulos
Capítulo I: Introducción al lenguaje de programación. Este capítulo es el único de carácter teórico y contiene los conceptos básicos de programación, los distintos tipos de lenguajes existentes, el ciclo de vida de un programa y una breve reseña histórica del lenguaje C y sus características principales. Concepto de Algoritmo.
Capítulo II: Pseudocódigo. Herramientas para desarrollar algoritmos en pseudocódigo. Variables y constantes. Estructuras de control de decisión (simple, doble, anidada y múltiple). Operadores de relación. Operadores lógicos (conjunción, disyunción y complemento). Variables contadoras y sumadoras. Estructura de control de repetición (exacta, anidada y condicional). Máximos y mínimos.
Capítulo III: Codificación Librerías. Declaración de variables y constantes. Tipos de variables primitivas (numéricas y carácter). Pasar de pseudocódigo a código los algoritmos. Distintas partes de un programa. Inclusión de comentarios en C. Codificación de las estructuras de control de decisión y repetición. La función getchar(). Librería math.h
Capítulo IV: Arreglos, Vectores o Matrices Concepto de Vectores. Vectores paralelos. Máximos y Mínimos con vectores. Búsqueda y edición. Ordenamiento de elementos (método burbuja). Cadena de Caracteres. Generación de números aleatorios. Ingreso y funciones para cadena de caracteres. Matrices.
Caminando Junto al Lenguaje C
10
Capítulo V: Funciones y Procedimientos Descomposición de programas en subprogramas. Modularización. Funciones. Pasaje de argumentos (tipos de parámetros). Ámbito de variables. Variables Locales y Globales. Procedimientos. Menús. Recursividad. Estructura de datos. Registros de datos. Arreglos de registros.
Capítulo VI: Planilla de Cálculo – Calc Descripción del Entorno gráfico y área de trabajo. Algunas herramientas del menú y barra. Principales funciones del Calc. Funciones con operadores lógicos. Ordenamientos de planillas. Referencias Relativas y Absolutas. Gráficos.
Cada capítulo, salvo el primero, contiene ejercicios para que resuelvan los estudiantes. En total son 213 ejercicios y además contiene un total de 93 ejemplos prácticos. El ultimo capitulo es un regalo que hace el autor al lector, donde presenta una guía rápida del programa Calc (Planilla de Cálculo) muy útil para su formación universitaria.
11
Martin Goin
Caminando Junto al Lenguaje C
12
Capítulo I: Introducción al Lenguaje de Programación
“Esta máquina puede hacer cualquier cosa que sepamos cómo ordenarle que la ejecute…” Ada Lovelace (1815 – 1852)
La frase pertenece a Ada Lovelace, considerada la primera programadora de computadoras de la historia, que escribió y publicó algoritmos para la Máquina Analítica de Charles Babbage en 1843.
Conceptos básicos de programación
Primero vamos a definir “programación”: Es la acción y efecto de programar. El verbo “programar” tiene varios usos: se refiere a ordenar e idear las acciones que se realizarán en el marco de un proyecto: por ejemplo la preparación de máquinas para cumplir con una cierta tarea específica, la preparación de un espectáculo deportivo o artístico, la preparación de datos necesarios para obtener la solución de un cálculo a través de una calculadora, Sistema y distribución de materias para una carrera o de temas para un curso o asignatura, etc. Pero en la actualidad la noción de programación se encuentra más asociada a la programación en informática. En este sentido “Programar” es el proceso por el cual un programador escribe, prueba, depura y mantiene un código usando un lenguaje de programación.
13
Martin Goin
Lenguaje de Programación
Lenguaje artificial que puede ser usado para controlar el comportamiento de una máquina, especialmente una computadora. Estos se componen de un conjunto de reglas sintácticas y semánticas que permiten expresar instrucciones que luego serán interpretadas. Debe distinguirse del “lenguaje informático”, que es una definición más amplia, porque muchas veces es utilizado como un sinónimo del lenguaje de programación. Un lenguaje informático no siempre es un lenguaje de programación. Por ejemplo el HTML (lenguaje de marca) es un lenguaje informático que describe a la computadora el formato o la estructura de un documento. (y no es un lenguaje de programación). Los lenguajes informáticos engloban a los lenguajes de programación. El programador es el encargado de utilizar un lenguaje de programación para crear un conjunto de instrucciones que, al final, constituirá un programa o subprograma. En definitiva, los lenguajes utilizados para escribir programas que puedan ser entendidos por las computadoras se denominan “Lenguajes de programación”
Los lenguajes de programación se clasifican en tres grandes categorías: Lenguaje máquina, Lenguaje de bajo nivel y Lenguaje de alto nivel.
Lenguaje máquina: Son aquellos cuyas instrucciones son directamente entendibles por la computadora. Las instrucciones en lenguaje máquina se expresan en términos de la unidad de memoria más pequeña, es decir el bit (dígito binario 0 y 1). El lenguaje será entendible por el procesador, pero poco claros para el programador. Entonces para simplificar el lenguaje máquina, aparecieron los lenguajes de bajo nivel.
Lenguajes de bajo nivel (ensambladores) Estos lenguajes son generalmente dependientes de la máquina, es decir dependen de un conjunto de instrucciones especificas de la computadora
Caminando Junto al Lenguaje C
14
En este lenguaje las instrucciones se escriben en códigos alfabéticos, conocidos como nemotécnicos (abreviaturas de palabras). ADD SUB LDA STO
Suma Resta Cargar acumulador almacenar
Por ejemplo: ADD X,Y,Z (esta instrucción significa que se deben sumar los números almacenados en las direcciones X e Y y el resultado quedará en la dirección Z) Lo anterior traducido a lenguaje máquina será: 1110 1001 1010 1011 El ASSEMBLER es el primer lenguaje de este nivel.
Lenguajes de alto nivel (evolucionados): Son lenguajes cuyas instrucciones son escritas con palabras similares a los lenguajes humanos (por lo general en inglés), facilitando su comprensión. Estos lenguajes son transportables (con pocas o ninguna modificación), es decir que pueden ser utilizados en diferentes tipos de computadoras. Otra propiedad es que son independientes de la máquina, esto es la sentencia del programa no dependen del diseño del hardware. Incluyen rutinas de uso frecuente como las entradas y salidas, funciones matemáticas, manejo de tablas, etc. (Que figuran en librerías del lenguaje), de manera que puedan utilizarse siempre que se las requiera sin tener la necesidad de programarlas cada vez. Los lenguajes de alto nivel no son entendibles directamente por la máquina (se alejan del procesador), entonces necesitan ser traducidos. Si volvemos al ejemplo anterior, la suma de los números X e Y que queda almacenado en Z será simplemente como una operación aritmética Z=X+Y (asignación)
Los programas escritos en un lenguaje de alto nivel se llaman “programa fuente”
15
Martin Goin
Existen muchos lenguajes de alto nivel, los principales son: C/C++, Visual Basic, Pascal, PHP, Python, Matlab, PL/SQL, Java y Fortran.
Los lenguajes de programación pueden, en líneas generales, dividirse en dos categorías: o Lenguajes interpretados o Lenguajes compilados
Lenguaje interpretado Un lenguaje de programación es, por definición, diferente al lenguaje máquina. Por lo tanto, debe traducirse para que el procesador pueda comprenderlo. Un programa escrito en un lenguaje interpretado requiere de un programa auxiliar (el intérprete), que traduce los comandos de los programas según sea necesario. Ejemplos de lenguajes interpretados: ASP, Basic, JavaScrip, Logo, Lisp, Perl, PHP, VBScrip, Python, etc
Lenguaje compilado Un programa escrito en un lenguaje "compilado" se traduce a través de un programa anexo llamado compilador. El compilador traduce el programa fuente a uno llamado programa objeto. Este programa objeto se utiliza en la fase de ejecución del programa, obteniendo un programa ejecutable (que no requiere ninguna traducción). Un programa escrito en un lenguaje compilado posee la ventaja de no necesitar un programa anexo para ser ejecutado una vez que ha sido compilado, entonces se vuelve más rápida. Sin embargo, no es tan flexible como un programa escrito en lenguaje interpretado, ya que cada modificación del archivo fuente (el archivo comprensible para los seres humanos: el archivo a compilar) requiere de la compilación del programa para aplicar los cambios. Ejemplos de lenguajes compilados: ADA, C, C++, Cobol, Fortran, Pascal, Algol, etc.
Caminando Junto al Lenguaje C
16
Se han propuesto diversas técnicas de programación cuyo objetivo es mejorar tanto el proceso de creación de software como su mantenimiento. Entre ellas, se pueden mencionar las siguientes:
Programación Lineal
Programación Estructurada
Programación Modular
Programación Orientada a Objetos (POO)
La mejor forma de explicar dichas técnicas es a través de su evolución histórica en los lenguajes de alto nivel. Tradicionalmente, la programación fue hecha en una manera secuencial o lineal, es decir una serie de pasos consecutivos con estructuras consecutivas y bifurcaciones. Los lenguajes basados en esta forma de programación ofrecían ventajas al principio, pero el problema ocurre cuando los sistemas se vuelven complejos y extensos. Frente a esta dificultad aparecieron los lenguajes basados en la programación estructurada. Esta programación estructurada utiliza un número limitado de estructuras de control, reduciendo así considerablemente los errores Esta técnica incorpora: Diseño descendente (top-dow): el problema se descompone en etapas o estructuras jerárquicas. Recursos abstractos (simplicidad): consiste en descomponer las acciones complejas en otras más simples capaces de ser resueltas con mayor facilidad.
Estructuras básicas: existen tres tipos de estructuras básicas: Estructuras secuénciales: cada acción sigue a otra acción secuencialmente. La salida de una acción es la entrada de otra. Estructuras selectivas: en estas estructuras se evalúan las condiciones y en función del resultado de las mismas se realizan unas acciones u otras. Se utilizan expresiones lógicas.
17
Martin Goin
Estructuras repetitivas: son secuencias de instrucciones que se repiten un número determinado de veces. Estos programas no ofrecen flexibilidad y el mantener una gran cantidad de líneas de código en sólo bloque se vuelve una tarea complicada, entonces surgió la idea de programación modular que consiste en separar las partes complejas del programa en módulos o segmentos, esto debe hacerse hasta obtener subproblemas lo suficientemente simples como para poder ser resueltos fácilmente. Ésta técnica se llama refinamiento sucesivo, “divide y vencerás”. De esta manera tenemos un diseño modular, compuesto por módulos independientes que puedan comunicarse entre sí. Poco a poco este estilo de programación fue reemplazando al estilo impuesto por la programación lineal. Entonces, vemos que la evolución que se fue dando en la programación se orientaba siempre a ir descomponiendo más el programa. Este tipo de descomposición conduce directamente a la programación orientada a objetos. Pues la creciente tendencia de crear programas cada vez más grandes y complejos llevó a los desarrolladores a crear una nueva forma de programar que les permita crear sistemas de niveles empresariales y científicos muy complejos. Para estas necesidades ya no bastaba la programación estructurada ni mucho menos la programación lineal. Es así como aparece la programación orientada a objetos (POO). Básicamente la POO simplifica la programación con la nueva filosofía y nuevos conceptos que tiene. La POO se basa en dividir el programa en pequeñas unidades lógicas de código, aumentando considerablemente la velocidad de desarrollo de los programas. A estas pequeñas unidades lógicas de código se les llama objetos. Los objetos son unidades independientes que se comunican entre ellos mediante mensajes. Lo interesante de la POO es que proporciona conceptos y herramientas con las cuales se modela y representa el mundo real tan fielmente como sea posible.
El principal problema que presentan los lenguajes de alto nivel es la gran cantidad que existen en la actualidad. No existe el mejor lenguaje (algunos son más apropiados para ciertas cosas)
Caminando Junto al Lenguaje C
18
Fases para la creación de un programa
Definición del Problema: Esta fase está dada por el enunciado del problema, el cual requiere una definición clara y precisa. Es importante que se conozca lo que se desea que realice la computadora; mientras esto no se conozca del todo no tiene mucho caso continuar con la siguiente etapa.
Análisis del Problema: Esta fase requiere de una clara definición, donde se contemple exactamente lo que debe hacer el programa y el resultado o solución deseada, entonces es necesario definir:
Los datos de entrada (tipo y cantidad)
Cual es la salida deseada (tipo y cantidad)
Los métodos y fórmulas que se necesitan para procesar los datos.
En esta etapa se determina “que” hace el programa. Una recomendación muy práctica es el de ponernos en el lugar de la computadora y analizar que es lo que necesitamos que nos ordenen y en que secuencia para producir los resultados esperados.
Diseño del Algoritmo: En esta etapa se determina “como” se hace el programa. El diseño del algoritmo es independiente del lenguaje de programación. Las herramientas para diseñar algoritmos son: Diagrama de Flujo y Pseudocódigo El Diagrama de Flujo: Es una representación gráfica de un algoritmo
19
Martin Goin
El Pseudocódigo: Las instrucciones se representan por medio de frases o proposiciones en español que facilitan tanto la escritura como la lectura de programas Si queremos crear el pseudocódigo del diagrama de flujo anterior, entonces: ingresar A y B si A > B entonces asignar a C = A + 10 sino asignar a C = B - A fin Si
La programación se apoya en los métodos llamados “algoritmos”. La definición del algoritmo es: “una secuencia no ambigua, finita y ordenada de pasos para poder resolver un problema”.
Las características de un buen algoritmo son:
Debe tener un punto particular de inicio (programa principal). El módulo de nivel más alto que llama a (subprogramas) módulos de nivel más bajos.
Caminando Junto al Lenguaje C
20
Debe ser definido, no debe permitir dobles interpretaciones.
Debe ser general, es decir, soportar la mayoría de las variantes que se puedan presentar en la definición del problema.
Debe ser finito en tamaño y tiempo de ejecución.
Adicionalmente los algoritmos pueden requerir de datos de entrada para producir datos de salida.
• Datos de Entrada: un algoritmo tiene cero o más entradas, es decir cantidades que le son dadas antes de que el algoritmo comience, o dinámicamente mientras el algoritmo corre. • Procesamiento de Datos: aquí incluye operaciones aritmético-lógicas, selectivas y repetitivas; cuyo objetivo es obtener la solución del problema. • Salida de Resultados: permite comunicar al exterior el resultado. Puede tener una o más salidas.
Codificación: La codificación es la operación de escribir la solución del problema (de acuerdo a la lógica del diagrama de flujo o pseudocódigo), en una serie de instrucciones detalladas, en un código reconocible por la computadora. Estas instrucciones detalladas se le conoce como código fuente, el cual se escribe en un lenguaje de programación o lenguaje de alto nivel.
Prueba y Depuración: Los errores humanos dentro de la programación de computadoras son muchos y aumentan considerablemente con la complejidad del problema. El proceso de identificar y eliminar errores, para dar paso a una solución sin errores se le llama depuración. 21
Martin Goin
La prueba consiste en la captura de datos hasta que el programa no presente errores (los más comunes son los sintácticos y lógicos).
Documentación: Describe los pasos a dar en el proceso de resolución de un problema. La importancia de la documentación debe ser destacada en el producto final. Programas pobremente documentados son difíciles de leer, más difíciles de depurar y casi imposibles de mantener y modificar. A menudo un programa escrito por una persona, es usado por otra. Por ello la documentación sirve para ayudar a comprender o usar un programa o para facilitar futuras modificaciones. La documentación de un programa puede ser interna o externa. La primera es la contenida en líneas de comentarios y la segunda incluye análisis, diagrama de flujo y/o pseudocódigo, manuales de usuario con instrucciones para ejecutar el programa y para interpretar los resultados.
Mantenimiento: Se lleva a cabo después de terminado el programa, cuando se detecta que es necesario hacer algún cambio, ajuste o complementación al programa para que siga trabajando de manera correcta. Para poder realizar este trabajo se requiere que el programa este correctamente documentado.
Comencemos a programar
Partimos de la definición del problema. La mejor y típica manera de empezar es con algo cotidiano y simple como la preparación del mate. Teniendo en cuenta que los ingredientes son: la yerba y el agua y los utensillos son: el mate, la bombilla, la pava y el termo.
Agregar yerba al mate
Caminando Junto al Lenguaje C
22
llenar agua en la pava Encender la hornalla Colocar la pava sobre la hornalla Esperar hasta que tenga la temperatura adecuada Verter el agua de la pava al termo Poner la bombilla en el mate Verter el agua del termo en el mate (cebar el mate) Observar: En un número finito de pasos se pudo resolver el problema planteado. En este caso, son 8 los pasos a seguir para que el mate quede listo. Las instrucciones son precisas. En cada paso, es claro qué acción realizar. Las recetas culinarias son un claro ejemplo de algoritmo. Existe un problema, elementos para solucionarlos, un procedimiento a seguir y un resultado que es el plato listo.
Pre y post condiciones En el ejemplo del mate se puede observar que existen condiciones que se deben cumplir antes de realizar el algoritmo (como por ejemplo, disponer de todos los ingredientes y de los utensilios). A estas condiciones que son necesarias que se cumplan antes de comenzar la ejecución del algoritmo, se las llama pre-condiciones. Se pueden asumir como verdaderas antes de comenzar con la ejecución de las acciones especificadas en el algoritmo. De la misma forma, existen condiciones post-ejecución, las cuales son condiciones que surgen a partir de la ejecución del algoritmo. Las instrucciones de un algoritmo se pueden repetir un número finito de veces (si ellas mismas indican repetición) pero un algoritmo debe terminar después de ejecutar un número finito de instrucciones, sin importar cuáles fueron los datos o elementos de entrada. Una instrucción es una acción a ejecutar (la puede ejecutar cualquier entidad: un hombre, una computadora, un auto, etc). Dicha instrucción se debe poder realizar o llevar a cabo en un número finito de pasos. Es necesario que la instrucciones sean precisas, que sólo signifiquen una sola cosa y que estén libres de ambigüedades.
23
Martin Goin
Habíamos dicho que existen una gran cantidad de lenguajes de programación, algunos con propósito específico y otros de uso generalizado como el lenguaje C que es el que vamos a abordar en este libro.
Lenguaje de programación C
El lenguaje C es uno de los lenguajes de programación más populares en el mundo, ejecutándose en la mayoría de los sistemas operativos y pueden ser usados en casi todas las plataformas informáticas. Este lenguaje fue creado en 1972 por el estadounidense Dennis M. Ritchie en los laboratorios Bell. En un principio se creó para desarrollar softwares de sistemas (conjuntamente con el UNIX), ampliando más tarde su potencial para desarrollar softwares de aplicaciones. Puede ser que dicho lenguaje sea más difícil de aprender que otros, pero su ventaja es la versatibilidad que ofrece. Los programas desarrollados en lenguaje C pueden ser más pequeños que los mismos hechos en otros lenguajes y por ende son más rápidos. Una desventaja es que es un lenguaje más tolerante a los errores de programación que otros, lo que significa que un descuido puede causar grandes consecuencias. Uno de los objetivos de diseño del lenguaje C es que sólo sean necesarias unas pocas instrucciones en lenguaje máquina para traducir cada elemento del lenguaje, sin que haga falta un soporte intenso en tiempo de ejecución. Es posible escribir C a bajo nivel de abstracción; de hecho, C se usó como intermediario entre diferentes lenguajes.
Hay una versión muy interesante en el origen del lenguaje que dice que el C fue el resultado del deseo de los programadores Thompson y Ritchie para jugar al Space Travel (1969). Habían estado jugando en el mainframe de su compañía, pero debido a su poca capacidad de proceso y al tener que soportar 100 usuarios, no tenían suficiente control sobre la nave para Caminando Junto al Lenguaje C
24
evitar colisiones con los asteroides. Por ese motivo decidieron portar el juego a otra máquina ubicada en otro sector de la compañía. El problema era que dicha máquina no tenía sistema operativo, así que decidieron escribir uno. Como el sistema operativo de la máquina que poseía el juego estaba escrito en lenguaje ensamblador ASSEMBLER, decidieron usar un lenguaje de alto nivel y portátil. Consideraron usar B (Lenguaje anterior al C), pero carecía de las funcionalidades necesarias para aprovechar algunas características avanzadas, entonces empezaron a crear uno nuevo, el lenguaje C.
Imagen de Wikipedia: Ritchie (parado) junto a Thompson (sentado) año 1972. Ambos trabajando con la PDP-11
25
Martin Goin
Las principales características que posee el lenguaje C son:
Es un lenguaje de programación de nivel medio ya que combina los elementos del lenguaje de alto nivel con la funcionalidad del ensamblador.
Sirve para crear aplicaciones y software de sistemas.
Es portable, es decir, posibilitando la adaptación de programas escritos para un tipo de computadora en otra.
Es de fácil aprendizaje.
Posee un completo conjunto de instrucciones de control.
Al ser un lenguaje estructurado se divide el programa en módulos, lo que permite que se puedan compilar de modo independiente.
El código generado por el lenguaje es muy eficiente ya que los datos son tratados directamente por el hardware de números, caracteres y direcciones de los computadoras.
Trabaja con librerías de funciones en las que básicamente sólo se necesitan cambiar los valores dentro de una aplicación dada.
Es uno de los lenguajes más populares. Muy utilizado, especialmente en el campo de la ingeniería y el campo científico.
Dispone de excelentes compiladores de C gratuitos, para casi cualquier plataforma sobre la que se quiera trabajar y con entornos de programación claros y funcionales
“UNIX es simple. Sólo necesita un genio para entender su simplicidad” Dennis Ritchie (1941 – 2011)
Dennis Ritchie fue un científico en computación que colaboró con el desarrollo del sistema operativo UNIX y creador del lenguaje de programación C junto a Ken Thompson.
Caminando Junto al Lenguaje C
26
Capítulo II: Pseudocódigo
En el capítulo anterior hemos definido el algoritmo como “una secuencia no ambigua, finita y ordenada de pasos para poder resolver un problema”. El diseño del algoritmo es independiente del Lenguaje de programación, el mismo puede ser usado para cualquier lenguaje de programación. Anteriormente habíamos mencionado las distintas maneras de expresar un algoritmo (gráfico con diagrama de flujo y textual con pseudocódigo), en nuestro caso trabajaremos con el último. El pseudocódigo está diseñado para facilitar su comprensión, en lugar de la lectura mediante la computadora. También se utilizan en la planificación del desarrollo de programas informáticos, para esquematizar la estructura del programa antes de realizar la efectiva codificación. No existe una sintaxis estándar para el pseudocódigo, pero en definitiva se parecen. En nuestro caso, el pseudocódigo que utilizaremos en el libro, está muy ligado al lenguaje C, es decir conserva en gran medida la sintaxis del código. En principio la escritura será rígida, pero la gran ventaja estará en el pasaje del pseudocódigo al código ya que será casi directo.
Algoritmos (Primeros pasos)
Tabla de herramientas básicas La siguiente tabla muestra algunas de las herramientas básicas del pseudocódigo y su significado. Pseudocódigo
Significado
comienzo()
Determina el inicio del algoritmo
27
Ejemplo
Martin Goin
Debe estar siempre en todo algoritmo ingresar
Sirve para ingresar datos por teclado
ingresar( A); → ingresa un dato para la variable A ingresar (A,B); → ingresa un dato para cada variable A y B
imprimir
Muestra por pantalla un dato, un cartel o ambas
imprimir (A); → imprime por pantalla el dato que tiene la variable A imprimir (“Así es la vida”); → imprime por pantalla el cartel “Así es la vida” imprimir (“El promedio es ”,P); → imprime por pantalla “El promedio es 176.34” ,en este caso la variable P contiene dicho valor numérico. imprimir (“El área es ”,A,” y el perímetro es “,P); → imprime por pantalla “El área es 84.7 y el perímetro es 56” ,en este caso se pueden alternar cartel y variables.
{}
Denota el comienzo → { y el fin →} de un grupo de sentencias y/o el propio algoritmo como se observa en el ejemplo.
comienzo() { ingresar (A,B); P = (A+B)/2;
Nota: todo algoritmo debe imprimir (“El promedio es tener el comienzo y las llaves. “,P); En un algoritmo puede haber } más de { }, siempre y cuando resulten equilibradas, es decir que existan la misma cantidad de llaves que abren { con las que cierran } =
Asignación
P=A+B; C=8;
Caminando Junto al Lenguaje C
28
D=7+A; ;
Fin de sentencia
Se observan en los ejemplos anteriores.
Nota: A medida que vamos avanzando incorporaremos más pseudocódigo. Todas las palabras claves como “comienzo”, “ingresar” e “imprimir” van siempre en minúscula.
Atención. Las operaciones aritméticas deben expresarse siempre en una línea, por ejemplo si queremos realizar la siguiente operación: entonces debemos escribirlo de la siguiente manera: C = (-B+9)/(2*A) El asterisco * representa en programación la multiplicación y la barra inclinada a derecha / la división.
La mejor manera de empezar a entender los algoritmos es a través de ejemplos prácticos. A continuación veremos algunos ejemplos de algoritmos expresados en pseudocódigo:
Ejemplo 1: Ingresar tres números y mostrar la sumatoria de los mismos. comienzo() { ingresar (A,B,C); S = A+B+C; imprimir (“La suma es “,S); → Claramente se ve que se imprime el cartel “La suma es “ y el valor que contiene S } Nota: en la primera línea comienzo() no lleva “;”
29
Martin Goin
Ejemplo 2: Ingresar la temperatura actual en Celsius y mostrar la misma en Fahrenheit. comienzo() { ingresar (C); F = 9/5*C+32; imprimir (“La temperatura en Fahrenheit es “,F); }
Ejemplo 3: Hallar el perímetro y el área de un rectángulo ingresando sus lados. comienzo() { ingresar (a,b); P = 2*a + 2*b; A = a*b; imprimir (“El perímetro del rectángulo es “,P); imprimir (“El área del rectángulo es “,A); } Nota: En el ejemplo 3 se ve claramente que las letras A,P,a y b son variables y que en nuestro caso se diferencian las minúsculas de las mayúsculas (esto no sucede en todos los lenguajes de programación)
Caminando Junto al Lenguaje C
30
Variables y Constantes
Un objeto es una Variable, cuando su valor puede modificarse y además posee un Nombre que lo identifica y un Tipo que describe su uso. Un objeto es una Constante, cuando su valor no puede modificarse y además posee un Nombre que lo identifica y un Tipo que describe su uso.
Cuando definimos una variable, estamos creando un identificador (nombre de la variable) que hace referencia a un lugar de la memoria donde se almacena un dato. La diferencia respecto de la definición de una constante, es que en el momento de su creación, el valor del objeto es desconocido, mientras que para una constante no solamente es conocido sino que permanece inalterado durante la ejecución del procedimiento resolvente. Recuerde que la definición de los objetos, siempre tiene lugar en el Ambiente.
Ejemplo 4: Hallar el área y el perímetro de una circunferencia ingresando el radio r. En este caso debemos utilizar π para los dos cálculos (como no podemos denominarlo con el símbolo para usarlo en el algoritmo, lo llamaremos PI). Al mantenerse inalterable lo definimos como una constante. definir PI 3.1416 comienzo() { ingresar (r); P = 2*PI*r; A = PI*r*r; → r2 lo expresamos simplemente como r*r imprimir (“El perímetro de la circunferencia es “,P); imprimir (“El área de la circunferencia es “,A);
31
Martin Goin
} Nota: Las constantes se definen antes de la palabra comienzo y no llevan “=” ni “;”
Identificadores para las variables y las constantes:
Los nombres o etiquetas de las variables y constantes siempre deben empezar con una letra (Mayúscula o minúscula) y no puede contener espacios en blanco, si usamos más de un carácter para su identificación empezamos con la letra y luego podemos seguir con números o letras. Esta permitido usar “_” entre medio y no esta permitido usar palabras reservadas (reservadas por el propio lenguaje de programación).
Ejemplos válidos: A, a , B1 , A20 , AA1 , Aa1 , B2B , Promedio , SUMATORIA , A_1 , b1_2 Ejemplos no validos: 1B , 2c , _S , ¿A, La variable
Se recomienda que el nombre represente el dato en si y que no sea extenso, algunos ejemplos: Para una sumatoria → S Para dos sumatorias → S1 , S2 Para la sumatoria de edades → SE Para contar → C Para un promedio → P o Prom Para el promedio de edades de mujeres → PEM
En el caso del lenguaje C se diferencian los identificadores escritos en mayúsculas con las minúsculas, por ejemplo la variable “a” podría representar la longitud de un lado de un poliedro y la variable “A” el área de de dicho poliedro.
Caminando Junto al Lenguaje C
32
Estructuras de Control
Las estructuras de control nos permiten controlar el flujo del programa: tomar decisiones, realizar acciones repetitivas etc, dependiendo de unas condiciones que nosotros mismos establezcamos. El concepto de flujo de control se refiere al orden en que se ejecutan las sentencias o acciones de un programa. En los anteriores ejemplos hemos visto un flujo lineal también llamado “Estructura secuencial”, pero existen también la estructura alternativa y la de repetición, siendo métodos que permiten desviarse de la estructura secuencial.
Estructura de Control de Decisión:
También llamada de alternativa, permite bifurcar el “flujo” del programa en función de una expresión lógica o condición lógica. Con frecuencia aparecen en algoritmos situaciones en donde se debe elegir un camino dependiendo de los datos de entrada y la condición impuesta. Existen a su vez tres estructuras de decisión: simple, doble y múltiple.
Estructura de Control de decisión Simple: Veamos un ejemplo de un algoritmo que utilice una decisión simple:
Ejemplo 5: Mostrar el perímetro de una circunferencia, siempre y cuando el radio que se ingresa sea mayor a cero. definir PI 3.1416 comienzo()
33
Martin Goin
{ ingresar (r); si (r > 0) { Peri = 2*r*PI; imprimir (“El perímetro de la circunferencia es ”,Peri); } } Nota: Se observa que las dos sentencias que se encuentran dentro del si (el cálculo del perímetro y la impresión del mismo) están delimitados por las llaves { } porque deben escribirse siempre y cuando tengamos más de una sentencia en una decisión. En este caso si se comete el error de ingresar un radio negativo o cero, el programa simplemente termina, ya que solo funciona cuando la condición r > 0 (expresión lógica) sea verdadera. Además lo que se encuentra dentro del si esta tabulado a derecha. Esta técnica se llama “indentación”
Indentación: También se lo conoce como “sangrado”. La palabra es de origen inglés “indentation” y se trata de la sangría y saltos de línea para mejorar la legibilidad de los algoritmos. Si escribimos el algoritmo de modo compacto, es decir sin tabulaciones, ni saltos el programa no sufre efecto alguno, pero dificulta en la interpretación del programador. Por ejemplo el ejemplo 5 podría escribirse en una línea, de la siguiente forma: comienzo(){ingresar (r);si (r > 0) circunferencia es ”,Peri);}}
{Peri = 2*r*PI;imprimir (“El perímetro de la
Estructura de Control de decisión Doble: Esta estructura es similar a la anterior con la salvedad de que se indican acciones no sólo para la rama “verdadera” sino también para la “falsa”; es decir, en caso de que la expresión lógica sea cierta se ejecutan una acción o grupo de acciones y en caso de que sea falsa se ejecuta el otro grupo de acciones.
Caminando Junto al Lenguaje C
34
Ejemplo 6: Ídem al ejemplo anterior pero en el caso de ingresar un radio erróneo (cero o negativo) indicarlo con el cartel “Error en el ingreso”. comienzo() { ingresar (r); si (r > 0) { Peri = 2*r*PI; imprimir (“El perímetro de la circunferencia es ”,Peri); } sino imprimir (“Error en el ingreso”);
} Nota: Cuando es falsa la expresión lógica (r > 0) se ejecuta lo que está dentro del “sino”. A medida que se van incorporando estructuras de control en el algoritmo se va indentando las sentencias que se encuentran dentro de las mismas. Además se ve claramente que la instrucción imprimir (“Error en el ingreso”); que está dentro del “sino” no tiene llaves, porque solo se trata de una sentencia.
Veamos otro ejemplo:
Ejemplo 7: Mostrar el número más grande (entre dos) ingresado por pantalla. comienzo() {
35
Martin Goin
ingresar (A,B); si (A > B) imprimir (“El número ”,A,” es el mayor”); sino imprimir (“El número ”,B,” es el mayor”);
} Nota: Claro que este algoritmo funciona cuando los valores A y B ingresados sean distintos. ¿Qué sucede si ingresamos dos valores iguales? ¿Cuál sería el resultado?
Atención: Se recomienda en una estructura de control de decisión doble NO dejar vacio el si por ocupar el sino. En el ejemplo 5 podríamos haber hecho la condición del si con (r < = 0) en vez de (r > 0), entonces nos quedaría de la siguiente manera: comienzo() { ingresar (r); si (r B) imprimir (“El número ”,A,” es el mayor”); sino si (A == B) imprimir (“Son iguales”);
37
Martin Goin
sino imprimir (“El número ”,B,” es el mayor”);
} Nota: Dentro del sino se encuentra otra estructura si porque si no es A > B caben dos posibilidades, que sean iguales o que B > A. Es importante respetar la indentación a medida que se van agregando estructuras dentro de otras.
El ejemplo anterior podía haberse realizado de otra manera, por ejemplo:
Ejemplo 9: comienzo() { ingresar (A,B); si (A == B) imprimir (“Son iguales”); sino si (A > B) imprimir (“El número ”,A,” es el mayor”); sino imprimir (“El número ”,B,” es el mayor”);
} Nota: Es decir comenzando a preguntar por si son iguales o también así podríamos hacerlo de la siguiente manera:
Caminando Junto al Lenguaje C
38
Ejemplo 10: comienzo() { ingresar (A,B); si (A >= B) si (A == B) imprimir (“Son iguales”); sino imprimir (“El número ”,A,” es el mayor”); sino imprimir (“El número ”,B,” es el mayor”); } Nota: En este caso la anidación se produce en el si y no en el sino como los ejemplos 8 y 9. Prueba hacer el algoritmo si comenzamos con la expresión B > A y otro algoritmo con B ≥ A
Estructura de Control múltiple: El problema que presenta el si anidado es cuando tenemos numerosas alternativas. Por ejemplo si nos piden mostrar el nombre del mes ingresando su número, tendremos 12 alternativas, es decir once si anidados (no se cuenta el ultimo por defecto).
Ejemplo 11: Ingresar el número del mes para mostrar su nombre, usando anidamiento. comienzo() { ingresar (M); si (M == 1)
39
Martin Goin
imprimir (“Enero”); sino si (M == 2) imprimir (“Enero”); sino si (M == 3) imprimir (“Marzo”); sino si (M == 4) imprimir (“Abril”); sino si (M == 5) imprimir (“Mayo”); sino si (M == 6) imprimir (“Junio”); sino si (M == 7) imprimir (“Julio”); sino si (M == 8) imprimir (“Agosto”); sino si (M == 9)
Caminando Junto al Lenguaje C
40
imprimir (“Septiembre”); sino si (M == 10) imprimir (“Octubre”); sino si (M == 11) imprimir (“Noviembre”); sino imprimir (“Diciembre”); } Nota: Para anidar N alternativas se necesitan siempre N-1 si anidados
La solución más económica será la utilización de la estructura de control “según - caso” que trabaja como un distribuidor de casos. Veamos como se implementa en el ejemplo anterior:
Ejemplo 12: Ingresar el número del mes para mostrar su nombre, usando control múltiple. comienzo() { ingresar (M); según (M) { caso 1: imprimir (“Enero”); salir;
41
Martin Goin
caso 2: imprimir (“Febrero”); salir; caso 3: imprimir (“Marzo”); salir; caso 4: imprimir (“Abril”); salir; caso 5: imprimir (“Mayo”); salir; caso 6: imprimir (“Junio”); salir; caso 7: imprimir (“Julio”); salir; caso 8: imprimir (“Agosto”); salir; caso 9: imprimir (“Septiembre”); salir;
Caminando Junto al Lenguaje C
42
caso 10: imprimir (“Octubre”); salir; caso 11: imprimir (“Noviembre”); salir; defecto: imprimir (“Diciembre”); salir; } } Nota: La estructura “según” necesita solo del par de llaves { } para delimitar todos los casos. Cada “caso” debe terminar con un “salir” para saltear los casos consecutivos y la última alternativa se obtiene por defecto.
Ejemplo 13: Ingresar dos números y el operador aritmético (suma “+”, resta “-“, producto “*” o división “/”) para realizar el cálculo y mostrar el resultado. comienzo() { ingresar (A,B); ingresar (operador); según (operador) { caso “+”: R = A + B; salir; 43
Martin Goin
caso “-”: R = A - B; salir; caso “*”: R = A * B; salir; caso “/”: R = A / B; salir; defecto: R = 0; salir; } imprimir (“El resultado es “, R); } Nota: En estos casos el defecto se utiliza por si no ingresamos correctamente el operador aritmético, en estos casos se determino que su resultado sea directamente cero. Además existe un inconveniente en la división si el denominador B es igual a cero, para poder solucionar el problema se podría incorporar a este caso una decisión como se muestra a continuación: caso “/”: si (B ==0) R = 0; sino R = A / B; salir; En estos casos el resultado devolverá cero si B es nulo. Claramente se ve que se pueden combinar los distintos tipos de alternativas.
Caminando Junto al Lenguaje C
44
¿Cómo podríamos mejorar el ejercicio 13 para que devuelva un mensaje de error en el caso de un operador mal tipeado y/o el denominador en cero cuando queremos dividir?
Operadores de Relación A continuación veremos una tabla con todos los operadores de relación que se utilizan para expresar las condiciones entre dos valores: Operador
> < >= < ≥ ≤ = ≠
Nota: Es importante el orden en los símbolos >= y = 4)
Decisión Doble: Existen dos alternativas, cuando la condición sea verdadera y cuando sea falsa
si (nota >= 4)
{ sentencias;
imprimir (“Aprobó”);
} si (condición) { sentencias; } sino {
Caminando Junto al Lenguaje C
46
imprimir (“Aprobó”); sino imprimir (“Desaprobó”);
sentencias; } si (condición) si (condición) { sentencias; }
Decisión Anidada: Cuando tenemos más de una condición (una dentro de otra).
si (nota >= 4)
Existen dentro del si y/o dentro del sino
sino
sino
si (nota < 7) imprimir (“Aprobó”); imprimir (“Promocionó”); sino
{
imprimir (“Desaprobó”);
sentencias; } según (variable) { caso valor: sentencias; salir; .
Decisión Múltiple: Cuando tenemos muchas alternativas en la condición. Si no se cumple ninguna de las condiciones la opción es por “defecto”.
según (alerta_de_incendio) { caso 1: imprimir(“Bajo: estado verde”); salir; caso 2:
. .
imprimir(“Moderado: estado azul”);
defecto:
salir; caso 3:
sentencias;
imprimir(“Alto: estado amarillo”);
salir; }
salir; caso 4: imprimir(“Muy Alto: estado naranja”); salir; defecto: imprimir(“Extremo: estado rojo”); salir; }
47
Martin Goin
Operadores Lógicos
Existen tres Operaciones Lógicas fundamentales: Conjunción Lógica o Producto Lógico: El operador correspondiente se representa mediante los símbolos '^' (propio de la Lógica Proposicional) 'AND' y '.' En el Lenguaje de Programación C se utiliza el símbolo '&&'. El efecto de este Operador es la evaluación simultánea del Estado de Verdad de la variables lógicas involucradas. Llamamos Estado de Verdad, a uno cualquiera de los dos valores del conjunto Lógico. En tal sentido a los Operadores Lógicos en general, se los denomina Conectores Lógicos, puesto que "conectan" predicados (o variables lógicas). Así tendremos, por ejemplo que la expresión : A && B, será Verdadera únicamente si A y B lo son. Cualquier otro arreglo de Estados de Verdad para ambas variables, dará como resultado el Valor Falso, puesto que basta con que una de la dos variables tenga valor Falso, para que ambas no sean simultáneamente Verdaderas. Variables Lógicas P Q Verdadero Verdadero Verdadero Falso Falso Verdadero Falso Falso
Resultado P && Q Verdadero Falso Falso Falso
Disyunción Lógica Inclusiva o Suma Lógica: El Operador correspondiente, se representa mediante los símbolos 'v' (propio de la Lógica Proposicional), 'OR' y '+' En el Lenguaje de Programación C se utiliza el símbolo '||'. El efecto de este operador, es la evaluación no simultánea del Estado de Verdad de las variables lógicas involucradas. Esto implica que al tener Estado Verdadero por lo menos una de las variables afectadas, la operación dará un resultado verdadero. Así tendremos que la expresión : A || B, será Falsa únicamente cuando el Estado de ambas variables sea Falso. En cualquier otro caso, la operación será Verdadera.
Caminando Junto al Lenguaje C
48
Variables Lógicas P Q Verdadero Verdadero Verdadero Falso Falso Verdadero Falso Falso
Resultado P || Q Verdadero Verdadero Verdadero Falso
Negación o Complemento Lógico: Este Operador representado por un guión sobre la Variable a Complementar ejemplo Ᾱ y también la palabra ‘NOT’ al aplicarse a un predicado lógico (simple o compuesto) , devuelve el valor opuesto; es decir : si el predicado en cuestión es Falso, el resultado será Verdadero y recíprocamente. En el Lenguaje de Programación C se utiliza el símbolo '!'. Variable Lógica P Verdadero Falso
Resultado !P Falso Verdadero
Por ejemplo si tenemos la expresión : !( A || B ), devolverá como resultado verdadero, únicamente cuando las variables A y B adopten simultáneamente el estado falso.
Ejemplo 16: Verificar que el número ingresado esta dentro del intervalo 10 y el 20 (incluidos) comienzo() { ingresar (N); si (N >= 10 && N = 15 && T 20) imprimir (“Hay riesgo alto de incendio”); }
Ejemplo 18: Mostrar un cartel “Número elegido” para aquellos que cumplen con alguna o las dos condiciones siguientes (que sea par o que sea negativo) comienzo() { ingresar (N); si (N % 2 == 0 || N < 0) imprimir (“Número elegido”); }
Caminando Junto al Lenguaje C
50
Ejemplo 19: Mostrar un cartel “Número no elegido” para aquellos que NO cumplen con alguna de las dos condiciones siguientes (que sea múltiplo de 3 o que sea mayor a 30) comienzo() { ingresar (N); si ! (N % 3 == 0 || N >=30) imprimir (“Número no elegido”); }
51
Martin Goin
Ejercicios: Pseudocódigo – Estructura de Control de Decisión
1)
Diseñar un algoritmo que, dados dos números, imprimir su suma.
2)
Diseñar un algoritmo que imprima el cuadrado y el cubo de un número ingresado.
3)
Diseñar un algoritmo que imprima el número siguiente al ingresado.
4)
Hallar la energía según la masa m sabiendo que la velocidad de la luz c es igual a 2.997925 x 1010 con la famosa formula de Einstein E=cm2
5)
Hallar el resultado de ex usando la siguiente serie de Taylor:
,
el usuario debe ingresar solo el valor de x 6)
Ingresar un número y mostrar dos resultados que provienen del mismo: aumentado un 10% y disminuido en un 20%
7)
Diseñar un algoritmo que imprima el área de un triángulo cuya base y altura se ingresan por teclado. (área = (b * h) / 2)
8)
Diseñar un algoritmo que imprima el perímetro de un triángulo cuyos 3 lados se ingresan por teclado. (perímetro = a + b + c)
9)
Diseñar un algoritmo que, dados tres números, calcule e imprima el promedio.
10)
Diseñar un algoritmo que, dadas las longitudes de los lados de un trapecio, calcule e imprima su perímetro.
11)
Diseñar un algoritmo que, dado el peso de un objeto en Kg, calcule y muestre dicho peso en libras (1 libra es igual a 0.453592 Kg.).
12)
Diseñar un algoritmo que calcule el volumen de un cilindro dado su radio y altura (volumen=2.π.r.h).
13)
Diseñar un algoritmo para calcular el porcentaje de hombres y de mujeres que hay en un grupo, dados los totales de hombres y de mujeres.
14)
Un profesor corrige un examen y según el puntaje de 1 a 100 (números naturales) debe calificar al alumno respetando la siguiente tabla:
Caminando Junto al Lenguaje C
52
Nota 1 2 3 4 5 6 7 8 9 10
15)
Puntaje 0 -29 30 – 47 48 – 59 60 – 65 66 – 71 72 – 77 78 – 83 84 – 89 90 – 95 96 - 100
Para que una persona prepare 3 equipos de rescate A, B y C. Se sabe que se tarda 15 minutos en preparar el equipo A, 20 con el equipo B y 23 con el equipo C. La cantidad de rescatistas según el equipamiento se ingresan por teclado (cantidad de A, de B y de C). ¿Cuántos minutos tardará dicha persona en preparar los equipos de todos los rescatistas?
16)
Ingresar dos números naturales y mostrar el menor suponiendo que son distintos.
17)
Diseñar un algoritmo que indique con carteles si el número ingresado es negativo, positivo o nulo.
18)
Ingresar un número y mostrar un cartel que indique si el mismo es entero o real.
19)
Diseñar un algoritmo que indique si el número ingresado es par o impar. El n° ingresado es > 0.
20)
Ingresar un número y luego mostrar el número consecutivo siguiente al ingresado que sea par.
21)
Ingresar un número y luego mostrar el número consecutivo siguiente al ingresado que sea impar.
22)
Ingresar tres números y mostrar el mayor (asuma que los n° son distintos).
23)
Ingresar tres números y mostrar el mayor y el menor (asuma que los n° son distintos).
53
Martin Goin
24)
Repita el ejercicio anterior pero utilizando el operador lógico Y (&&) en las condiciones para minimizar su cantidad.
25)
Diseñar un algoritmo que imprima el número de docena (“primera”, “segunda” o “tercera”) dado el resultado de una jugada de ruleta. Utilizar el operador lógico Y (&&).
26)
Diseñar un algoritmo que imprima “par” si el valor ingresado es 2, 4, o 6; “impar” si es 1, 3, o 5; y en cualquier otro caso “error”. Utilizar el operador lógico O (||).
27)
Diseñar un algoritmo que, dado un número, imprima “Verdadero” si está entre 0 y 10 e “Falso” si es mayor a 10 o menor a cero. a) Resolver el ejercicio con el operador lógico Y (&&). b) Resolver el ejercicio con el operador lógico O (||).
28)
Un empleado cobra según la categoría (A - $7500, B - $9500, C - $11500) y según su antigüedad se le aumenta ( 20) ) ) { S = S + N; C++; ingresar(N); }
69
Martin Goin
P = S/C; imprimir (“El promedio es “,P); } Nota: Como no sabemos de entrada la cantidad de números que se van a ingresar entonces debemos usar un contador C para poder finalmente hallar el promedio. El inconveniente que puede presentar este algoritmo es que de entrada no se cumpla la condición del mientras, por lo tanto el valor de C terminaría en cero generando un error en la división al hallar el promedio P. Esto se podría resolver agregando antes de dicho cálculo la siguiente sentencia si. (se muestra en negrita) comienzo() { S = 0; C = 0; ingresar(N); mientras ( !( (N % 2 == 1) && (N > 20) ) ) { S = S + N; C++; ingresar(N); } si(C == 0) imprimir(“No hubo números de ingreso”); sino { P = S/C; imprimir(“El promedio es “,P); } }
Ejemplo 30: Contar la cantidad de veces que se ingresa números pares y la cantidad de números impares hasta que se ingrese un número negativo. El cero no se cuenta.
Caminando Junto al Lenguaje C
70
comienzo() { CP = 0; CI = 0; ingresar(N); mientras ( N > = 0 ) { si ((N % 2 == 0) && (N != 0)) CP++; sino si ((N % 2 == 1) && (N != 0)) CI++; ingresar(N); } imprimir (“La cantidad de números pares es “,CP); imprimir (“La cantidad de números impares es “,CI); } Nota: Mientras N no sea negativo el bucle sigue iterando. Para incrementar los contadores se les agregó a las condiciones (N != 0) porque el enunciado del problema así lo determinaba.
Al igual que la sentencia para y la sentencia si, se pueden anidar los mientras.
Estructura de control de repetición (Sentencia “hacer - mientras”) Esta estructura repite una instrucción o grupo de instrucciones hasta que una expresión lógica sea cierta.
71
Martin Goin
Un aspecto muy importante de la presente estructura de control es que la expresión lógica no se evalúa hasta el final de la estructura con lo cual el bucle se ejecuta al menos una vez, contraria a la estructura “mientras” que podía no ejecutarse nunca. Es decir que después de cada iteración el bucle evalúa la condición, si es verdadera sigue repitiendo y si la condición es falsa termina.
Ejemplo 31: Hacer un algoritmo que muestre del 0 al 20 (solo los números pares). comienzo() { N = 0; hacer { imprimir(N,” “); N = N + 2; } mientras ( N < 21 ) } Nota: A medida que va iterando el bucle se incrementa N de dos en dos, en la última repetición se imprime 20 y se incrementa en 22, por lo tanto termina porque la condición ahora es falsa.
Ejemplo 32: En un bosque se necesita saber el promedio de diámetro de cada tronco de ciprés y el promedio de su altura. El proceso termina cuando el usuario responde con una ‘N’, mientras tanto debe responder con ‘S’. comienzo() { C = 0;
Caminando Junto al Lenguaje C
72
SA = 0; SD = 0; hacer { ingresar(A,D); SA = SA + A; SD = SD + D; C++; imprimir(”¿Desea seguir ingresando datos? S/N“); ingresar(opcion); } mientras ( opcion == ‘S’ ) PA = SA/C; PD = SD/C; imprimir (“El promedio de altura de los cipreses es “,PA); imprimir (“El promedio de diámetro de los cipreses es “,PD); } Nota: La variable opcion está reservada para que el usuario responda S o N (si quiere seguir ingresando o no). Tomar en cuenta que para seguir ingresando datos el usuario debe presionar solo la S (mayúscula). Para resolver este problema se podría poner la siguiente condición en el mientras (opcion == ‘S’ && opcion == ‘s’) Por otra parte este tipo de estructura sirve para que al menos se ingrese los datos de un árbol, por eso no es necesario verificar si el denominador es nulo en los promedios.
Al igual que en las anteriores estructuras, es posible crear algoritmos que tengan bucles “hacer-mientras” una dentro de otra.
73
Martin Goin
Tabla de estructura de control de repetición Pseudocódigo
Significado
Ejemplo
para (valor inicial; condición; incremento/decremento)
Bucle de repetición exacto.
para(i=0; i < 10; i++)
Se sabe de antemano la cantidad de iteraciones que cumple el bucle.
imprimir(“3 X “,i,”→”,i*3);
{ sentencias; }
{
} Imprime la tabla de multiplicación del 3.
mientras (condición) { sentencias; }
hacer { sentencias; } mientras(condición)
Bucle de repetición condicional.
i = 1; mientras (i La librería que nunca puede faltar es stdio.h que contiene los prototipos de funciones y los tipos de datos para manipular sus entradas y salidas. Es decir que siempre comenzaremos por incluir en nuestros programas la siguiente línea: #include < stdio.h > Existen otras librerías, a continuación veremos algunas de las más importantes:
#include < stdlib.h > Contiene tipos, macros y funciones para la conversión numérica, generación de números aleatorios, búsquedas y ordenación, gestión de memoria y tareas similares.
#include < string.h > Contiene los prototipos de las funciones y macros de clasificación de caracteres.
#include < math.h > Contiene los prototipos de las funciones y otras definiciones para el uso y manipulación de funciones matemáticas.
#include < time.h > Contiene los prototipos de las funciones, macros, y tipos para manipular la hora y la fecha del sistema. Caminando Junto al Lenguaje C
80
Atención: En un programa se pueden utilizar más de una librería y el orden es indistinto, siempre y cuando se ubiquen en la cabecera. En el pseudocódigo no escribíamos este dato.
Declaración de Constantes: La sintaxis para definir las constantes en el lenguaje C es de la siguiente manera: #define nombre_constante valor_constante
Por ejemplo si queremos incluir la constante π en el programa, la sintaxis es la siguiente: #define PI 3.1416
Si se tratara de más de una constante, las mismas se definen una debajo de la otra. Atención: La declaración de constantes no necesita ; (punto y coma) para finalizar la línea de comando.
Comienzo del Programa: En el pseudocódigo lo llamábamos de la siguiente manera comienzo() en codificación será: main()
Declaración de Variables: Este dato en el pseudocódigo era invisible, porque se daba por entendida dicha declaración. La sintaxis es: tipo_variable nombre_variable; Ejemplos: int A; 81
Martin Goin
int A,B; float suma; char C1; float S1,S2;
Atención: En este lenguaje no puede quedar ninguna variable sin declarar. Además es importante saber que se diferencian las minúsculas de las mayúsculas.
Tipos de Datos
Por Tipo de Datos, entenderemos la Clase que agrupa Datos con idénticas capacidades de operación. Existen diferencias entre los distintos lenguajes de programación en cuanto a los Tipos de Datos que se utilizan, las operaciones permitidas entre ellos y el modo en que pueden organizarse (Estructuras más complejas). En principio veremos los tipos de Datos Primitivos o Básicos. Cada Tipo de Dato Primitivo o Básico, define como se mencionó anteriormente, el conjunto de valores que puede asumir una variable, así definida. Los Tipos de Datos Básicos que maneja el lenguaje son: Numérico y carácter. Estos Tipos se aplican tanto a las Variables como a las Constantes, pero debe observarse que una variable de un determinado Tipo, sólo puede tomar como valor una constante del mismo Tipo. A continuación, se analizarán cada uno de los distintos Tipos Básicos mencionados:
Tipo Numérico: Básicamente se distinguen dos Subtipos : Tipo Numérico Entero. Caminando Junto al Lenguaje C
82
Tipo Numérico Real.
Los Datos Numéricos Enteros se denotan con int (integer en inglés, entero en español) y long (largo en inglés, es decir entero largo) Su sintaxis es: int nombre_variable; long nombre_variable; → para valores muy grandes y/o muy chicos
Los Datos Numéricos Reales, su representación es apelando a un punto Decimal que separe la mantisa de la parte entera de la parte decimal. Se denotan con la palabra float, que significa punto flotante y double que es el punto flotante largo. Su sintaxis es: float nombre_variable; double nombre_variable; → para valores muy grandes y/o muy chicos
Tipo Caracter: Involucran a un conjunto ordenado y finito de símbolos que el procesador puede reconocer. Si bien no existe un conjunto estándar, podemos decir que dicho conjunto está básicamente integrado por:
1) Letras mayúsculas (desde la A hasta la Z), sin incluir la CH y la LL (eventualmente puede no ser incluida la Ñ). 2) Letras minúsculas (desde la a hasta la z), con las mismas restricciones que para las mayúsculas. 3) Dígitos (del 0 al 9). 4) Caracteres especiales. Están incluidos aquí símbolos tales como: 83
Martin Goin
*,+,-,:,;,,,",/,,=,|,\,~,@,#,$,.,%,^,&,(,),{,},[,],`,!,?,' y otros. El espacio en blanco, también es considerado como un caracter. La sintaxis es: char nombre_variable; char es la reducción de la palabra en inglés “character” que significa carácter.
Atención: En C los caracteres van delimitados por comillas simples como en el lenguaje algorítmico. Por ejemplo: categoría = ‘A’
A continuación mostramos una tabla con los tipos de datos básicos y sus rangos de valores: TIPO char int long float double
ANCHO EN BIT 8 16 32 32 64
RANGO EN PC -128 a 127 -32768 a 32767 -2147483648 a 2147483647 3.4E-38 a 3.4E+38 1.7E-308 a 1.7E+308
Podemos sintetizar los Tipos de Datos Primitivos mediante el esquema que se presenta a continuación:
Caminando Junto al Lenguaje C
84
Cuerpo del Programa: Esta es la sección en donde aparece el algoritmo. Es aquí donde se encuentra la traducción del programa escrito en pseudocódigo a código. El cuerpo del programa se encuentra encerrado entre las llaves { } del main(). A continuación veremos un ejemplo muy sencillo de un algoritmo en pseudocódigo y su codificación:
Ejemplo 1: Mostrar el siguiente cartel “Bienvenidos a la Codificación”. Pseudocódigo
Código #include
comienzo()
main()
{
{
imprimir (“Bienvenido a la codificación”);
printf(“Bienvenido a la Codificación”);
}
}
Se observa que en el código se agrega la librería stdio.h en la primera línea, comienzo se reemplaza por main, las llaves quedan iguales y la función imprimir se traduce al código con printf
Atención: Importante es saber que las palabras reservadas del código se escriben en minúsculas.
Ejemplo 2: Mostrar la suma de tres números siendo: A = 5, B = 8 y C = 1. Pseudocódigo
Código
85
Martin Goin
#include comienzo()
main()
{
{ int A, B, C, suma;
A = 5;
A = 5;
B = 8;
B = 8;
C = 1;
C = 1;
suma = A + B + C;
suma = A + B + C;
imprimir (“La suma es ”,S);
printf(“La suma es %i”,S);
}
}
En estos casos se observa que en el código se declaran las variables A, B, C y suma de tipo entero (int), invisible para el pseudocódigo. La declaración de variables se puede realizar por separado. Para el ejemplo anterior será: int A; int B; int C; int suma;
Pero nos resulta más cómodo y económico agruparlo en una sola línea Las asignaciones y el cálculo de la suma son idénticos, pero la impresión tiene una diferencia además de su traducción imprimir → printf.
Caminando Junto al Lenguaje C
86
El printf puede mostrar el contenido de una o más variables y por lo general va acompañada de carteles. En nuestro ejemplo: printf(“La suma es %i”,S); el cartel es “La suma es “ , luego %i que es una máscara de salida y por ultimo S que es la variable. Cada máscara va asociada a una variable, en estos casos %i se asocia a S, esto quiere decir el formato de salida que debe mostrar S debe ser un entero. Otro ejemplo:
imprimir (“El área es ”,A,” y el perímetro es “,Peri); →En estos casos se presentan dos máscaras una asociada a la variable A que es el área y la otra variable Peri que es el perímetro, entonces la codificación será: printf(“El área es %i y el perímetro es %i”,A,Peri); Esto quiere decir que tanto A como Peri son de tipo entero
En la siguiente tabla mostramos las máscaras más comunes: Máscara %i %d %c %s
Imprime Un entero Un entero Un único caracter Una cadena de caracteres Una cadena de caracteres limitada por un número por %(número)s ejemplo: %5s (en estos casos imprimirá los cinco primeros caracteres) %% % Esto es por si queremos imprimir el símbolo de porcentaje Un número con decimales. El tamaño es número1 y la %(número1).(número2)f cantidad de decimales es número2. Por ejemplo: %6.2f (el tamaño del número será 6 y tendrá 2 decimales)
Ejemplo 3: (Ejercicio 4 del capítulo anterior) Se ingresa el radio para mostrar el perímetro de la circunferencia Pseudocódigo
Código #include
87
Martin Goin
definir PI 3.1416
#define PI 3.1416
comienzo()
main()
{
{ float r,P; prinf(“Ingrese el radio: “);
ingresar (r);
scanf(“%f”,&r);
P = 2*PI*r;
P = 2*PI*r;
imprimir (“El perímetro de la
printf(“El perímetro de la circunferencia
circunferencia es “,P);
es %6.2f”,P);
}
}
En este ejemplo se usa una constante PI, es decir que la codificación de definir PI 3.1416 es prácticamente directa #define PI 3.1416 La traducción de la sentencia ingresar es scanf . El mismo tiene asociado dos parámetros: la máscara y la variable de ingreso. Delante de la variable hay un “&” que significa la dirección de la variable donde se va a almacenar el dato. En el ejemplo el radio r es de tipo float (decimal) Nota: Da lo mismo usar la máscara %i o %d
Hasta el momento hemos codificado algoritmos de estructura secuencial, a continuación una tabla como referencia:
Pseudocódigo
Código
Caminando Junto al Lenguaje C
Ejemplo
88
definir
#define
#define G 9.807
comienzo()
main()
main() { sentencias }
ingresar
scanf
scanf(“%d”,&edad);
imprimir
printf
printf(“El promedio es %6.2”,P);
Asignaciones
Se mantienen
S = A * B + C;
Llaves { }
Se mantienen
Atención: Recordar que las variables se declaran en el código siendo invisibles para el pseudocódigo.
Comentarios en la codificación
El lenguaje C, como la mayoría de los otros lenguajes, permite al programador introducir comentarios en el programa fuente, pero que el compilador ignora siempre y cuando estén expresados dentro de los símbolos “/*” en el comienzo y “*/” para el final.
/*
Esto es un comentario que ocupa varias líneas
*/
89
Martin Goin
La misión de estos comentarios es servir de explicación o aclaración sobre cómo está desarrollado el programa, de forma que pueda ser entendido por cualquier otra persona o por el propio programador un tiempo después. Por ejemplo si quisiéramos comentar el ejemplo 3 en la cabecera:
/* Ejemplo 3: Se ingresa el radio para mostrar el perímetro de la circunferencia */
#include #define PI 3.1416 main() { float r,P; prinf(“Ingrese el radio: “); scanf(“%f”,&r); P = 2*PI*r; printf(“El perímetro de la circunferencia es %6.2f”,P); } Nota: El comentario puede ocupar las líneas que sean necesarias siempre y cuando estén encerrados por los símbolos /*…*/
El comentario se puede utilizar en cualquier parte del programa, por ejemplo en el caso del ejemplo anterior podríamos comentar que falta chequear que el radio que ingresa el usuario por teclado no sea ≤ 0 como se ve a continuación:
Caminando Junto al Lenguaje C
90
/* Ejemplo 3: Se ingresa el radio para mostrar el perímetro de la circunferencia */
#include #define PI 3.1416 main() { float r,P; prinf(“Ingrese el radio: “); scanf(“%f”,&r); /* falta validar el ingreso por si se ingresa un valor cero o negative */ P = 2*PI*r; printf(“El perímetro de la circunferencia es %6.2f”,P); } Nota: El comentario es optativo, pero siempre se recomienda usarlo como un simple recordatorio.
Codificación en estructura de control de decisión
En el capítulo de Pseudocódigo aprendimos cómo funciona la estructura de decisión y empezamos viendo la estructura de control de decisión simple. A continuación la traducción en código y un ejemplo en pseudocódigo y código. Pseudocódigo
Código
si (condición)
if (condición)
{
{
91
Martin Goin
sentencias;
sentencias;
}
}
Ejemplo 4: (Ejercicio 5 del capítulo anterior) Mostrar el perímetro de una circunferencia, siempre y cuando el radio que se ingresa sea mayor a cero. Pseudocódigo
Código #include
definir PI 3.1416
#define PI 3.1416
comienzo()
main()
{
{ float r,Peri; printf(“Ingrese el radio: “);
ingresar (r);
scanf(“%f”,&r);
si (r > 0)
if (r > 0)
{
{
Peri = 2*r*PI;
Peri = 2*r*PI;
imprimir (“El perímetro de la
printf(“El perímetro de la
circunferencia es ”,Peri);
circunferencia es %6.2f“,Peri);
} }
Caminando Junto al Lenguaje C
} }
92
Atención: Es importante conservar la indentación también en el código.
El código de la estructura de control de decisión doble lo vemos a continuación en la traducción en código y un ejemplo en pseudocódigo y código. Pseudocódigo
Código
si (condición)
if (condición)
{
{
sentencias;
sentencias;
}
}
sino
else {
{
sentencias;
sentencias;
}
}
Ejemplo 5: (Ejercicio 6 del capítulo anterior) Mostrar el perímetro de una circunferencia, siempre y cuando el radio que se ingresa sea mayor a cero, caso contrario informar con el cartel “Error en el ingreso”. Pseudocódigo
Código #include
definir PI 3.1416
#define PI 3.1416
comienzo()
main()
{
{
93
Martin Goin
float r,Peri; printf(“Ingrese el radio: “); ingresar (r);
scanf(“%f”,&r);
si (r > 0)
if (r > 0)
{
{
Peri = 2*r*PI;
Peri = 2*r*PI;
imprimir (“El perímetro de la
printf(“El perímetro de la
circunferencia es ”,Peri);
circunferencia es %6.2f“,Peri);
}
}
sino
else imprimir (“Error en el ingreso”);
}
printf(“Error en el ingreso”); }
Nota: En estos casos dentro del else no tenemos llaves {} por tratarse de una única sentencia.
Con respecto a los si anidados: Pseudocódigo
Código
si (condición)
if (condición)
si(condición)
if(condición)
{
{
sentencias;
sentencias;
Caminando Junto al Lenguaje C
94
}
}
sino
else si(condición)
if(condición)
{
{
sentencias;
sentencias;
}
}
Ejemplo 6: (Ejercicio 10 del capítulo anterior) Ingresar dos números enteros y mostrar el más grande y en caso de que sean iguales mostrar un cartel “Son iguales”. Pseudocódigo
Código
comienzo()
#include
{
main()
ingresar (A,B);
{
si (A >= B)
int A,B;
si (A == B) imprimir (“Son iguales”); sino
printf(“Ingrese dos números “); scanf(“%i”,&A); scanf(“%i”,&B);
imprimir (“El número
if (A >= B)
”,A,” es el mayor”);
if (A == B)
sino
printf(“Son iguales”); imprimir (“El número ”,B,” es el
else
mayor”);
printf (“El número %i”,A,”
}
es el mayor”); else
95
Martin Goin
printf (“El número %i”,B,” es el mayor”); }
Por su parte la estructura de control múltiple “según” se traduce al código de la siguiente manera: Pseudocódigo
Código
según (variable)
switch (variable)
{
{
caso valor:
case 1:
sentencias;
sentencias;
salir;
break;
.
.
.
.
.
.
defecto:
default:
sentencias;
sentencias;
salir;
break;
}
}
Ejemplo 7: (Ejercicio 13 del capítulo anterior) Ingresar dos números y el operador aritmético (suma “+”, resta “-“, producto “*” o división “/”) para realizar el cálculo y mostrar el resultado.
Caminando Junto al Lenguaje C
96
Pseudocódigo
Código
comienzo()
#include
{
main()
ingresar (A,B);
{
ingresar (operador);
int A,B;
según (operador)
float R;
{
char op;
caso “+”:
printf(“Ingrese dos números “);
R = A + B;
scanf(“%i”,&A);
salir;
scanf(“%i”,&B);
caso “-”:
printf(“Ingrese la operacion “);
R = A - B;
scanf(“%c”,&op);
salir;
switch (variable)
caso “*”:
{
R = A * B;
case “+”:
salir;
R = A + B;
caso “/”:
break;
R = A / B;
case “-”:
salir;
R = A - B;
defecto:
break;
R = 0;
case “*”:
salir;
R = A * B;
}
break;
97
Martin Goin
imprimir (“El resultado es “, R);
case “/”:
}
R = A / B; break; default R = 0; break; } printf(“El resultado es %6.2f“,R); }
Nota: En este ejemplo no se contempla la posibilidad de dividir por cero. Una propuesta sería informar tal situación y no cometer el error de calcularlo.
Codificación en estructura de control de repetición
En el caso de la sentencia “para” la traducción a la codificación es “for”: para (valor inicial; condición;
for ((valor inicial; condición;
incremento/decremento)
incremento/decremento)
{
{
sentencias;
sentencias;
}
}
Ejemplo 8: Hallar el promedio de altura de los alumnos de una comisión sabiendo que son 30. Pseudocódigo
Código
Caminando Junto al Lenguaje C
98
comienzo()
#include
{
main()
S = 0;
{
para (i=0; i0) return('+'); else
Caminando Junto al Lenguaje C
168
return('-'); } int main() { int a,b; printf("\n Ingrese los dos números: "); scanf("%d %d", &a, &b); printf("\n La diferencia entre %i y %i es %c", a, b, resta(a,b)); return 0; } Nota: Además se puede observar que en el retorno de la función resta existen tres return, pero solo uno de estos es el que debe funcionar (depende de la respuesta del if)
Atención: Las funciones no devuelven arreglos, solo datos de tipo escalar, es decir punteros, numéricos (float e int) y caracteres (char). Si quisiéramos retornar un arreglo entonces tendríamos que utilizar procedimientos.
Variables Globales y Locales
Variables Globales: Estas se crean durante toda la ejecución del programa, y son globales, ya que pueden ser llamadas, leídas, modificadas, etc; desde cualquier función incluso del mismo main. Las variables se definen antes del main().
Variables Locales: Estas, pueden ser utilizadas únicamente en la función que hayan sido declaradas.
169
Martin Goin
A continuación mostraremos un ejemplo que utilice variables globales y locales.
Ejemplo 5: Se genera un vector de 100 números aleatorios (del 1 al 10), luego el usurario elige una cantidad menos o igual a 100 para hallar su promedio. Para el promedio se debe utilizar una función. #include #define N 100 int c; →Esta es la variable Global (se puede utilizar tanto en el main como dentro de las funciones)
float promedio(int v[]) { int i,s=0; →s es una variable Local por estar definida dentro de la función for (i=0;i