OS2TE_LINEX.02 8/5/08 13:59 Página 36 2 C uando ponemos en marcha una lavadora, grabamos nuestro espacio favorito de televisión o planificamos nuestros trabajos escolares del fin de semana, estamos programando. Por tanto, programar es una labor cotidiana que nos ayuda a resolver muchas tareas, organizándolas de acuerdo con un plan inicial o programa. La programación también supone un ejercicio mental muy didáctico: como si de una partida de ajedrez se tratara, tendremos que ir resolviendo cada problema que se nos plantee de la forma más efectiva posible. En esta unidad nos introduciremos en el mundo de la programación mediante ordenadores, que han multiplicado las posibilidades de esa disciplina, e iremos descubriendo, poco a poco, cómo la máquina es capaz de hacer lo que nosotros le ordenamos. Lenguajes de programación OS2TE_LINEX.02 8/5/08 13:59 Página 37 1 Lenguajes de programación La mayor parte de las veces en que nos encontramos frente a un ordenador es este quien nos guía, indicándonos las posibilidades que tenemos y marcándonos claramente los límites de nuestra interacción con él. Esto se debe a que, por lo general, utilizamos los ordenadores como operadores, es decir, trabajamos con programas desarrollados para un fin específico. Ejemplos de este tipo son los procesadores de texto, que sirven para elaborar documentos, o los videojuegos, que únicamente nos dan algunas opciones a las que accedemos mediante determinadas teclas y periféricos. Los lenguajes de programación traducen nuestras órdenes en un código de ceros y unos, inteligible por la máquina. Sin embargo, hay otra forma de manejar el ordenador en la que es el usuario el que toma el mando de la situación, indicándole a la máquina qué es lo que tiene que hacer en cada momento y también cómo debe responder ante determinados estímulos procedentes del exterior. Estos usuarios reciben el nombre de programadores y pueden elegir entre un nutrido grupo de lenguajes de programación para comunicarse con el microprocesador, que es el verdadero cerebro de todas las operaciones que se realizan dentro del ordenador. Los programadores actuales suelen intercalar varios lenguajes en sus aplicaciones, dependiendo, fundamentalmente, de las necesidades de rapidez de respuesta o de la especialización de cada lenguaje para una determinada función. Para ellos, es posible realizar todo esto de forma sencilla, utilizando un entorno de desarrollo de programación, conocido como IDE1, que incluye todas las herramientas necesarias para poner a punto sus programas. Te interesa saber Mediante complicados algoritmos mnemotécnicos, distintos para cada familia de chips, el lenguaje ensamblador es el que más rápidamente hace funcionar el microprocesador: se utiliza, por ello, en aplicaciones donde el tiempo de ejecución es crítico, como, por ejemplo, en los simuladores en tiempo real. 1 IDE: acrónimo de Integrated Development Environment (Entorno de Desarrollo Integrado). Lenguajes de programación Los lenguajes de programación son, en definitiva, meros traductores de códigos humanos a códigos de la máquina. El nivel de un determinado lenguaje se define según la proximidad entre ambos códigos: los de alto nivel son los más sofisticados y cercanos a los códigos humanos (por ejemplo, Basic, Pascal, C++, Logo, etc.), mientras que los de bajo nivel son los más cercanos al galimatías numérico que suponen los ceros y unos con los que se entienden entre sí los circuitos electrónicos del ordenador. Entre estos últimos destaca el lenguaje ensamblador. Atendiendo al criterio anterior, existen también lenguajes de nivel medio, como C, que, sin lugar a dudas, ha sido el más utilizado por los programadores avanzados en la última década. Sin ir más lejos, la mayor parte del código que constituye el sistema operativo Linux está desarrollada en C. 37 OS2TE_LINEX.02 8/5/08 13:59 Página 38 2 Logo Te interesa saber Las órdenes o instrucciones en los lenguajes de programación se ejecutan directamente cuando se dispone de un intérprete de comandos. Sin embargo, cuando hay que compilarlas, es necesario seguir un proceso más complicado, dificultad que se ve compensada por una considerable reducción del tamaño del código de programa generado y una mayor autonomía de ejecución, es decir, ocupa menos recursos de memoria y puede funcionar en más ordenadores. Para que te familiarices con los lenguajes de programación, vamos a practicar con uno muy sencillo, denominado Logo. De entre las muchas versiones existentes de este lenguaje de programación, vamos a trabajar con un interprete de comandos desarrollado en Java, que permite ejecutarlo en cualquier sistema y equipo. Este programa se denomina XLogo (http://xlogo.tuxfamily.org/) y tiene la ventaja añadida de acogerse a una licencia GPL, esto es, funciona como software libre y se adapta perfectamente a nuestra distribución GNU/Linex. Cuando entramos en XLogo, se nos presenta como un entorno de programación integrado, con una entrada de comandos que permite ordenar a una pequeña tortuga para que se mueva a nuestro antojo por la ventana gráfica central. Será en esta ventana donde veremos que la tortuga sigue nuestras instrucciones al pie de la letra. Ventana inicial de XLogo. 2.1. Ejecución del programa Hay dos formas de trabajar con XLogo. La primera precisa de conexión a Internet. Consiste en utilizar el enlace Ejecución en línea de XLogo, haciendo uso de la siguiente dirección: UNIDAD 2 http://xlogo.tuxfamily.org/common/webstart/xlogo.jnlp 38 Importante Para poder ejecutar cualquier aplicación escrita en Java, es preciso tener instalada y funcionando en el ordenador la aplicación Java Runtime Environment (JRE), que puede descargarse libremente en la siguiente dirección web: http://java.sun.com/javase/ downloads/index.jsp La segunda consiste en descargarnos un archivo ejecutable del programa, en la siguiente dirección: http://xlogo.tuxfamily.org/common/xlogo-new.jar Cada vez que iniciemos la aplicación, deberemos arrancar este programa pulsando sobre el icono correspondiente. Una vez abierto el programa, vamos a ejecutar nuestra primera orden Logo. Para ello, escribimos la instrucción BORRAPANTALLA en la línea de entrada superior Comando y pulsamos la tecla Intro. Cuando el comando está correctamente escrito, el color de las letras cambia a verde y, una vez ejecutado, aparece en la ventana inferior, denominada Ventanilla de información (Histórico de comandos en algunos manuales), que también sirve para informarnos de los errores que se detecten. OS2TE_LINEX.02 8/5/08 13:59 Página 39 2.2. Interfaz de usuario Se llama interfaz de un programa a los recursos que este utiliza para comunicarse con el operador y hacerle su uso más «amable». Hasta hace unos años, los entornos de programación eran muy poco amistosos y todo consistía en introducir ordenes en un terminal. Actualmente, esto ha cambiado mucho y XLogo es un buen ejemplo de ello, pues ofrece una serie de opciones y de herramientas que hacen más agradable la tarea de programar. Básicamente, podemos definir los siguientes espacios: 쮿 Línea de entrada de comandos. Desde aquí introduciremos ordenes puntuales que queremos que la tortuga cumpla rápidamente. También se pueden introducir varias instrucciones LOGO al mismo tiempo. 쮿 Ventana gráfica. Se encarga de mostrarnos los resultados gráficos de nuestros programas. Tiene la ventaja de poder exportar en diversos formatos los resultados y dibujos que genera. Te interesa saber El intérprete XLogo no distingue entre mayúsculas y minúsculas en los comandos introducidos; no obstante, aquí adoptaremos el criterio de poner dichos comandos siempre en mayúsculas para diferenciarlos de los argumentos del programa. El sistema operativo, sin embargo, sí es muy estricto en esto y no es lo mismo almacenar un fichero con el nombre programa.lgo que con el nombre PROGRAMA.LGO. 쮿 Editor de procedimientos. Permite escribir y almacenar procedimientos que posteriormente podemos utilizar en distintos programas. Más adelante profundizaremos sobre este importante aspecto de la programación. 쮿 Ventanilla de información. La ventana inferior muestra los comandos utilizados, así como la información generada por su ejecución. Línea de entrada de comandos Ventana gráfica Editor de procedimientos El interfaz dispone también de las entradas típicas de menú: Archivo, Edición, Herramientas y Ayuda, que permiten, entre otras cosas, configurar la apariencia de nuestro interprete XLogo o la velocidad con que se mueve la tortuga, ver la lista de instrumentos musicales que podemos simular con la orden PONINSTRUMENTO número, etcétera. A la derecha de la ventana gráfica se encuentra una barra de herramientas vertical con las funciones Zoom (Acercar y Alejar), Copiar, Cortar, Pegar y Comando de inicio. Actividades Busca información sobre el lenguaje JAVA e indica qué tipo de programación utiliza, para qué se usa principalmente, cuáles son sus principales características y bajo qué licencia se divulga. 1 Lenguajes de programación Ventanilla de información 39 OS2TE_LINEX.02 Te 8/5/08 13:59 Página 40 interesa saber El lenguaje de programación Logo es un dialecto de LISP, un lenguaje orientado a desarrollar programas de inteligencia artificial, y tiene sus raíces en la teoría educativa constructivista. Está pensado para comenzar a utilizarlo de modo casi inmediato, aunque también permite desarrollar programas complejos. 2.3. Nuestro primer programa en Logo Vamos a empezar a mover la tortuga escribiendo lo siguiente en la línea de entrada de comandos: AVANZA 100 GIRADERECHA 90 AVANZA 30 GIRAIZQUIERDA 90 AVANZA 30 ROTULA [La tortuga se mueve] Tienes que pulsar siempre la tecla Intro después de una instrucción o conjunto de ellas, a fin de que el intérprete entienda que debe ejecutarla. Una vez hecho esto, en la ventana gráfica de XLogo ocurre lo siguiente: El conjunto de comandos anteriores (AVANZA, GIRADERECHA, GIRAIZQUIERDA y ROTULA), con sus argumentos (100, 90, 30, 90, 30 y La tortuga se mueve), constituye un programa que, al ejecutarse, da como respuesta la salida gráfica que hemos visto. Concretamente, hemos hecho que la tortuga avance una serie de píxeles en cada ocasión y gire en ambos sentidos 90º. Por último, hemos insertado un texto. Una regla fundamental del programador es que, al igual que ocurre en el lenguaje escrito, en el de programación hay que respetar escrupulosamente las normas sintácticas (espacios, comillas, corchetes…). Si no lo hacemos así, en el mejor de los casos se nos parará la ejecución del programa con un mensaje de error. Actividades 2 Siguiendo con el ejemplo anterior, explica qué ocurre cuando ejecutas las siguientes instrucciones: UNIDAD 2 GIRADERECHA 30 AVANZA 100 GIRADERECHA 120 AVANZA 100 CENTRO 40 Nota: para ver con más claridad la figura, utiliza al final de la secuencia la orden OCULTATORTUGA. 3 Busca en Internet quiénes fueron los autores iniciales de Logo, en qué se basaron y cuáles eran sus objetivos. OS2TE_LINEX.02 8/5/08 13:59 Página 41 2.4. Comandos o primitivas Una de las características principales del lenguaje XLogo es que sus instrucciones son muy cercanas al lenguaje hablado, lo que simplifica bastante el abstracto ejercicio de programar. Conforme nos habituemos a escribir las distintas órdenes, podremos ir haciendo uso de otra de las ventajas que nos permiten todos los intérpretes XLogo: la introducción de órdenes en su forma nemotécnica abreviada, que nos evita teclear gran parte del código. Orden Forma abreviada Significado AVANZA n AV n Avanza n pasos RETROCEDE n RE n Retrocede n pasos GIRADERECHA n GD n Gira a la derecha n grados GIRAIZQUIERDA n GI n Gira a la izquierda n grados ROTULA [texto] Escribe texto en BXLogo CENTRO Lleva la tortuga a casa PONCOLORLAPIZ n PONCL n Selecciona el color del lápiz BORRAPANTALLA BP Borra la pantalla SUBELAPIZ SL No pinta al desplazarse BAJALAPIZ BL Pinta al desplazarse PONXY x y Coloca la tortuga en las coordenadas (x, y) Algunos comandos internos de Logo, también llamados primitivas, pueden precisar una información adicional para ejecutarse correctamente. Por ejemplo, cuando le decimos a la tortuga que avance, deberemos indicar cuánto debe avanzar. Esta información complementaria en forma de parámetros se llaman argumentos, y pueden ser de tres tipos: 쮿 Números, por ejemplo AV 50. 쮿 Palabras, por ejemplo, ESCRIBE “Hola 쮿 Listas. Se definen encerrándolas entre corchetes; por ejemplo, la orden INVIERTE [1 2 3] devolvería [3 2 1]. Te interesa saber Los lenguajes y sistemas operativos ofrecen la posibilidad de cambiar el nombre de los comandos o funciones que utilizamos para adaptarlos a nuestra lengua y por comodidad a la hora de trabajar con ellos. Por ejemplo, en LinEx, elcomando ALIAS permite poner un «mote» a una orden. 4 Haz un sencillo programa que permita obtener un resultado similar al de la figura del margen. En el menú, selecciona Herramientas 씰 Preferencias para elegir la tortuga y el fondo. Ayuda: el comando RETROCEDE hace que la tortuga avance en sentido contrario a su orientación. 5 Investiga sobre las siguientes primitivas e indica el tipo de argumento: CUADRICULA n n, PONFORMA n, PONCOLORPAPEL [r v a], EJES n, ULTIMO “Logo. 6 Abre un terminal LinEx y renombra el comando «ls» con la palabra «muestra». Si no conoces la sintaxis del comando ALIAS pide ayuda al sistema operativo con la orden «man alias». Lenguajes de programación Actividades 41 OS2TE_LINEX.02 8/5/08 13:59 Página 42 2.5. Bucles Código de colores El color en XLogo viene especificado por una lista de tres números, [r v a], comprendidos entre 0 y 255. El número r es el componente rojo, v el verde y a el azul (en inglés hablaríamos de [r g b], esto es, red, green y blue). XLogo tiene 17 colores predefinidos, a los que se puede hacer referencia mediante un número, una lista [r v a] o una primitiva. Las primitivas correspondientes de los nueve primeros son: Frecuentemente es necesario repetir varias veces una instrucción; en otros casos, deseamos que la instrucción se repita mientras se cumple cierta condición. Para ello utilizamos los bucles, recursos que potencian enormemente el desarrollo de los programas y constituyen una parte fundamental de los mismos. Veremos, en primer lugar, cómo se elabora un bucle utilizando la instrucción REPITE. Vamos a resolver de dos formas distintas el mismo problema: dibujar un cuadrado rojo de 100 unidades de lado. Utilizando las formas abreviadas de órdenes que se muestran en la tabla de la página anterior, introduciremos la siguiente secuencia en la línea de entrada de comandos para dibujar el cuadrado: PONCL 1 AV 100 GD 90 AV 100 GD 90 AV 100 GD 90 AV 100 GD 90 N.º Primitiva [r v a] Color 0 Negro [0 0 0] 쮿 1 Rojo [255 0 0] 쮿 2 Verde [0 255 0] 쮿 3 Amarillo [2552550] 쮿 Orden Significado 4 Azul [0 0 255] 쮿 REPITE n [instrucción] Repite n veces las instrucciones escritas entre [ ] 5 Magenta [2550255] 쮿 6 Cian [0255255] 쮿 7 Blanco [255 255 255] 쮿 8 Gris [128 128 128] 쮿 Como se ve, hemos repetido varias veces la misma secuencia de instrucciones. Pues bien, hay una orden que nos ahorrará trabajo realizando un bucle, es decir, repitiendo un conjunto de órdenes las veces que le indiquemos: Conforme vayamos avanzando en programación, nos daremos cuenta de la importancia de poder realizar «de un plumazo» toda una serie de órdenes repetidas. Veamos como, utilizando la orden REPITE, se simplifica mucho la secuencia de comandos necesaria para dibujar el cuadrado del ejemplo anterior: PONCL 1 REPITE 4 [AV 100 GD 90] Siempre que la tortuga salga del mismo sitio, la salida gráfica será exactamente igual que la anterior. Para ello, solo tienes que utilizar el comando CENTRO al principio del programa. UNIDAD 2 Actividades 42 7 Haciendo uso de dos bucles, realiza un programa que dé una salida gráfica similar a la de la figura. En la siguiente figura se muestran ambos cuadrados colocando su inicio en distintas posiciones del terminal gráfico, que podemos considerar un sistema de coordenadas cuyo origen (0, 0) se encuentra en el centro de la ventana gráfica de XLogo. Mediante la orden PONXY x y, o de forma independiente, PONX x y PONY y, se puede definir la ubicación inicial de la tortuga. En este caso, un cuadrado empieza en el punto (100, 100), y el otro, en el punto (100, 100). En la ventana superior vemos el resultado; en la inferior, el código introducido. OS2TE_LINEX.02 8/5/08 13:59 Página 43 XLogo dispone de otras primitivas que permiten la construcción de bucles, además de la ya vista REPITE. Por ejemplo, REPITEPARA y MIENTRAS permiten realizar evoluciones cíclicas (dar un número determinado de vueltas) dentro del programa. Al utilizar la orden REPITE se define automáticamente una variable interna llamada «cuentarepite», que determina el número de la iteración en curso. Por ejemplo, la orden Variables Como veremos más adelante, las variables son textos o números que pueden tomar distintos valores. REPITE 5 [ESCRIBE cuentarepite] mostrará en la ventanilla de información lo siguiente: La primitiva REPITEPARA consiste en asignar a una variable valores consecutivos entre dos números dados, con un incremento determinado. Así, la instrucción REPITEPARA [x 1 10 2] [ES :x ES :x*:x] daría como salida una lista con los números impares contenidos entre 1 y 10, y sus cuadrados. Te Por último, otra potente forma de diseñar un bucle es mediante la instrucción MIENTRAS, que permite repetir cíclicamente un bucle mientras no se cumpla una condición prefijada. En otros lenguajes de programación, la función de la primitiva REPITEPARA se lleva a cabo mediante los bucles for…next. Orden Estructura Significado REPITEPARA REPITEPARA [datos] [lista de instrucciones] Repite la lista de instrucciones entre dos valores especificados y con un salto definido. MIENTRAS MIENTRAS [lista a evaluar] [órdenes] «lista a evaluar» contiene un conjunto de instrucciones que se evalúan como ciertas o falsas; «órdenes» es una lista de los comandos que van a ser ejecutados mientras la respuesta sea cierto. interesa saber Por otra parte, la instrucción condicional MIENTRAS es muy parecida a los comandos condicionales if…then que estudiaremos más adelante. Un bucle que se llama a sí mismo se dice que es recursivo. Esta técnica, muy utilizada en programación, da lugar a los llamados algoritmos recursivos, muy utilizados en las técnicas matemáticas de desarrollo fractal, también usados en la programación de videojuegos. Imagen de un fractal. La naturaleza ofrece muchos ejemplos de recursividad. La concha de un caracol, la hoja de un helecho o un copo de nieve son ejemplos de desarrollos recursivos. Lenguajes de programación Bucles y recursividad 43 OS2TE_LINEX.02 8/5/08 13:59 Página 44 2.6. Procedimientos Otro de los grandes recursos que tiene el lenguaje de programación XLogo es la posibilidad de crear procedimientos: conjunto de órdenes, con una estructura definida, que hace siempre la misma tarea. Los programas que vamos a desarrollar también tendrán esta estructura. Su forma general es: para nombre del procedimiento :variable 1 :variable 2… … Secuencia de órdenes … fin El editor de procedimientos Para definir un procedimiento utilizaremos principalmente este editor, al que podemos acceder de varias formas, aunque la más directa es hacer clic sobre el botón EDITAR de nuestro interfaz, cuya ventana principal aparece a la izquierda. Los botones más importantes del editor son: Guarda en memoria los cambios hechos en el editor y cierra la ventana. Cierra la ventana del editor sin guardar los últimos cambios. En el ejemplo de la ilustración, hemos creado el siguiente procedimiento, al que hemos llamado «cuadrado»: para cuadrado repite 4 [av 50 gd 90] fin Editor de procedimientos. Si hemos creado correctamente nuestro procedimiento, cuando pulsemos sobre el pingüino aparecerá lo siguiente en la ventanilla de información (en nuestro ejemplo, aparecerá el nombre «cuadrado»): Acabas de definir nombre del procedimiento. UNIDAD 2 Una norma básica en programación es poner nombres a los procedimientos que recuerden el cometido que tienen. La definición de procedimientos equivale a incluir una nueva orden en nuestro lenguaje de programación. Siempre que ejecutemos ese procedimiento, el ordenador responderá de forma similar. 44 Importante Cada vez que carguemos un fichero de procedimientos, es necesario pulsar sobre el pingüino para que queden definidos. Los procedimientos se pueden ejecutar cuantas veces queramos, siempre que no cerremos la aplicación. Si son cortos, no resulta problemático perderlos al cerrar el programa; sin embargo, en la mayoría de las ocasiones los procedimientos son largos y complejos, por lo que repetirlos puede ser una labor tediosa. Para evitarlo, se debe guardar todo el contenido del editor de procedimientos mediante las opciones Guardar o Guardar como del menú principal de la aplicación. Todos los archivos guardados tendrán la extensión .lgo y se pueden abrir y modificar con el editor de procedimientos o con cualquier editor de textos. OS2TE_LINEX.02 8/5/08 13:59 Página 45 Ejemplo 1 Las tildes en programación Realiza un procedimiento, denominado «hexagono», que pinte un polígono regular de 6 lados de 100 unidades cada uno. Por lo general, en programación no se ponen tildes en los comandos, fundamentalmente a fin de guardar la compatibilidad con la mayoría de los intérpretes o compiladores, que están basados en el idioma inglés. La única dificultad estriba en determinar el ángulo que debe girar la tortuga al finalizar el trazo de cada lado. Si dos lados consecutivos del hexágono forman un ángulo de 120°, la tortuga deberá girar 180° 120° 60°. Así pues, el procedimiento será: para hexagono repite 6 [av 100 gd 60] fin Con XLogo podemos hacer melodías con muchos instrumentos distintos. Vamos a crear un procedimiento para poner algo de música en nuestra clase utilizando las siguientes primitivas: Orden Significado SEC [lista de notas] Introduce en memoria la melodía. BOS Borra una secuencia de la memoria. PONINSTRUMENTO número Elige un instrumento de la lista. TOCAMUSICA Reproduce la secuencia musical. A continuación introduzcamos con el editor el siguiente procedimiento: para musica :instrumento SEC [do re mi fa sol la si : do] PONINSTRUMENTO :instrumento TOCAMUSICA BOS fin musica número Prueba el procedimiento poniendo distintos números. No olvides encender los altavoces. Actividades 8 Realiza un procedimiento para crear una cenefa similar a la de la figura del margen, que recorra horizontalmente la ventana gráfica. 9 Busca las notas de una canción sencilla y transcríbela como secuencia para que suene con el interprete XLogo. Lenguajes de programación El símbolo : de la secuencia sube las notas siguientes una octava. Ya solo nos queda introducir en el editor de comandos la orden: 45 OS2TE_LINEX.02 8/5/08 13:59 Página 46 2.7. Variables Los procedimientos que hemos visto hasta ahora presentan un inconveniente: solo manejan parámetros fijos. Para superar esta limitación, hay que recurrir a las variables. Las variables aumentan las posibilidades de los programas, pues permiten introducir distintos valores y obtener, así, diferentes resultados. En la tabla siguiente se muestran las órdenes utilizadas más frecuentemente a la hora de trabajar con variables: Orden Significado ES [texto] Imprime en el terminal el texto que se encuentra entre corchetes HAZ “nombre Crea la variable nombre LEELISTA [Titulo] “nombre Solicita una entrada por teclado que almacena en la variable nombre AZAR n Genera un número aleatorio entero de orden n 1 Una variable es un dato (numérico o alfanumérico) asociado a un nombre que el ordenador almacena y que, como su denominación indica, puede variar. Es posible definir una variable de distintas formas, pero la más sencilla es utilizar el comando HAZ con la siguiente sintaxis, según se trate de números o de texto (variable numérica o alfanumérica): HAZ “x 5 HAZ “texto “yo\ soy\ el\ valor\ de\ la\ variable\ texto Te interesa saber Para introducir un salto de línea, es preciso utilizar la secuencia especial \n. Para no confundir al intérprete Logo, hay que poner una barra invertida (\) delante de cada espacio. Fíjate en la utilización correcta de las comillas. Para comprobar que la asignación ha sido correcta, emplea la orden ES en el terminal (los dos puntos indican que se trata de una variable): ES :x 5 ES :texto yo soy el valor de la variable texto También puede ser el programa el que en un momento determinado te pida que introduzcas el valor de una variable, como veremos a continuación. Ejemplo 2 Realiza un procedimiento para calcular automáticamente el índice de masa corporal de una persona. UNIDAD 2 El parámetro mencionado permite determinar si nuestro peso es o no el adecuado. Equivale a la relación inversa entre la masa (en kg) y el cuadrado de la altura de un individuo (en m), luego el procedimiento será: 46 para imc LEELISTA [¿Cuánto pesas (kg)?] “masa LEELISTA [¿Cuánto mides (m)?] “altura ES [Tu índice de masa corporal es: ] ES :masa/(:altura*:altura) fin Los valores de masa y de altura se almacenan para utilizarlos posteriormente, lo que permite utilizar el programa con cualquier persona. OS2TE_LINEX.02 8/5/08 13:59 Página 47 Otra forma de definir variables es asignándoselas directamente a un procedimiento. Utiliza el editor de procedimientos y abre el fichero cuadrado.lgo guardado anteriormente para definir las variables color y lado en el procedimiento cuadrado, tal como se observa a continuación: para cuadrado :color :lado PONCL :color REPITE 4 [AV :lado GD 90] fin Una vez creado el procedimiento, no olvides pulsar sobre el pingüino para definirlo. A continuación, guárdalo mediante la opción Guardar del menú principal. Ya podemos ejecutar el procedimiento, pero ahora no basta con escribir cuadrado en la línea de comandos, pues el programa está esperando más datos; si no se los proporcionamos, nos dará un informe de error. Asignación de dos variables, color y lado, en el procedimiento «cuadrado». Supongamos que queremos un cuadrado de color amarillo y con 200 unidades de lado. Entonces deberemos escribir lo siguiente en la línea de comandos: cuadrado 3 200 Cuando el programa llama al procedimiento, le pasa el valor de las dos variables en el mismo orden en que las has definido, con lo que el resultado gráfico será el siguiente: Actividades 10 Si ejecutas muchas veces el procedimiento observarás que, en ocasiones, no se ve nada en la pantalla. Deduce por qué ocurre esto y corrígelo. Un comando curioso es AZAR. Si lo quisieras utilizar para definir, por ejemplo, la variable color, deberías poner como argumento el número máximo más uno de entre los que se pueden elegir (en este caso 17 1) y el cuadrado saldría de un color determinado al azar. Prueba a teclear varias veces la siguiente línea de comandos: cuadrado AZAR 18 200 11 Haz un procedimiento o programa que pinte diez segmentos contiguos, cada uno con una dirección al azar, con un tamaño mínimo de 20 unidades y máximo de 100 unidades, y de un color que habrá de determinarse cuando se ejecute. Lenguajes de programación cuadrado AZAR 18 200 47 OS2TE_LINEX.02 8/5/08 13:59 Página 48 2.8. Organización del trabajo al programar Te interesa saber Los bugs son errores de programación no detectados en las primeras fases de desarrollo de una aplicación, denominadas alfa y beta, y generalmente obligan al equipo de programación a fabricar «parches» que los subsanen. Hay algunas normas que un programador debe respetar para realizar eficazmente sus aplicaciones y, sin lugar a dudas, la primera de todas es tener claro lo que se quiere hacer. Es importante dedicar todo el tiempo que resulte necesario a diseñar las líneas generales y algoritmos principales de la aplicación. Una vez definido el objetivo, conviene desarrollar la solución de forma gráfica, ayudándonos de un diagrama de flujo, para posteriormente pasar a la acción escribiendo el código. La experiencia dicta que, por exhaustivos que sean los análisis previos, casi nunca se puede evitar cometer errores, lo que obliga a recurrir continuamente al método de ensayo y error, depurando al máximo los programas hasta conseguir que funcionen. A continuación, estudiaremos un ejemplo de planteamiento y resolución de un problema real con Logo. Construcción de una espiral cuadrada Vamos a diseñar un programa que dibuje una espiral cuadrada en la ventana gráfica. Para ello, hay que aplicar lo aprendido hasta ahora. Ha llegado el momento de conjugar los comandos, instrucciones o primitivas que conocemos de este nuevo lenguaje con el fin de expresar una idea y plasmarla en un código que el ordenador pueda entender y ejecutar. Además, será necesario introducir la instrucción condicional SI, que se describe a continuación: Orden Significado SI condición [orden] Si se cumple la condición, el programa ejecuta la orden indicada entre corchetes; de lo contrario, continúa. Las condiciones constan de un operador (igual que, mayor que, menor que, etc.) y de un valor de referencia. Abordaremos el problema desarrollando todas las partes del trabajo: 1. Análisis del problema. Una espiral cuadrada no es más que un UNIDAD 2 cuadrado, el tamaño de cuyo lado va creciendo progresivamente. Vamos a introducir dos variables en la llamada al procedimiento: la longitud inicial del lado (:lado) y la longitud máxima que queramos que tenga este (:l_maximo). Resulta evidente que habrá que utilizar un bucle para trazar los lados. 48 OS2TE_LINEX.02 8/5/08 13:59 Página 49 2. Diagramas de flujo. El trabajo con lápiz y papel es fundamental en programación, pues ayuda a plasmar mejor las ideas y sirve de referencia a lo largo de toda la ejecución. En paralelo al análisis del problema, es conveniente desarrollar gráficamente las distintas partes de que consta, lo cual debe hacerse de forma organizada y siguiendo el mismo flujo, o camino, por el que discurrirá cuando esté en marcha. Existen marcos estipulados para cada operación que simplifican el entendimiento y corrección del programa. 3. Código. El procedimiento que hay que realizar debe dar vueltas sobre sí mismo; para ello, es preciso hacer que, una vez ejecutado, se llame a sí mismo. Es ahora cuando toca utilizar la técnica de recursividad comentada anteriormente, para que el proceso se repita hasta que se cumpla la condición de que el lado, que se incrementará en dos unidades cada vez, sea mayor que el determinado por la variable :l_maximo. Cuando esto ocurra, se ejecutará la orden ALTO y finalizará el procedimiento. El algoritmo queda como sigue: inicio lado inicial y máximo lado máximo SÍ stop NO dibujar lado incrementar lado Diagrama de flujo para la construcción de una espiral. para espiral :lado :l_maximo SI :lado :l_maximo [ALTO] AV :lado GD 90 espiral :lado2 :l_maximo fin 4. Resultados y depuración. En ocasiones, el resultado no se corresponde exactamente con lo que habíamos imaginado, o bien se nos ocurren ideas más acertadas durante el proceso, lo cual obliga a realizar las modificaciones oportunas hasta conseguir aproximarse lo máximo posible a lo que realmente se desea realizar. En el ejemplo que hemos desarrollado, el resultado es el que muestra la figura: Un algoritmo es un conjunto finito de instrucciones o pasos que sirven para ejecutar una tarea o resolver un problema. El nombre se debe al matemático Al-Khwarizmi, que estudió y trabajó en Bagdad en la primera mitad del siglo IX y que, para muchos, fue el más grande de los matemáticos de su época. De hecho, es considerado el padre del álgebra y el creador de nuestro sistema de numeración. Lenguajes de programación Los algoritmos 49 OS2TE_LINEX.02 8/5/08 13:59 Página 50 3 Programando en C Te interesa saber El lenguaje C fue inventado por Dennis Ritchie en colaboración con Ken Thompson en 1972, cuando estaba diseñando el sistema operativo UNIX. A partir de este lenguaje surgieron numerosas variantes, por lo que se hizo necesario definir un C estándar, conocido hoy como ANSI C. Para crear programas en C son necesarias una serie de herramientas, entre las que cabe mencionar un editor de textos y, sobre todo, un compilador, esto es, el traductor del lenguaje C al lenguaje que entiende la máquina; en este caso, se trata del programa GCC, con el que obtenemos un archivo ejecutable a partir de nuestro archivo fuente escrito en lenguaje C. Estas y otras herramientas se integran en un entorno de desarrollo denominado Anjuta IDE, que utilizaremos para programar en C bajo LinEx de una forma más rápida y efectiva. 3.1. Nuestro primer programa en C Abre Anjuta IDE desde el menú Programación y sigue los pasos del Asistente para aplicaciones para la creación de un proyecto nuevo de tipo Genérico/proyecto para consola. Nombra el proyecto como ejemplo1 en lenguaje C y objetivo ejecutable. Sigue los pasos siguientes desmarcando las opciones adicionales para crear el proyecto más simple posible. Al finalizar el asistente se generan automáticamente todos los archivos necesarios para el proyecto, incluyendo un código de ejemplo. Exploraremos mediante el panel derecho Proyecto la estructura de carpetas hasta llegar a la carpeta src (archivos fuentes) donde localizaremos el archivo main.c (archivo fuente principal). Haciendo clic sobre el mismo, se abre en el editor de la derecha, donde procedemos a modificar el mensaje entrecomillado «Hello World» por otro como «Mi primer programa en C.» que nos ayude en las pruebas. UNIDAD 2 GCC es un conjunto de compiladores desarrollados por el proyecto GNU. 50 Anjuta IDE es un entorno de programación en varios lenguajes que hace uso de las herramientas GCC. El proceso a seguir con las herramientas consiste en guardar el archivo modificado (Archivo 씰 Guardar), compilar el archivo fuente (Construir 씰 Compilar, o tecla F9) generando un ejecutable (Construir 씰 Construir, o tecla F11) y, finalmente, ejecutar dicho archivo (Construir 씰 Ejecutar, o tecla F3). Al ejecutar se abre una nueva ventana de terminal con el resultado de la ejecución, en este caso la visualización del mensaje deseado por pantalla (entre líneas discontinuas). La ventana se cerrará al pulsar una tecla. Entorno de programación. Ventana de terminal. OS2TE_LINEX.02 8/5/08 13:59 Página 51 Análisis de nuestro primer programa en C Los programas en C están compuestos de unidades de programa denominadas funciones, que son los módulos básicos del programa. En nuestro ejemplo, el programa está compuesto por una sola función llamada main. Todos los programas de lenguaje C deben tener una función main, pues es la primera que se ejecuta cuando se hace funcionar el programa. Los paréntesis que siguen a main la identifican como nombre de función. Te interesa saber La diferencia entre una definición y el uso o llamada de función en C puede verse claramente en el siguiente ejemplo equivalente al anterior: void imprime (void) Un método de comunicación de datos entre funciones consiste en el uso de argumentos. Estos son los datos que se pasan a las funciones y se encierran entre paréntesis; en el programa que acabamos de diseñar, main es una función sin argumentos, lo que se indica mediante ( ). La línea printf (“Mi primer programa en C.”); realiza una llamada a una función denominada printf con el argumento «Mi primer programa en C.»; printf ejecuta una escritura en la salida estándar (normalmente, dicha salida es el monitor) de una cadena o secuencia de caracteres entrecomillados. { printf (“Mi primer programa en C con funciones.”); return; } int main( ) { imprime( ); return(0); } Una cadena es una secuencia de caracteres y va entre comillas. Cada instrucción en C termina con un punto y coma. La línea de main() no va seguida de punto y coma porque no se trata de una llamada a una función, sino de la definición de una función. La definición de una función especifica las instrucciones que posee dicha función, así como los argumentos que tiene. 쮿 Las funciones de librería utilizadas por el compilador están a disposición del programador. Para usar estas funciones de librería, es necesario incluir antes el fichero correspondiente. Así, printf es una función de librería que está definida en el fichero stdio.h (standard input/output header). 쮿 Todas las líneas que empiezan con el símbolo # son, en realidad, directivas del lenguaje C, es decir, sirven para ayudar a compilar los programas, realizando algunas tareas antes de comenzar el proceso (preprocesador). La línea #include stdio.h tiene el cometido de incluir la información que hay en el fichero stdio.h en nuestro programa. Por ejemplo, en el fichero stdio.h se encuentra la definición de la función printf. Si no se pusiera include en nuestro programa, el compilador no sabría cómo interpretar printf y daría error. 쮿 La utilización de llaves en el programa tiene la función de agrupar una secuencia o un conjunto de sentencias. Actividades 12 Modifica el programa inicial para añadir otro mensaje de salida por pantalla que diga, por ejemplo, «¡Hola, Pepe!». Lenguajes de programación Cada librería incluye diversas funciones. Por ejemplo, la librería asociada a stdio.h define funciones de entrada y salida estándar. Pero en el fichero ejecutable de nuestro programa solo están las funciones de librería que hemos utilizado. De esta forma, el tamaño del código ejecutable se reduce al mínimo. 51 OS2TE_LINEX.02 8/5/08 13:59 Página 52 3.2. Nuestro segundo programa en C Re c u e r d a En C, todo lo que va entre comillas es una cadena, y una cadena es una secuencia de caracteres. Después de cerrar el proyecto anterior (Archivo 씰 Cerrar proyecto) creamos uno nuevo (Archivo 씰 Proyecto nuevo) con un nuevo nombre, como ejemplo2, configuramos las opciones del asistente de forma similar al anterior e incorporamos el siguiente código fuente, en este caso a un nuevo archivo fuente (Archivo 씰 Nuevo, de tipo C Source File) que llamaremos ejemplo2.c. Eliminamos el ejemplo main.c por defecto y añadimos el nuevo al proyecto: #include stdio.h main ( ) { int a; printf(“Mi segundo programa en C.\n”); printf(“Pulsa la tecla INTRO para terminar.”); getchar( ); printf (“Introduzca un valor para a:”); scanf(“%i”,&a); printf (“El valor es: %i\n”,a); } La salida por pantalla de este programa se muestra en el margen. Salida de nuestro primer programa en C. Análisis de nuestro segundo programa en C En este programa se introducen algunas novedades relativas a la entrada y salida: CARACTERES ESPECIALES NO IMPRIMIBLES Código Significado \b Retroceso \f Salto de página \n Nueva línea \r Retorno de carro \t Tabulación horizontal \” Comillas \’ Apóstrofo \0 Carácter nulo \\ Barra invertida \v Tabulación vertical \a Alerta UNIDAD 2 Actividades 52 13 Escribe un programa que pida y muestre en pantalla el horario de clases en columnas tabuladas 쮿 La secuencia \n es un carácter especial no imprimible que indica la creación de una nueva línea, es decir, funciona como un punto y aparte. Al ser \n un carácter, se puede incluir en cualquier parte de una cadena como otro carácter más. Si no lo hubiésemos incorporado en nuestro programa, la salida habría sido: Mi segundo programa en C. Pulsa la tecla INTRO para terminar. Todos los caracteres que comienzan con \ se denominan secuencias de escape y sirven para dar formato (tabulaciones, saltos de línea…) a la salida de texto por pantalla. 쮿 La función getchar() espera que el usuario pulse la tecla RETURN para continuar la ejecución. Esta función no necesita argumentos, pero los paréntesis son imprescindibles, puesto que se trata de una función. 쮿 La función scanf es la equivalente al printf pero para la entrada de datos por teclado de acuerdo a un formato de los mismos y a la variable en la que se almacenan. Como en printf, en una cadena se indica el formato y, a continuación, las variables, en el orden que corresponda a ese tipo de datos. Por ello, en una sola sentencia se pueden capturar por teclado (scanf) o mostrar por pantalla (printf) los datos de varias variables. Estas funciones básicas de entrada y salida se encuentran en una librería asociada al archivo stdio.h, por lo que siempre que las utilicemos tendremos que incluir esta directiva en nuestro programa: #include stdio.h OS2TE_LINEX.02 8/5/08 14:00 Página 53 3.3. Nuestro tercer programa en C Observa, a continuación, lo que has de escribir en el editor de texto para que te aparezca en la pantalla del terminal de ejecución. #include stdio.h main ( ) /* Tercer ejemplo */ { int horas, minutos, segundos; printf(“Introduce un número de horas: “); scanf(“%i”,&horas); minutos 60 * horas; segundos 60 * minutos; printf (“Hay %d segundos en %d horas.\n”, segundos, horas); } Análisis de nuestro tercer programa en C 쮿 En este lenguaje, el ordenador ignora todo lo que va encerrado entre los signos /* y */, pues indican el principio y el final de un comentario. También se ignora lo que se escribe a la derecha de los signos //. Se utilizan comentarios en los programas para hacerlos más comprensibles (son aclaraciones del programador). 쮿 La línea int horas, minutos, segundos; es una sentencia de declaración. Esta sentencia significa lo siguiente: Salida del tercer ejemplo. 쐌 En algún sitio de la función se usarán las variables horas, minutos y segundos. 쐌 Estas dos variables son de tipo entero (int1). El punto y coma (;) final identifica la declaración como una sentencia o instrucción en C. También se podría haber escrito de esta otra forma: int horas; int minutos; int segundos; Te en la misma o en tres líneas independientes. De igual forma, se han agrupado en una sola línea sentencias de entrada, de salida y de asignación, separadas por (;). interesa saber 쮿 printf significa «escritura» (print) con «formato» (format), pues hace posible que el usuario dé formato a su gusto (tabulaciones, saltos de línea…) a la salida. En C, todas las variables utilizadas han de ser declaradas antes de su uso. Como ya estudiaste con Logo, las variables se almacenan en memoria, y su valor puede variar a lo largo del programa. 쮿 La variable horas se captura de teclado mediante una función de librería scanf. El símbolo (&) que precede a la variable horas indica que lo que se está mandando como argumento no es el valor que posee la variable horas sino la dirección en que se encuentra. El valor introducido sirve para la sentencia siguiente: minutos ⴝ 60 * horas; segundos ⴝ 60 * minutos; donde se asigna a la variable minutos el resultado de multiplicar 60 por horas y a la variable segundos el producto de minutos por 60. Posteriormente, se puede otorgar otros valores a estas variables. 쮿 El signo igual, , es el operador de asignación, y el asterisco, *, el operador de multiplicación. Actividades 14 Escribe un programa en C que calcule el índice de masa corporal. 1 int: abreviatura de integer, palabra inglesa que significa «entero». Lenguajes de programación 쮿 scanf indica exploración o escaneo de la entrada (scan) con formato. 53 OS2TE_LINEX.02 8/5/08 14:00 Página 54 Operadores más comunes En la tabla se describen otros operadores que te pueden resultar útiles. Operador Significado + número positivo (usado como operador unitario) y suma (empleado como operador binario) – número negativo (utilizado como operador unitario) y resta (empleado como operador binario) * operador de multiplicación / operador de división % operador módulo, esto es, resto de la división de dos números enteros Si hemos introducido el valor 3 para las horas, la siguiente línea escribe en pantalla el texto «Hay 10 800 segundos en 3 horas.»: printf (“Hay %d segundos en %d horas.\n”, segundos, horas); Como puedes apreciar, los dos %d no aparecen en pantalla; en su lugar figuran los valores de las variables segundos y horas. El símbolo % avisa a la función printf que se va a imprimir una variable en esta posición, y la letra d informa que dicha variable es entera (digit). La función scanf %i también indica un valor entero para la entrada de horas. 3.4. Funciones en C A medida que vayas progresando en la programación en lenguaje C, descubrirás que puedes crear tus propias funciones y, de esta forma, organizar mucho mejor tus programas. La estructura general de una función en C es la siguiente: tipo nombre_función (argumentos_de_función) { declaración_de_variables sentencias } Como puedes observar, esta estructura se corresponde con la utilizada en los ejemplos anteriores; en general, el nombre de la función no será main («principal»), sino el que tú decidas en cada caso. 3.5. Operaciones con los datos Los datos son la información numérica y textual que se usa en programación. Se introducen mediante declaraciones y expresiones. Actividades UNIDAD 2 15 Escribe un programa que calcule los minutos de clase que tienes en 54 Te interesa saber El tipo void (vacío, sin valor) se utiliza para definir los parámetros y resultados de las funciones. una semana lectiva (sin días de fiesta), utilizando variables de tipo entero, como minutos_por_clase, clases_por_dia, etcétera. 16 Relaciona las funciones de C con los procedimientos de Logo. 17 ¿Qué tipos de sentencias de C conoces? ¿En qué se diferencian? OS2TE_LINEX.02 8/5/08 14:00 Página 55 Tipos de datos Es posible establecer una primera división de los datos distinguiendo entre constantes, datos con valores fijos que no pueden ser alterados por el programa, y variables, cuyo valor se puede cambiar a lo largo del programa. Una segunda clasificación de los datos es la que corresponde al tipo de información asociada. Reflexiona Realiza el siguiente programa y explica lo que aparecerá en pantalla: #include stdio.h main () /*cuarto ejemplo */ { int i 1; char c ’c’; float f 1.0; double d 1e-1; printf (“\ti %d\n\tc %c\n\tf %f\n\td %lf\n”, i, c, f, d); return(0); } TIPOS DE DATOS BÁSICOS EN LENGUAJE C Tipo Descripción Rango char Carácter 0 a 255 int Entero 32768 a 32768 float Coma flotante Aproximadamente 6 dígitos de precisión double Coma flotante de doble precisión Aproximadamente 12 dígitos de precisión void Sin valor Sin valor Observa el resultado en pantalla. Como se ve en el programa, es posible asignar un valor a una variable en el momento de la declaración. Conjuntos de datos Las cadenas de caracteres corresponden a conjuntos de datos denominados arrays, que son secuencias de datos almacenados en memoria en posiciones consecutivas, a los que podemos acceder de forma independiente. Así, por ejemplo, el array “abc” se almacenaría en memoria como: a b c \0 El carácter ‘\0’ se llama carácter nulo y se utiliza para marcar el final de la cadena en memoria. De esta forma, el carácter ‘a’ sería el elemento 0 del array, y los caracteres ‘b’ y ‘c’ serían los elementos 1 y 2. Debes tener precaución con el acceso a posiciones sucesivas (posteriores a la última definida), ya que podría tener efectos inesperados. Re c u e r d a Como vimos, las cadenas de caracteres (también llamadas string), van entrecomilladas. Las comillas no forman parte de la secuencia, sino que sirven para especificar el comienzo y el final de la misma. A continuación, se muestran algunos ejemplos de cadenas de este tipo: “En el punto donde se detiene la ciencia, empieza la imaginación.” “abc” “a” “\n a \n b \n c \n” Lenguajes de programación En el apartado anterior ya se dijo que %d indica a la función printf el lugar en que se ha de escribir una variable de tipo entera. Los códigos %c, %f y %lf señalan a dicha función el lugar en la cadena de caracteres en la que se han de escribir variables de tipo char, float y double, respectivamente. Finalmente se ha devuelto el valor 0 para la función main, que por defecto es de tipo int aunque no se defina, y esto puede tomarse como un resultado para una posible función invocadora, o como un código de error de ejecución en otros casos, por lo que suele devolverse por defecto el valor 0 como indicador de éxito. 55 OS2TE_LINEX.02 8/5/08 14:00 Página 56 Comillas o apóstrofos Conviene tener presente que 'x' es distinto de “x”: 쮿 'x' es una constante de tipo carácter. Pertenece a un tipo básico (char). 쮿 “x” es una cadena de caracteres. Se trata de un tipo derivado (array compuesto de elementos del tipo básico char). En realidad, “x” contiene dos caracteres, a saber, 'x' y '\0'. Uso de los arrays Una variable array se declara del siguiente modo: tipo nombre_array [numero_de_elementos]; A cada elemento del array (son números naturales y definen la posición de la memoria) se accede de esta forma: nombre_array [numero_de_elemento]; Así, por ejemplo, al primer y segundo elemento de un array se accederá, respectivamente, mediante: nombre_array [0]; nombre_array [1]; Con el resto de los elementos del array se procede de modo similar. Reflexiona Realiza el siguiente programa: #include stdio.h main ( ) { int x[2]; /* se reserva memoria para dos elementos de tipo int */ x[0] 10; x[1] 11; /* el elemento x[2] no existe, no se ha reservado memoria */ printf (“\nx[0] %d\nx[1] %d\n”, x[0], x[1]); } 쮿 Explica qué pasaría si se hubiera escrito x[2] 3; El compilador probablemente no nos informará de ningún error; sin embargo, el valor 3 quedará guardado en una posición de memoria del ordenador reservada para indicar el final del array. De esta manera, al ejecutar el programa, es posible que se produzcan efectos inesperados en el funcionamiento no solo de nuestro programa, sino también de otras utilidades o en el propio sistema operativo. 3.6. Expresiones Para operar con datos de cualquier tipo, se utilizan operadores que indican la operación que se va a realizar. 쮿 Un operador es un símbolo que realiza una determinada operación sobre sus operandos. UNIDAD 2 쮿 Un operando es un dato, variable o constante, que es manipulado por el operador. 56 Los operadores se pueden dividir en cinco grupos: aritméticos, relacionales y lógicos, a nivel de bits, especiales y de asignación. Los veremos a continuación. OS2TE_LINEX.02 8/5/08 14:00 Página 57 Operadores aritméticos Estos operadores realizan operaciones aritméticas. En la siguiente tabla se muestran algunos de ellos: OPERADORES ARITMÉTICOS Operador Acción Resta, también menos monario Suma, también suma monaria * Multiplicación / División % Módulo (resto) de la división Decremento (monario) Incremento (monario) Re c u e r d a El término relacional se refiere a la relación entre unos valores y otros, mientras que el vocablo lógico alude a las formas en que esas relaciones pueden conectarse entre sí. Ambos operadores se basan en la idea de verdadero (true en inglés) y falso (false en inglés). Para cualquier valor distinto de cero, la expresión es cierta, y para 0 es falsa. Las expresiones que son ciertas toman el valor de 1 y las que son falsas, el 0. OPERADORES RELACIONALES OPERADORES LÓGICOS Operador Acción Operador Acción Mayor que && Y Mayor o igual que || O Menor que ! No Menor o igual que Igual ! No igual Operadores a nivel de bits Con estos operadores se realizan operaciones sobre los bits de un byte o una palabra (dos bytes). Solo se pueden utilizar con los tipos char e int. OPERADORES A NIVEL DE BITS Operador Acción Operador Acción & Y ~ Complemento a uno (NOT) | O Desplazamiento a la derecha ^ O exclusiva (XOR) Desplazamiento a la izquierda A diferencia de los operadores relacionales y lógicos, cuyo resultado es siempre 0 o 1, las operaciones de bits pueden producir cualquier valor arbitrario resultante de la operación bit a bit de los operandos de la expresión. En cuanto a los operadores de desplazamiento, en una expresión con , el operando anterior se desplaza tantos bits a la derecha como indique el operando posterior; por su parte, en una expresión con , el operando anterior se desplaza tantos bits a la izquierda como indique el posterior. Actividades 18 Observa los valores que van tomando las variables y deduce el valor que devuelve la función siguiente: int operadores (void) { int a[4], b[3]; char c[2]; a[0] 2 3 * 4; /* a[0] 14; */ a[1] (2 3) * 4; /* a[1] 20; */ a[2] 10 / 2 % 3; /* a[2] 2; */ a[3] a[0] a[2]; /* a[3] 12; a[2] 3;*/ b[0] 10 12; /* b[0] 1; */ b[1] 2 && 3; /* b[1] 1; */ b[2] 2 & 3; /* b[2] 2; */ c[0] 2; /* 0000 0010 (2) */ c[1] 3; /* 0000 0011 (3) */ c[0] c[0] | 9; /* 0000 1011 (11)*/ c[1] c[1] 1; /* 0000 0110 (6) */ c[0] (4 ^ 5) & 6; /* 0000 0000 (0) */ return a[2]b[1]c[1]; } Lenguajes de programación Operadores relacionales y lógicos 57 OS2TE_LINEX.02 8/5/08 14:00 Página 58 Operadores especiales Te interesa saber La evaluación de los operadores sigue un orden bien establecido, de acuerdo a su nivel de precedencia. A igual nivel de precedencia son evaluados por el compilador de izquierda a derecha. Para que resulte más sencillo el orden de evaluación de las expresiones, se recomienda el uso de paréntesis. En este apartado se incluye una serie de operadores que no pueden agruparse en ninguno de los otros anteriores. Son los siguientes: Operador condicional (?) El operador ? tiene la forma general: expresión1 ? expresión2 : expresión3 donde expresión1, expresión2 y expresión3 son expresiones en C. El operador ? actúa de la siguiente forma: evalúa la expresión1, y si es cierta, pasa a evaluar la expresión2 y toma ese valor como resultado; si, por el contrario, la expresión1 es falsa, evalúa la expresión3 y toma su valor para la expresión resultante. Reflexiona Realiza este programa y averigua el valor de las variables en cada una de las siguientes expresiones: int x, y, z; x 2 3 ? 4 : 5; y 2 3 ? 4 : 5; z 1 2 ? (4 3 ? 2 : 3) : 5; Re c u e r d a Un operador monario actúa solo sobre un operando, mientras que un operador binario actúa sobre dos operandos. En la primera expresión, a x se le asigna el valor 4; en la segunda, a y se le asigna el valor 5, y en la tercera, a z se le asigna el valor 2. Operadores de dirección (&) y de contenido (*) La definición de un puntero se haría así: Estos dos operadores son monarios y operan con punteros. Los punteros surgen de la necesidad de conocer la dirección de memoria de una variable, más que el valor que tiene. El significado que tiene en este caso el operador * no tiene nada que ver con el operador aritmético indicado con el mismo signo. En el código fuente no hay confusión entre uno y otro, pues el aritmético es binario y el de punteros es monario. Lo mismo ocurre con el operador &. TipoBase * NombreVarPuntero Operador coma (,) Por ejemplo: int *pnum; Además de representar una lista de elementos (como en printf), la coma (,) puede emplearse como operador para encadenar varias expresiones. Estas expresiones son evaluadas de izquierda a derecha, y el valor de la expresión total es el valor de la expresión situada en el extremo de la derecha. Fíjate en el ejemplo: Te interesa saber La asignación de un puntero con una dirección de una variable se haría así: NombreVarPuntero &Variable Por ejemplo: pnum & dato1; La asignación de un valor en la dirección apuntada por el puntero sería así: UNIDAD 2 *NombreVarPuntero Valor 58 Por ejemplo: *pnum 45; Si un puntero no señala a ningún sitio, se utiliza el valor constante NULL para la asignación o comparación. int x; x (2, 3, 4); En este caso, a x se le asigna el valor 4. Actividades 19 Completa el código del ejemplo de operador condicional para mos- trar en pantalla el valor que toman las variables x, y y z. OS2TE_LINEX.02 8/5/08 14:00 Página 59 Operadores de asignación Como hemos visto en ejemplos anteriores, una sentencia de asignación es aquella en la que se asigna un valor a una variable. Responde a la forma general: nombre_variable operador_de_asignacion expresion; Los operadores de asignación son los siguientes: , *, /, %, , , , , &, ^, | El operador asigna el valor de la expresión que está a la derecha a la variable que se encuentra a su izquierda. La asignación se evalúa de derecha a izquierda. Por ejemplo: int a, b, c; int x, y; a 5; b 4 a; c (a * b) 1; x y 2; El resto de los operadores de asignación se exponen en la siguiente tabla a modo de ejemplo, utilizando los valores x e y anteriores: Sentencia de asignación Asignación equivalente x y x * y; x x * y; 4 2 x / y; x x / y; 1 2 x % y; x x % y; 0 2 x y; x x y; 4 2 x y; x x y; 0 2 x y; x x y; 8 2 x y; x x y; 0 2 x & y; x x & y; 2 2 x ^ y; x x ^ y; 0 2 x | y; x x | y; 2 2 3.7. Sentencias de control La mayoría de las sentencias de control de cualquier lenguaje están basadas en condiciones y se conocen como sentencias condicionales. Ya sabemos que una condición es una expresión cuya resolución da como resultado verdadero (true) o falso (false) y que cualquier valor distinto de cero es true, mientras que el valor cero es false. Otros tipos de sentencias, no directamente condicionales, son las sentencias iterativas y las de control de secuencia. Sentencias condicionales El lenguaje C posee dos sentencias condicionales: if y switch, además del operador ?, que en ocasiones puede emplearse en lugar de if. Te interesa saber La expresión (s ⴝ 0, i ⴝ 1) está formada por el operador coma, cuyos operandos son expresiones de asignación. Te interesa saber Otros dos operadores muy utilizados son el de incremento y el de decremento, ambos monarios. El primero suma 1 a su operando, mientras que el segundo resta esa misma cantidad. 쮿 La sintaxis del operador de incremento es: ⴙⴙx; o xⴙⴙ; y es equivalente a xⴙⴝ1, y también a xⴝxⴙ1. 쮿 Por su parte, la sintaxis del operador de decremento es: ⴚⴚx; o xⴚⴚ; que equivale a xⴚⴝ1, y también a xⴝxⴚ1. Lenguajes de programación Lo anterior dará como resultado la asignación de los valores enteros 5, 9 y 44 a las variables a, b y c, así como el valor 2 a las variables x e y, teniendo en cuenta que el 2 se asigna primero a la y y después a la x. 59 OS2TE_LINEX.02 8/5/08 14:00 Página 60 Sentencia if La sintaxis de este tipo de sentencias viene dada por una de estas dos estructuras: Te Estructura 1 if (expresión) sentencia interesa saber Las condiciones se evalúan de arriba hacia abajo. Solo se ejecuta la sentencia correspondiente a la primera expresión que sea cierta, si la hubiera. Si ninguna es cierta, se ejecuta el else final si existiese; de lo contrario, no se ejecuta ninguna sentencia. Estructura 2 if (expresión) sentencia_1 else sentencia_2 Si la expresión es verdadera, se ejecuta la sentencia correspondiente a if; si es falsa, se ejecuta la sentencia correspondiente al else, en el caso de que la hubiera. En el segundo caso se ejecuta sentencia_1 o sentencia_2, pero nunca ambas. Por necesidades de programación, puede resultar necesario anidar varias sentencias if, es decir, meter unas dentro de otras. Reflexiona Observa el siguiente programa: if (x y) if (x z) numero_menor x; else numero_menor z; else if (y z) numero_menor y; else numero_menor z; 쮿 ¿Cuál es el objetivo del mismo? Actividades 20 Explica cómo funcionan los siguientes programas: a) b) UNIDAD 2 c) 60 if (contador 50) contador; if (xy) zx; else zy; if (ch‘\n’) { numero_de_lineas; numero_de_caracteres ; } Como puedes deducir, se trata de asignar a la variable numero_menor el valor de la variable x, y o z que sea menor de los tres, mediante una estructura if-else anidada. Puesto que cada rama de las sentencias if-else solo lleva asociada una única sentencia, no es necesario poner llaves. Fíjate también en que se ha sangrado el código por niveles de anidamiento, lo que ayuda a evitar errores. Una estructura también muy común en programación es la denominada escala if-else-if, que aparece a continuación, junto con un programa cuya finalidad es idéntica a la del anterior: if (expresión1) sentencia else if (expresión2) sentencia_2 . . . else sentencia_n if (x y && x z) numero_menor x; else if (y x && y z) numero_menor y; else numero_menor z; OS2TE_LINEX.02 8/5/08 14:00 Página 61 Sentencia switch La sentencia switch amplía las posibilidades de la sentencia if de forma sencilla y ordenada. Estas sentencias se rigen por la siguiente sintaxis: switch (expresión) { case expresión_constante_1: sentencias_1 break; case expresión_constante_2: sentencias_2 break; . . default: sentencias_n } El switch evalúa la expresión con cada una de las expresiones constantes (casos), de arriba abajo, hasta hallar la correcta. Cuando la encuentra, ejecuta las sentencias correspondientes a esa rama (case). Si no hay ningún caso que coincida con la expresión, se ejecutan las sentencias correspondientes a la rama default, si existen, dado que es opcional; si no está definida dicha rama, no hace nada. Te interesa saber A continuación, se muestra un ejemplo de utilización de la sentencia switch. En cada uno de los casos, se realiza una operación diferente con las variables x e y. switch (operando) { case 1: x * y; break; case 2: x / y; break; case 3: x y; break; case 4: x y; break; default: printf (“¡ERROR!”); } Las sentencias break en el switch son opcionales. El break hace que se produzca una salida inmediata de la sentencia switch. Actividades main() { char opcion_menu; int jugadores = 0; printf("Elige una opcion (0-2): "); opcion_menugetchar(); switch (opcion_menu) { case '1': jugadores 1; printf("Has elegido jugar tú solo contra el ordenador.\n"); break; case '2': jugadores 2; printf("Has elegido jugar contra otra persona.\n"); break; case '0': printf("Has decidido no jugar, otra vez será…\n"); break; default: printf("ERROR: Esta opción no estaba definida\n"); } if (jugadores 0) printf("Ahora comenzaría el juego…\n"); } 쮿 A continuación, explica su utilidad. Lenguajes de programación 21 Realiza el siguiente programa: 61 OS2TE_LINEX.02 8/5/08 14:00 Página 62 Sentencias iterativas Ejemplo 3 i 0; while (s[i] ‘ ‘) i; Ejemplo 4 Los bucles o sentencias iterativas permiten ejecutar un conjunto de instrucciones hasta que se alcance una cierta condición. Las sentencias iterativas en C son while, for y do. Sentencia while Para expresar en C un bucle que habrá de repetirse mientras (while) se cumpla una determinada condición, se emplea la siguiente sintaxis: i 1; while (i 5) { printf (“\ni %d”, i); i; } while (expresión) sentencia Se evalúa la expresión y, si es verdadera, se ejecuta la sentencia y se vuelve a evaluar la expresión. El ciclo continúa hasta que se llega a una expresión falsa, momento en el que la ejecución continúa con lo que hay fuera del bucle. Los ejemplos que aparecen al margen te ayudarán a entender mejor esta sentencia. Te interesa saber 쮿 La forma general descrita para la sentencia for es equivalente a la estructura de la sentencia while: expresión1 while (expresión2) { sentencia expresión3; } 쮿 La siguiente instrucción es un bucle infinito: for (;;) sentencia Las tres expresiones de la sentencia for son opcionales, aunque los puntos y coma siempre deben aparecer. 쮿 El ejemplo 1 es un bucle para contar las posiciones que contienen espacios en blanco en un array s. 쮿 El ejemplo 2 es un bucle que escribe en pantalla los cinco primeros números naturales. Sentencia for Con este tipo de sentencias es posible crear bucles más complejos, mediante la sintaxis siguiente: for (expresión_1; expresión_2; expresión_3) sentencia En la sentencia for, expresión1 se denomina inicialización; expresión2, condición, y expresión3, incremento. Por tanto, la ejecución de esta instrucción implica una inicialización la primera vez que se ejecuta (vuelta del bucle); las sucesivas vueltas se llevan a cabo mientras se cumple la condición, aplicándose, además, el incremento. Reflexiona Explica qué indica cada parte de esta sentencia for y el resultado del código: for (s 0, i 1; i 100; i) s i; printf (“La suma de los cien primeros números es %d.”,s); UNIDAD 2 Actividades 62 22 Indica cuántas veces se ejecuta la siguiente sentencia en el for: for (i0; i 10; i) sentencia En la primera expresión se inicializan las variables s e i (a 0 y 1, respectivamente), utilizando el operador coma, que ya conoces. La siguiente expresión determina la condición de salida del bucle, que tendrá lugar cuando i deje de ser menor o igual que 100. La última expresión del for indica qué se hará en las repeticiones con las variables; en este caso, se realiza el incremento de la variable i. El bucle se repetirá 100 veces, y en cada vuelta se acumula en s el valor que va tomando i, por lo que se van sumando todos los números del 1 al 100. OS2TE_LINEX.02 8/5/08 14:00 Página 63 Sentencia do De forma similar a la sentencia while, la sentencia do permite hacer bucles que al menos se ejecutan una vez, dado que la condición de salida se evalúa al final. Utiliza la siguiente sintaxis: do sentencia while (expresión); En la instrucción do se ejecuta primero la sentencia y, a continuación, se evalúa la expresión. En caso de ser cierta, se ejecuta la sentencia de nuevo, y así sucesivamente hasta que la expresión resulta ser falsa. Te interesa saber El bucle del siguiente ejemplo permite obtener la suma de los cincuenta primeros números naturales mediante la sentencia do: int s0, i1; do { ssi; } while (i 50); printf(“La suma es %d.”,s); Sentencias de control de secuencias: break y continue 쮿 Como se vio anteriormente, la sentencia break provoca la salida inmediata de switch. Esto también es aplicable a las sentencias while, for y do. Veamos cómo utilizarla dentro de un bucle for: for (i 0, i 10; i) for (j 0, j i; j) if (j 5) break; En este ejemplo, la ejecución de la sentencia break provoca una salida del bucle for de la variable j, pero no tiene ningún efecto sobre el bucle for de la variable i. 쮿 La sentencia continue funciona de manera similar. En vez de forzar la terminación, obliga a realizar una nueva vuelta del bucle saltándose cualquier código que exista entre medias. En los bucles while y do, una sentencia continue da lugar a que el control pase directamente a la evaluación de la condición y prosiga el proceso del bucle. En el caso de un for, primero se ejecuta la parte incremento del bucle; a continuación, se lleva a cabo la evaluación de la condición y, finalmente, el bucle prosigue. Reflexiona for (i 0; i 100; i) { numero array_de_numeros [i]; if (numero 0) continue; printf (“%d\t”, array_de_numeros [i]); } Actividades 23 Diseña un programa que El bucle escribe en pantalla todos los números positivos de un array de 100 números enteros, denominado array_de_numeros. La sentencia continue sirve para saltarse los números negativos y forzar una nueva vuelta del bucle. genere la lista de los cien primeros números pares. Hazlo de tres formas distintas: con bucle for, while y do. Lenguajes de programación ¿Qué hace el bucle siguiente y qué efecto tiene la sentencia continue? 63 OS2TE_LINEX.02 8/5/08 14:00 Página 64 3.8. Programación visual en C Las aplicaciones vistas hasta ahora en C tienen una interfaz basada en una simple ventana de terminal y una entrada de datos por teclado. Sin embargo, en muchos casos se hace necesario disponer de una interfaz gráfica de usuario (GUI), más agradable para las aplicaciones, basada en elementos gráficos y con una funcionalidad sujeta a eventos. Para el desarrollo de este tipo de aplicaciones se dispone de entornos de usuario capaces de diseñar interfaces gráficos y de librerías de software que facilitan la programación sobre el mismo. Es el caso de Glade, una herramienta de desarrollo rápido de aplicaciones (RAD) que, por medio de librerías gráficas GTK, permite crear interfaces completos basados en un solo archivo XML, que describe de forma jerárquica sus elementos u objetos, comúnmente denominados widgets. Usaremos Glade desde Anjuta IDE para crear nuestras aplicaciones gráficas en C para LinEx. El asistente de creación de proyectos de Anjuta nos servirá como punto de partida para crear una aplicación del tipo LibGlade con lenguaje C y para generar un archivo ejecutable. Al finalizar el asistente, se genera automáticamente una aplicación básica con un solo archivo fuente, main.c, y un archivo XML, que describe la interfaz relacionada con el anterior. En este caso se trata de aplicacion.glade, lista para ser compilada (tecla F11) y ejecutada (tecla F3). Usaremos estos archivos a modo de plantilla o base de la nueva aplicación. Empezaremos por modificar la interfaz gráfica y después el código asociado. Para ello, usaremos la opción del menú Proyecto 씰 Editar GUI de la aplicación (o bien, Alt-G) y accedemos al entorno de Glade, que dispone de tres ventanas principales: 쮿 Ventana de Proyecto o ventana principal, en la que se gestionan los componentes gráficos (ventanas, menús, diálogos) que integran el mismo. Desde aquí se realiza también la generación automática del código en C equivalente al entorno gráfico creado, que puede modificarse después. UNIDAD 2 Ventana de proyecto. Ventanas de paleta y de propiedades. 64 쮿 Ventana de Paleta, donde se eligen los distintos componentes que se van a incluir en el proyecto, haciendo clic en el icono correspondiente de todos los objetos disponibles o widgets (que pueden traducirse como «pequeños artificios»). 쮿 Ventana de Propiedades del componente u objeto seleccionado, en la que se puede alterar alguna propiedad visual o indicar qué eventos («clics» de ratón, selección, combinación de teclas…) le afectarán y cuál es el manejador asociado (función en C) a dicho evento. Dentro del proyecto aparece inicialmente un solo elemento, window1, correspondiente a la ventana inicial que genera el asistente de Anjuta con LibGlade. Haciendo clic sobre el mismo se abre dicha ventana en modo diseño. Una vez definida la interfaz gráfica y los eventos necesarios, el paso final consiste en desarrollar el código específico de la aplicación asociado a dichos eventos; una función C por cada evento cuyo nombre se asignó en el diseño de la interfaz. OS2TE_LINEX.02 8/5/08 14:00 Página 65 4 Aplicaciones a la robótica La creación de programas para ordenador puede extenderse a otros dispositivos programables que se comportan como miniordenadores y se denominan normalmente microcontroladores. Para crear robots y dotarlos de ciertas funciones «inteligentes», suelen utilizarse estos microchips a modo de «cerebro» del robot; recogen información de ciertos sensores y activan en consecuencia ciertos actuadores (motores, conmutadores, generadores de sonidos, etc) de acuerdo a un programa que se ejecuta en el mismo. A la hora de crear una aplicación basada en un microcontrolador, necesitamos una serie de herramientas, tanto de hardware como de software, que nos permitan desarrollar dicha labor con la mayor rapidez y fiabilidad. Por lo que respecta al software, se suelen utilizar las herramientas que proporciona el propio fabricante del microcontrolador u otras de terceros. Linux y el software libre asociado al mismo proporcionan el soporte necesario para el desarrollo de diferentes aplicaciones relacionadas con los microcontroladores, como ensambladores, compiladores, simuladores, programadores en circuito, etcétera. Algunas marcas de juguetes de construcción ya ofrecen la posibilidad de montar pequeños robots programables desde un ordenador. 4.1. Ensambladores y compiladores cruzados Las herramientas de desarrollo de software para microcontroladores no operan directamente sobre el microcontrolador que va a ejecutar finalmente el código desarrollado, sino que se ejecutan sobre un ordenador y simulan el comportamiento del microcontrolador final. Por ello, han sido denominadas comúnmente herramientas cruzadas (ya sean ensambladores o compiladores). Como herramientas de trabajo en LinEx para la programación de microcontroladores, adoptaremos aquí sdcc (compilador cruzado de C), gpasm (ensamblador cruzado), gpsim (simulador) y picprog (herramienta de grabación). Los diferentes elementos que conforman la programación de microcontroladores en C se muestran en el siguiente diagrama: sdcc archivo.c archivo.asm archivo.cod archivo.hex gpsim picprog simulación visual Lenguajes de programación archivo.stc gpasm 65 OS2TE_LINEX.02 8/5/08 14:00 Página 66 Procedimientos Animaciones por software Uno de los usos más notorios y espectaculares de la programación consiste en realizar efectos visuales y animaciones con el ordenador. Concretamente, el campo de la simulación por ordenador tiene una faceta gráfica que ha exigido a los programadores depurar al máximo sus «rutinas» con objeto de obtener resultados visualmente realistas. Es lo que se conoce como «realidad virtual», técnica que tiene muchas aplicaciones comerciales y artísticas, por ejemplo en los videojuegos o en las producciones cinematográficas actuales, donde no resulta fácil diferenciar lo simulado con el ordenador de lo auténticamente real. A continuación, aplicaremos lo aprendido realizando un programa de animación gráfica con XLogo. La idea: «Programar es divertido» Vamos a desarrollar un programa en lenguaje Logo que, al ejecutarse, muestre en el terminal gráfico una breve secuencia animada con formato de anuncio televisivo. En nuestro spot transmitiremos la idea de que hacer programas de ordenador puede ser incluso más divertido que utilizarlos. UNIDAD 2 Para ello, recurriremos al procedimiento ESPIRAL que ya vimos para crear una ilusión óptica de movimiento que posteriormente dé paso al mensaje de la campaña acompañado de su logotipo. 66 Estructura y análisis del anuncio El anuncio y, en consecuencia, el programa constan de cuatro partes: 1. Movimiento de la espiral. Es la fase más compleja del programa y en ella habrá que diseñar un algoritmo que dibuje cada vez una espiral distinta. Esto se puede conseguir incrementando, en una unidad por espiral, el ángulo de giro de la tortuga cuando traza los lados consecutivos. Para darle un efecto más colorista, varía al azar el color del trazado con las órdenes PONCOLOR y AZAR. 2. Mensajes. Debes incluir tres mensajes en momentos distintos del programa. Para ello, indícale a la tortuga, con la orden ROTULA, que los rotule. Comienza a escribir en una parte determinada de la pantalla, sirviéndote de la orden PONXY. El primer mensaje es «Te puedes quedar toda la vida mirando el mismo canal…». El segundo mensaje, continuación del anterior, reza «…o aprender a hacer tus propios programas.» Por último, escribe el tercer mensaje al final de la presentación: «Es un consejo de la Dirección General Contra el Aburrimiento.» OS2TE_LINEX.02 8/5/08 14:00 Página 67 Procedimientos 3. Logotipo de la campaña. Consistirá en una especie de i (de «imaginación»), coronada por un triángulo rojo. También es fácil de realizar moviendo convenientemente la tortuga con las órdenes AV y GD. El grosor de la línea se puede aumentar con la orden PONGROSOR [número]. 4. Final. Realiza la transición entre el segundo mensaje y el tercero haciendo que parpadee la tortuga en el centro de la pantalla. Utiliza para ello el bucle REPITE. inicio inicio datos: tamaño y ángulo tamaño 500 SÍ salida NO dibujar lado pintar espirales incrementar lado insertar logotipo y mensajes Diagrama de flujo del procedimiento ESPIRAL. restablecer entorno fin El código Para introducir el código podemos utilizar editor de texto Diana (gedit) y posteriormente guardar el fichero con el nombre anuncio.lgo, por ejemplo. Para programas cortos, resulta conveniente utilizar el Editor de procedimientos, que identifica y diferencia los comandos. Empieza por el procedimiento que traza la espiral. Para ello, pulsa sobre Editar y escribe lo siguiente: # Procedimiento espiral llamado por anuncio # Dibuja una espiral cada vez que se invoca para espiral :tamaño :angulo # Cuando se llama al procedimiento espiral, # hay que pasar 2 variables SI :tamaño 500 [ALTO] # Salida del procedimiento cuando se supera # el tamaño 500 AV :tamaño GD :angulo espiral :tamaño2 :angulo # El procedimiento se llama a sí mismo incrementando # el valor de la variable :tamaño en 2 unidades fin El carácter almohadilla (#) es necesario para que XLogo no confunda los comentarios del programa con el código. La explicación del procedimiento es muy sencilla: cuando el procedimiento ESPIRAL es llamado por el programa principal, se le pasan dos variables: el tamaño inicial del lado, que se incrementa en 2 unidades por ciclo, y el ángulo de giro, que se mantiene constante en cada llamada (más adelante, haremos que se incremente en una unidad cada vez que llamemos al procedimiento ESPIRAL). La tortuga termina su trabajo cuando el tamaño del lado llega a 501, una vez dibujada una espiral completa. En otros lenguajes de programación, esto recibe el nombre de subrutina. Vamos a ensayar el procedimiento para comprobar su buen funcionamiento. Para ello, debemos comprobar que no produce ningún error de estructura al pulsar sobre el botón del pingüino. Una vez solucionados los posibles problemas (en el caso de que hubiera surgido alguno), guardamos el procedimiento en el directorio de trabajo mediante la opción Guardar como… de XLogo, con el nombre espiral.lgo. A continuación, define los colores en la entrada de comandos y pulsa Intro: BP PONCL 3 PONCOLORPAPEL 0 espiral 10 79 Interesante Los comentarios son fundamentales en programación por dos motivos: recuerdan el cometido del código al autor de cara a posibles modificaciones y lo hacen rápidamente inteligible para otros programadores. Lenguajes de programación parpadeo de transición y créditos 67 OS2TE_LINEX.02 8/5/08 14:00 Página 68 Procedimientos En tu pantalla aparecerá un entramado de líneas como el de la figura: A continuación abordaremos el programa principal, que se encargará de llamar un número de veces, dependiendo de la velocidad de procesamiento del ordenador, al procedimiento espiral. Dejaremos para el final la labor de rotular los mensajes y pintar el logotipo. Abre de nuevo XLogo y escribe el código del procedimiento principal: UNIDAD 2 # Programa ANUNCIO Aprende a Programar # FICHERO: anuncio.lgo VERSION 02.Beta feb 2008 para anuncio #inicializamos todos los parametros y variables PONCP negro MODOVUELTA PONTAMAÑOPANTALLA [600 450] HAZ “angulo 200 REPITE 20 [BP PONCL 1 AZAR 17] espiral 1 :angulo ESPERA 1 HAZ “angulo :angulo1] 68 Una vez observado el resultado, tanto este número como el ángulo inicial se pueden cambiar por consideraciones estéticas. En cada ciclo del bucle se borra primero la pantalla, se elige un color al azar entre 1 y 17, se llama a espiral con tamaño de lado 1 y el valor que tenga la variable angulo, se espera un instante, se incrementa el ángulo en una unidad y se vuelve a empezar. Esta repetición de imágenes será la que cree el efecto de movimiento. inicio inicializo ángulo0 (continúa) Las primeras líneas son las notas de cabecera del programa, muy importantes para ubicarnos cuando el código es extenso. Empezamos con el procedimiento principal, que llamaremos anuncio. Lo primero que debes hacer es definir la variable angulo e inicializarla con un valor de 200°. Después, haz un bucle, que llamará al procedimiento espiral, repitiéndolo veinte veces. borrar pantalla y color al azar incrementar ángulo tamaño 361 NO retardo llamar a proceso ESPIRAL SÍ (continúa) OS2TE_LINEX.02 8/5/08 14:00 Página 69 Procedimientos # Comienzan mensajes ESPERA 10 BP # inicializa el color, el grosor y la posición del lápiz PONCL blanco PONGROSOR 6 PONPOS [-100 -100] OCULTATORTUGA # Texto del primer mensaje PF 13 ROTULA [\ \ \ \ Te puedes quedar toda la vida mirando el mismo canal …] ESPERA 250 # Posiciona para segundo mensaje PONPOS [-160 60] ROTULA [ \ \ ...o aprender a hacer tus propios programas.] # Punto sobre la i ESPERA 50 PONCL rojo MUESTRATORTUGA ESPERA 200 # Logotipo terminado BP # Mensaje final OCULTATORTUGA SUBELAPIZ # Para no pintar al moverse PONPOS [ -200 -200] PONCL blanco PF 16 ROTULA [Es un consejo de la Dirección General Contra el Aburrimiento] # parpadeo CENTRO PONCL rojo REPITE 8 [ESPERA 20 OCULTATORTUGA ESPERA 20 MUESTRATORTUGA] ESPERA 200 # Restaura los parámetros iniciales PF 12 PONGROSOR 1 MUESTRATORTUGA BAJALAPIZ BP # Borra y acaba fin Para ejecutar el programa, debes cargarlo en el intérprete con la opción Abrir del menú principal y ejecutarlo con la llamada al procedimiento anuncio desde la línea de comandos. Observarás que el efecto es sorprendente, pero puedes optimizarlo y darle un toque personal cambiando el ángulo inicial y el número de veces que se repite el ciclo. Conclusiones La programación es un lenguaje que nos sirve para entendernos con las máquinas y, al igual que otros lenguajes, solo tiene el límite que nuestra imaginación y perseverancia quieran ponerle. El ejemplo estudiado permite seguir todos los pasos que hay que dar en la elaboración de un programa, para lo cual ha bastado con utilizar un limitado número de instrucciones. No obstante, Logo posee otras muchas instrucciones que hacen posible la realización de complejos programas y funciones. Como habrás observado, Logo es un lenguaje ideal para iniciarse en esta apasionante técnica que es la creación de programas para ordenadores. Interesante En 1973 apareció la primera película de Hollywood que utilizó imágenes generadas por ordenador. De ese modo se consiguió crear una serie de efectos especiales desconocidos hasta la fecha. El nombre de la película era Westworld (traducida al castellano como Almas de metal) y en ella se utilizaron imágenes generadas por ordenador en 2D. Actividades 1 Analiza el código completo y realiza una tabla con todas las instrucciones nuevas incluidas en el programa, indicando su función. 2 Modifica los parámetros y variables del programa diseñado: introduce otro giro en el procedimiento espiral, varía el incremento del ángulo, elígelo al azar o cambia el tiempo de retardo que permanece en pantalla cada espiral, entre otras posibles modificaciones. Esta será una buena manera de familiarizarte con los mecanismos de la programación. 3 Si te fijas en el la figura de la página 66, el texto aparece cambiado en relación a nuestro anuncio. Realiza los ajustes y cambios necesarios en el programa para que quede igual. 4 Realiza un informe sobre la evolución de la animación por ordenador en el cine y la televisión, hasta llegar al momento actual. No olvides guardar el procedimiento con el nombre anuncio.lgo mediante el menú de XLogo. Ya solo queda montar el programa con los procedimientos espiral y anuncio. Esta tarea la puedes realizar de varias formas; utilizaremos la más simple, que consiste en incluir ambos códigos en el mismo sitio. Para ello, debes abrir con Diana el fichero espiral.lgo y, sirviéndote de las utilidades del editor, añadirlo completo al final del programa principal, que guardarás con el nombre de anuncio.lgo. Lenguajes de programación Lo que queda del programa principal es muy sencillo y puede entenderse perfectamente con los comentarios que acompañan las instrucciones. Lo introduciremos a continuación del código anterior: 69 OS2TE_LINEX.02 8/5/08 14:00 Página 70 Procedimientos Desarrollo de una aplicación sencilla con Glade Vamos a crear una aplicación para convertir euros a pesetas y viceversa, con la siguiente interfaz gráfica: tido de la conversión, y un último botón (button3) para salir del programa, con icono y el título «Salir» incluidos. Empezamos creando desde la ventana principal un nuevo proyecto seleccionando Proyecto 씰 Nuevo. Etiquetas y entradas de texto Dentro del proyecto nos aparece inicialmente un único elemento window1, correspondiente a la ventana inicial que genera el asistente de Anjuta con LibGlade. Haciendo clic sobre el mismo se abre dicha ventana en modo diseño. En la ventana de Paleta, se hace clic en el icono de Ventana. Este será el primer elemento de nuestro proyecto, cuyo nombre inicial, window1, aparecerá reflejado tanto en la ventana Glade como en la de Propiedades. UNIDAD 2 A continuación, se añaden de forma similar otros componentes, como botones, etiquetas y entradas de texto, para conformar una aplicación sencilla de cambio de moneda. Se pueden colocar los distintos objetos en posiciones arbitrarias o estructurar el entorno mediante contenedores de objetos (áreas). Para obtener una visión jerárquica de los contenedores y de los objetos contenidos, es conveniente activar una nueva ventana como la que se muestra a la derecha. Para ello, hay que seleccionar Ver 씰 Mostrar 씰 Árbol de Widget. 70 En la creación de la intefaz se utilizan contenedores de tipo fila (vbox1 y vbox2) y de tipo columna para situar dos etiquetas (label1 y label2) con el título de «Euros» y «Pesetas», respectivamente; dos entradas de texto (entry1 y entry2) asociadas a las etiquetas anteriores, debajo de las mismas; y tres botones, dos de ellos sin título (button1 y button2), pero con iconos de flechas que indiquen el sen- En los contenedores superiores se insertan dos etiquetas (label1 y label2), cuyo título se modifica en la ventana de Propiedades, como puede verse en las figuras siguientes. La distribución de ambas etiquetas se puede cambiar en el contenedor. Una vez dividido el contexto en diversas áreas o contenedores y subcontenedores, se insertan los objetos adecuados estableciendo las propiedades correspondientes a cada uno de ellos. Haciendo clic en el icono de texto de la ventana de Paleta, se insertan las entradas de texto debajo de las etiquetas en los contenedores externos de la siguiente fila. Botones Entre las entradas anteriores deben aparecer los botones con flecha y sin texto (button1 y button2), que indican el sentido de la conversión, por lo que se incluyen en sus correspondientes contenedores, ajustándolos al centro en este caso. El último botón (button3) se coloca en el contenedor reservado para él y se le asigna un título (Salir). OS2TE_LINEX.02 8/5/08 14:00 Página 71 Procedimientos Para que los botones realicen una función, es preciso asignarles un determinado comportamiento o evento asociado. En principio será suficiente con seleccionar en la pestaña Señales de la ventana de propiedades un manejador asociado al evento clicked (es decir, cuando se pulse el botón), dejar el nombre del manejador (función C a la que se invoca) por defecto (on_buttonX_clicked) y repetir el proceso para el resto de los botones. Como se puede observar, el proceso de creación de la interfaz se limita a insertar, agrupar y alterar las propiedades de determinados objetos o componentes disponibles. En el caso de botones y entradas de texto, las propiedades son especialmente importantes, pues por lo general se tiende a conservar el tamaño de dichos objetos de manera proporcional al tamaño de la ventana contenedora. Si ejecutamos de nuevo la aplicación en Anjuta, aún sin volver a Construir, desde el menú Construir 씰 Ejecutar (tecla rápida F3) el resultado de ejecución que obtenemos es el de nuestra nueva interfaz diseñada, aunque todavía carece de funcionalidad, ya que aún no la hemos programado. Si hacemos clic en los botones no obtendremos una salida de error en el terminal, puesto que aún no se han desarrollado las funciones correspondientes. Volviendo a Enjuta, examinamos el código inicial (main.c) para comentar algunos aspectos importantes sobre la programación en C con LibGlade que vamos a emplear: 쮿 En la primera parte del código aparecen unas sentencias de tipo include relativas a las funciones de librerías y tipos de datos que vamos a utilizar, que identificaremos con la primera parte del nombre de la función o variable, como glade_gnome_init, GtkWidget, gdouble, etc. Para las librerías gnome y glade, no es necesario incluir gtk ya que es derivada de gnome y se incluye en cualquier aplicación gnome. #include gnome.h #include glade/glade.h Corresponde al programador informarse sobre las mismas a partir de la documentación que aportan (vease http://develper.gnome.org). int main (int argc, char *argv[ ]) { GtkWidget *window1; GladeXML *xml; Desarrollo del código C de la aplicación Una vez terminado el diseño gráfico del interfaz guardamos el proyecto en Glade y abandonamos esta herramienta para continuar desde Anjuta. Todo el interfaz reside en un único archivo XML que se carga dinámicamente en tiempo de ejecución, en contra del método tradicional de generación de código C a partir del interfaz, ya en desuso pero que mostraremos después como alternativa. 쮿 Todas las aplicaciones Gnome y GTK requieren una inicialización de librerías. La utilización de LibGlade también lo requiere. Se hace en las líneas siguientes: gnome_program_init (PACKAGE, VERSION, argc, argv); glade_gnome_init(); PACKAGE y VERSION están definidas en el archivo config.h, generado por el asistente. Lenguajes de programación 쮿 La función principal del programa (main) se declara como siempre, y se añaden unas declaraciones de datos correspondientes al widget principal de la aplicación window1 y al archivo xml creado en Glade: 71 OS2TE_LINEX.02 8/5/08 14:00 Página 72 Procedimientos 쮿 La llamada a glade_xml_new crea un nuevo objeto de tipo GladeXML que referencia xml, y también crea todos los widgets del archivo de Glade euros.glade. La llamada a glade_xml_signal_autoconnect implica la conexión automática de las señales definidas en Glade, con sus funciones de manejo (handlers) o respuesta (callbacks) en el código C. Recuerda que cuando se creo el interfaz, se asociaron señales “clicked“ con manejadores del tipo on_buttonX_clicked. También puede prescindirse de esta conexión automática y hacerlas de forma individual mediante llamadas a la función g_signal_connect. xml glade_xml_new (PACKAGE_SOURCE_DIR”/euros.glade”, NULL, NULL); glade_xml_signal_autoconnect (xml); 쮿 Los objetos disponibles en el archivo xml, teniendo en cuenta la estructura jerárquica, se disponen mediante llamadas del tipo glade_xml_get_widget, indicando el puntero al archivo y el nombre del objeto para obtenerlos (get), y llamadas gtk_widget_show para mostrarlos (show). En este caso, para window1, la ventana principal es: window1 glade_xml_get_widget (xml, “window1”); gtk_widget_show (window1); 쮿 Finalmente, el programa termina con la llamada a la función gtk_main, que es un bucle «sin fin» que llama a nuestras funciones en base a los eventos que ocurran; por ejemplo, cuando suceden eventos de pulsar botones (señales clicked), se transfiere el control a los manejadores y luego vuelve al bucle infinito. Para salir del bucle, una de las funciones tendría que llamar a la función gtk_main_quit. gtk_main( ); return 0; UNIDAD 2 Generación del código en C del interfaz gráfico 72 Una alternativa a la utilización de Anjuta con LibGlade es la utilización independiente de Glade para generar código C de la interfaz creada que pueda ser modificado posteriormente con un editor. Para ello, una vez diseñada la interfaz, guardamos el proyecto. Glade sugerirá para él un nombre por defecto, proyecto1, y creará para almacenarlo una carpeta, denominada Proyectos, en tu directorio personal. Acepta las opciones por defecto y haz clic en el icono Construir. Con esto habrá concluido la primera parte del proceso, la creación de la interfaz de la aplicación, y se podrá cerrar Glade para continuar ahora desde el terminal. Glade ha generado todo el código en C necesario para ejecutar la aplicación, que únicamente muestra la ventana y una serie de guiones (scripts) para compilar dicha aplicación. Con el fin de comprobar que el procedimiento seguido hasta ahora se ha efectuado correctamente, teclea desde el terminal las órdenes que aparecen en la figura siguiente: Compilación y ejecución de un proyecto Glade. Si todo ha ido bien, en el directorio ~/Proyectos/proyecto1/src/ se hallará el programa ejecutable proyecto1, que aún no tiene un comportamiento definido para su ejecución, exceptuando la visualización de su interfaz. El código de las funciones manejadoras de eventos que se especificaron para los botones de Glade se introduce en este caso en el archivo fuente de proyecto callbacks.c, donde ya aparecen huecos para cada una de las funciones de eventos. Desarrollo del código para funciones de la aplicación Crearemos ahora el código necesario para realizar la conversión de moneda, asociado a los botones de las flechas, mediante las funciones on_button1_clicked y on_button2_clicked para la conversión a pesetas y a euros, respectivamente. El comportamiento del botón restante (Salir) ya fue definido en el diseño del interfaz, dado que es uno de los eventos comunes predefinidos para cualquier aplicación, que hace una invocación a la función gtk_main_quit comentada anteriormente. En la figura siguiente se muestra el código de las dos funciones, que comentamos a continuación. OS2TE_LINEX.02 8/5/08 14:01 Página 73 Procedimientos 쮿 Lo primero que hay que tener en cuenta en este tipo de funciones es el prototipo o definición de las mismas, que es similar en todas las funciones guiadas por eventos: un puntero al objeto, en este caso un botón de tipo GtkButton y otro de tipo gpointer para datos del evento. Si el proceso de compilación ha finalizado con éxito, al ejecutar nuestra aplicación se comprueba su correcto funcionamiento: void on_button1_clicked (GtkButton *button, gpointer user_data) GladeXML *xml glade_get_widget_tree (GTK_WIDGET(button)); GtkWidget* euros glade_xml_get_widget(xml, “entry1”); La aplicación responderá al objetivo inicial (conversión exacta), pero mantendrá el aspecto ya conocido, dado que lo único que se ha manipulado ahora son las funciones asociadas a los eventos de los objetos. Actividades 1 Amplía la aplicación de conversión a euros mostrada en estas páginas para que haga conversiones entre más divisas, seleccionables mediante una lista desplegable. 2 Desarrolla una aplicación en Glade que te salude cuando introduzcas tu nombre, como puedes ver en la figura adjunta. GtkWidget* pesetas glade_xml_get_widget(xml, “entry2”); Nota: se trata de un ejemplo clásico utilizado en diversos tutoriales de Glade que puedes encontrar en Internet. 쮿 Se utilizan un par de variables de tipo númerico (double) para realizar la conversión, y sus equivalentes de tipo cadena para representarlas en el widget de la entrada correspondiente mediante la función gtk_entry_set_text. Las conversiones de tipo cadena a numérico y la inversa se llevan a cabo mediante las funciones g_ascii_strtod y g_strdup_printf, respectivamente. gdouble e g_ascii_strtod(gtk_entry_get_text (GTK_ENTRY(euros)),NULL); gdouble p e * 166.386; gchar* resultado g_strdup_printf(“%.2f”,p); gtk_entry_set_text(GTK_ENTRY(pesetas), resultado); Con ello, lo que se consigue es leer y modificar el contenido de las entradas de texto y, de esta forma, recibir los resultados cuando se pulsen los botones correspondientes. Respecto al botón de salir (función on_button3_clicked), basta con invocar a la función especial gtk_main_quit para abandonar el programa. Finalmente, se guarda el archivo modificado y se vuelve a repetir el proceso de compilación, bien desde el propio entorno Anjuta, con la opción de menú Construir 씰 Construir Todo (o directamente pulsando la tecla F11), o bien desde el terminal, con el comando make en el directorio del proyecto. 3 Realiza los ejemplos de los programas en C que hemos desarrollado al principio de la unidad, creando un entorno gráfico adecuado con Glade para otorgarles un aspecto más agradable y profesional. 4 Desarrolla una aplicación que solicite un número y dé como resultado su tabla de multiplicar. 5 Desarrolla un programa en Glade que, a partir de tu fecha de nacimiento (día, mes, año) y de la fecha actual, te diga cuántos días llevas vivo. 6 Desarrolla una calculadora simple que, a partir de dos cantidades introducidas y de una operación seleccionable de una lista, muestre el resultado del cálculo. Lenguajes de programación 쮿 En las tres primeras líneas de las funciones asociadas a los botones de conversión se obtienen simplemente unos apuntadores, de tipo GtkWidget, para los widgets de entrada de texto entry1 y entry2, mediante una función de librería llamada glade_xml_get_widget que opera sobre el contexto del archivo de Glade para localizar dichos widgets. Dado que estamos en una función distinta a la principal (main) tenemos que obtener un apuntador al árbol de widgets que se utiliza, en este caso a la ventana donde está el botón al que se refiere la función y también las entradas de texto. 73 OS2TE_LINEX.02 8/5/08 14:01 Página 74 Procedimientos Programación de microcontroladores en C Condiciones iniciales Compilación y ensamblado El circuito inicial será muy simple y constará de recursos de visualización de tipo LED, un display de 7 segmentos y una pequeña pantalla LCD. Todos estos elementos se hallarán conectados a un PIC de gama media 16F877. Se compila el programa con el compilador cruzado sdcc desde Anjuta si se ha configurado así, o desde una ventana de terminal con la siguiente orden: usuario@pc:~/Projects/piclinex/src sdcc --debug -mpic14 -p16f877 piclinex.c Nuestro objetivo es triple: 쮿 Hacer que el LED parpadee. 쮿 Conseguir que el display de siete segmentos cuente en sentido ascendente. 쮿 Hacer que la pantalla LCD muestre el mensaje publicitario de LinEx. circuito de reset B7-B1 con pulsador 7 PIC micro B0 1 circuito de reloj display de 7 segmentos LED parpadeante D7-D4 4 de 4 MHz 16F877 C7-C4 4 D3-D2 2 ……… ……… 10 display LCD de dos líneas En primer lugar, es preciso desarrollar el programa en C. Para ello, se usará un editor de texto, o mejor aún, ya que conoces el entorno Anjuta, puedes personalizarlo con las herramientas de desarrollo con PIC. Las primeras líneas del programa en C correspondiente al objetivo propuesto aparecen a continuación (guarda el archivo como piclinex.c en un nuevo directorio de proyecto). Si se listan los archivos que hay ahora en esta carpeta, se observa que se han generado varios, de entre los cuales hay que destacar el piclinex.hex, que es el programa con el que se puede grabar ya directamente el chip, y piclinex.cod, con el que podemos comprobar que la aplicación es correcta mediante la simulación de la misma con la herramienta gpsim. El mismo proceso también se puede hacer por pasos haciendo uso del ensamblador cruzado gpasm a partir del archivo en lenguaje ensamblador piclinex.asm generado por el compilador con las siguientes órdenes: usuario@pc:~/Projects/piclinex/src gpasm -c piclinex.asm usuario@pc:~/Projects/piclinex/src gplink -o piclinex.hex -a inhx8m piclinex.o Simulación Con los archivos obtenidos, principalmente el código máquina correspondiente generado (piclinex.hex), es posible simular cómo ejecutaría el PIC el futuro programa contenido en él y el archivo cod (piclinex.cod) que contiene información simbólica del código fuente para que podamos seguir paso a paso el programa en el simulador, con el siguiente comando: usuario@pc:~/Projects/piclinex/src gpsim -s piclinex.cod UNIDAD 2 Se puede tener una visión bastante fiable del circuito completo si se simulan los recursos y dispositivos conectados al mismo. Para ello, el simulador gpsim dispone de una serie de librerías que permiten simular el comportamiento de varios recursos, como displays LCD y de 7 segmentos, puertas lógicas, etc. 74 Es preciso, por tanto, especificar cuáles serían las conexiones (pines) exactas entre el microcontrolador y los recursos en un archivo con extensión .stc, que relaciona, además, el código .hex. En la página siguiente se observa una parte del código de simulación. OS2TE_LINEX.02 8/5/08 14:01 Página 75 Procedimientos Resultado de la ejecución simulada en el display LCD. Grabación del microcontrolador Para grabar el microcontrolador con el programa que hemos desarrollado, una vez compilado, ensamblado y simulado, es necesario disponer también de una herramienta de grabación/programación que se comunique con una tarjeta de circuito impreso donde se coloca el PIC que se desea grabar. En Linux existe una amplia variedad tanto de tarjetas de grabación como de programas destinados a dichas tarjetas. En el ejemplo que estamos siguiendo, utilizaremos picprog (http://hyvatti.iki.fi/~jaakko/pic/picprog.html), un programa que funciona en modo comando y permite grabar una gran variedad de PIC utilizando programadores serie, los más baratos y sencillos de construir. A continuación, se muestra cuál sería la orden de consola en LinEx para grabar el código máquina generado anteriormente (piclinex.hex): picprog Simulador gpsim Esta herramienta utiliza como parámetros los últimos archivos generados: --erase Ejecución del programa --burn --input piclinex.hex --pic/dev/ttyS1 Grabar Borrar el PIC antes de grabar Puerto serie del grabador Archivo que se va a grabar usuario@pc:~/Projects/piclinex/src gpsim –c piclinex.stc En las ilustraciones se muestra el estado de los pines del chip, la ventana de control del simulador gpsim, la salida del display de siete segmentos y, por último, la salida del display de cristal líquido. Panel de control gpsim. Construir un grabador Puedes construir un simple grabador de PIC con un circuito como el de la figura y conectarlo al puerto serie de tu ordenador. No necesita fuente de alimentación, ya que la toma del PC, y utiliza muy pocos componentes. Puedes encontrar más información sobre este y otros grabadores de PIC en www.gnupic.org. Lenguajes de programación Con la última orden aparecen las ventanas de gpsim que permitirán examinar las memorias y registros del PIC, así como el estado de sus pines, y seguir la ejecución del programa paso a paso, comprobando el funcionamiento «cuasireal» del circuito completo. Módulo de simulación de display de 7 segmentos. 75 OS2TE_LINEX.02 8/5/08 14:01 Página 76 Propuesta de proyectos Realización de un programa para jugar a las tres en raya En la ejecución de este proyecto se empleará el lenguaje de programación en C y sus herramientas asociadas, que has estudiado en la unidad. El programa presentará como interfaz una matriz que represente el tablero con las fichas del juego: unas con el símbolo X y otras con el símbolo O. Condiciones generales de carácter obligatorio 1. El programa representará internamente la matriz del juego de las tres en raya como un array de caracteres de 3 por 3, cuyos posibles valores serán ‘O’, ‘X’, ‘ ‘ (espacio). 2. El programa se realizará de forma modular con al menos dos funciones que se encarguen de facilitar los movimientos de los dos jugadores y de comprobar las posibles combinaciones que indiquen una jugada ganadora. 3. La victoria de un jugador deberá indicarse mediante un texto de diálogo del tipo «Ha ganado el jugador 1». A continuación, el programa solicitará si se desea comenzar una nueva partida o finalizar la sesión. Condiciones generales de carácter voluntario 1. Modificar la aplicación para que permita seleccionar como segundo jugador al ordenador, es decir, competir con una máquina (PC) supuestamente inteligente. Cuando mueve el primer jugador, el símbolo X se coloca en la posición especificada de la matriz. Cuando le toca el turno al ordenador, recorre la matriz y pone O en la primera posición vacía de la matriz. Si no encuentra una posición vacía, lo indica y sale. 2. Incluir una nueva opción en el menú de tipo «Acerca de…», que, a modo de ayuda, proporcione una breve información sobre el objetivo de la aplicación y los datos personales del autor de la misma. 3. Añadir un nuevo menú que permita seleccionar el idioma (español o portugués) de los menús, ventanas de diálogo, etc., del programa. Documentación que hay que presentar 쮿 Manual del usuario del juego, en soporte electrónico, en el que se explique de forma detallada cuáles son las opciones y el manejo del programa. UNIDAD 2 쮿 Manual del programador, en soporte electrónico. Además del listado del código en C más relevante del programa, también se debe explicar de forma breve el significado o sentido de dicho código. 76 OS2TE_LINEX.02 8/5/08 14:01 Página 77 Actividades 1 2 ¿Qué diferencia hay entre utilizar el comando de Logo ADIOS en mayúsculas y emplearlo en minúsculas? ¿Y si hacemos lo mismo con el comando alias del sistema operativo LinEx? Indica cuáles de las siguientes afirmaciones son verdaderas y cuáles falsas. Corrige estas últimas. 7 main () { int x, y, z; x 7; y 8; z x y 5; } 8 Realiza un programa en lenguaje C que calcule la suma, la diferencia, el producto, el cociente y el resto de dos números enteros. Deberá solicitar los dos números por teclado y escribir en pantalla los resultados. 9 쮿 La instrucción REPITE te pide que introduzcas un dato que la máquina no ha entendido. Haz un programa en C que convierta tu edad de años a días (no tengas en cuenta las fracciones de años ni los años bisiestos). 쮿 La ruta, o path, indica el camino para encontrar un fichero. 10 Escribe un programa en C que calcule la longitud y el 쮿 LinEx es un sistema operativo hecho con el lenguaje Basic. 쮿 Logo es un lenguaje de alto nivel fácilmente inteligible. 3 ¿Qué valor toma la variable z en este programa escrito en lenguaje C? Realiza un procedimiento que dibuje un polígono cada vez que se ejecute. En la llamada definiremos el número y la longitud de los lados y el grosor del trazo. área de un círculo de radio 2,5 unidades. 11 ¿Cuáles son los cinco tipos de datos básicos en C? 12 Indica qué es lo que sale por pantalla con la siguiente sentencia printf: printf (“123\b\b\»hola mundo\””); 13 Observa estas instrucciones escritas en C y explica cuál es el error cometido: int x[5]; x[5] 10; 14 ¿Cuál es el resultado de estas expresiones C? a) b) c) d) e) f) g) 5 6 Realiza el siguiente programa con su correspondiente diagrama de flujo: el ordenador elige un número al azar del 0 al 99 y pide al usuario que lo acierte. Si falla, el ordenador indica si el número introducido es menor o mayor que el que él ha elegido y vuelve a pedir un número. Cuando el usuario acierta, recibe un mensaje de felicitación y sale del programa. Realiza un procedimiento que trace la gráfica de la velocidad frente al tiempo en un movimiento rectilíneo uniformemente variado. En la llamada se dará una velocidad inicial y una aceleración. Investiga sobre Logo en Internet y encuentra al menos cinco nuevas instrucciones que funcionen en nuestro intérprete, indicando su utilidad. 15 Señala en qué caso se asigna el valor 4 a b: if (a 3) b 4; 16 ¿Qué ocurre si no hay ninguna sentencia default en una sentencia switch? ¿Puede expresarse toda sentencia for como una sentencia while? 17 La relación entre la temperatura en la escala Celsius y en la escala Fahrenheit viene dada por la siguiente expresión: 5 °C (°F 32) 9 Realiza un programa visual con Glade y C que convierta los grados Fahrenheit en Celsius. Lenguajes de programación 4 2 (1 2 ? 3 : 4) 3 23?44?2:3:1 23?44?2:3:1 23?4:2?3:1 (2 3) ? (4) : (1 ? 3 : 1) (4 2) & (4 1) (4 2) && (4 1) 77