Tema 4: Introducción a la programación Ibiolab.uspceu.com/aotero/recursos/docencia/TEMA 4.pdf ·...
Transcript of Tema 4: Introducción a la programación Ibiolab.uspceu.com/aotero/recursos/docencia/TEMA 4.pdf ·...
Tema 4:
Introducción a la programación I
Objetivos del tema: Una vez visto los fundamentos de un computador y
conociendo cuáles son los pasos a seguir para solucionar un problema del
mundo real mediante un programa, es el momento de comenzar a estudiar un
lenguaje de programación que permita concretar una solución al problema
en software. El lenguaje de programación que hemos elegido para esta
asignatura es C++, si bien inicialmente empezaremos por C, que puede
considerarse una versión limitada del anterior que no soporta la
programación orientada a objetos.
Metodología y tecnología de la programación (I) 2/50
Índice
Índice ...........................................................................................................................................2
1 Breve historia de C ..............................................................................................................5
2 Variables y tipos de datos....................................................................................................6
3 Tipos de datos básicos .........................................................................................................7
3.1 Caracteres ....................................................................................................................7
3.2 Valores lógicos ............................................................................................................9
3.3 Números enteros ........................................................................................................10
3.4 Números reales ..........................................................................................................12
3.5 Rango y precisión de los tipos numéricos de C.........................................................13
3.6 Declaraciones de constantes ......................................................................................14
4 Nuestro primer programa en C ..........................................................................................15
5 Componentes de un programa en C...................................................................................15
5.1 Directivas del preprocesador .....................................................................................17
5.1.1 La directiva #include .........................................................................................17
5.1.2 La directiva #define...........................................................................................19
5.2 Comentarios...............................................................................................................19
5.3 Literales .....................................................................................................................20
5.4 Palabras reservadas....................................................................................................21
Metodología y tecnología de la programación (I) 3/50
5.5 Identificadores ...........................................................................................................21
5.6 Símbolos ....................................................................................................................22
6 Sentencias ..........................................................................................................................26
7 Sentencias de control de flujo............................................................................................27
7.1 Bloque de sentencias .................................................................................................27
7.2 Sentencia condicional simple : if...............................................................................27
7.2.1 Expresiones condicionales.................................................................................29
7.2.2 Sentencias if anidadas........................................................................................30
7.3 Bucles en C................................................................................................................31
7.3.1 Bucle do-while...................................................................................................31
7.3.2 Bucle while ........................................................................................................33
7.3.3 Bucle for ............................................................................................................34
7.3.4 Bucles anidados .................................................................................................36
7.3.5 Sentencias break y continue ..............................................................................37
7.4 Bifurcación múltiple: sentencia switch .....................................................................39
7.5 El operador condicional.............................................................................................41
7.6 Terminación del programa: función exit().................................................................42
8 Ejercicios ...........................................................................................................................44
9 Apéndice I: sistemas binario, octal y hexadecimal............................................................46
9.1 Conversiones entre bases...........................................................................................47
Metodología y tecnología de la programación (I) 4/50
9.2 Conversión Binario - Hexadecimal ..........................................................................47
9.3 Conversión Hexadecimal - Binario ...........................................................................48
9.4 Conversión Binario - Decimal...................................................................................48
9.5 Conversión Decimal - Binario...................................................................................49
9.6 Conversión Decimal - Octal ......................................................................................49
9.7 Conversión Decimal – Hexadecimal .........................................................................49
9.8 Conversión Binario – Octal .......................................................................................50
Metodología y tecnología de la programación (I) 5/50
1 Breve historia de C
A principios de la década de los 70 un pequeño equipo de investigación de los laboratorios
Bell de ATT comenzó a desarrollar un nuevo sistema operativo que, con el tiempo,
acabaría llamándose UNIX. En esta tarea se encontraron con que programar en lenguaje
ensamblador un sistema operativo era excesivamente complicado, además de no permitir
portar el sistema operativo a otros ordenadores. Es por ello que decidieron desarrollar un
nuevo lenguaje de programación que permitiera construir el sistema operativo. Para ello se
inspiraron en otros dos lenguajes de programación en cuyo desarrollo habían participado
varios miembros del proyecto: los lenguajes B y BCPL. El lenguaje resultante se llamó C.
El nuevo lenguaje de programación resultó ser una herramienta muy útil para programar
software de sistemas, por lo que se hizo popular muy rápidamente los laboratorios Bell.
Inicialmente no existía ninguna versión definitiva y estable de lenguaje, hasta que en 1978
se escribió el primer libro de referencia sobre él: The C Programming Languge. El
lenguaje se hizo muy popular y muchas universidades y fabricantes de ordenadores
crearon sus propios compiladores para C. A mediados de la década de los 80 gran parte de
la programación de los computadores del mundo se efectuaba en C. La profusión de
compiladores, en los que cada fabricante añadía sus propias instrucciones y bibliotecas,
llevó a la falta de portabilidad entre los programas. Esto llevó a ANSI (American National
Standards Institute) a crear una versión estándar del lenguaje que se llamó ANSI C.
Desde entonces ha habido varias revisiones del estándar, la más reciente de ellas en 1999.
Esta versión de mantenimiento del estándar, C99, añade nuevas características a ANSI C y
resuelve ciertos problemas que tenía éste. En la actualidad C se encuentra en cierto
declive, por un lado por la aparición de nuevos lenguajes de programación más simples
que, a costa de disminuir la eficiencia del programa, abstraen más al programador de los
detalles de la maquina y le permiten ser más productivo, a la vez que disminuyen la curva
de aprendizaje del lenguaje. Por otro lado, la gran importancia las aplicaciones distribuidas
y orientadas a Internet, para las cuales C no fue diseñado ya que fue creado más de 20 años
antes de la aparición de Internet, hacen que en muchas ocasiones sean preferibles otros
lenguajes de programación.
Metodología y tecnología de la programación (I) 6/50
Sin embargo, sigue habiendo ciertas aplicaciones para las cuales C (o su versión orientada
a objetos, C++) siguen siendo la mejor herramienta: los sistemas operativos, los vídeo
juegos y, en general, las aplicaciones de escritorio están mayormente desarrolladas en C.
Por otro lado, este lenguaje de programación ha influido notablemente en los lenguajes que
más apogeo tienen en la actualidad y que están llamados a ser los dominantes el día de
mañana: Java y C#.
C es un lenguaje de propósito general, esto es, desde él puede abordarse prácticamente
cualquier tipo de problema. Es un lenguaje de bajo-medio nivel, que permite el acceso al
hardware de la computadora de manera que se puede hacer uso eficiente de los recursos
con los que cuenta un equipo. Esto lo hace especialmente adecuado para aquellos
problemas que requieran cálculo intensivo y una gestión cuidadosa del espacio de
almacenamiento. Se ajusta muy bien a los esquemas de diseño jerárquico de arriba a abajo
y, por tanto, a la programación estructurada y a la modular.
2 Variables y tipos de datos
Las variables son identificadores utilizados para almacenar datos. Cada variable se asocia
con una determinada zona dentro de la memoria del ordenador cuyo tamaño dependerá del
tipo de dato que almacene la variable. Todos los datos a nivel de la máquina se representan
en una secuencia de bits; sin embargo C, en particular, y los lenguajes de alto nivel, en
general, permiten basarse en abstracciones que permiten ignorar los detalles de la
representación interna de los datos.
Las variables pueden contener diferentes valores durante los diferentes pasos de la
ejecución de un programa. Todas las variables en C deben definirse antes de su uso. Una
variable se define la siguiente forma:
tipo_de_dato nombre_variable;
esta sentencia define la variable nombre_variable que almacenará un dato del tipo
tipo_de_dato. Es posible definir varias variables del mismo tipo a la vez:
tipo_de_dato nombre_variable1, nombre_variable2,..., nombre_variableN;
Metodología y tecnología de la programación (I) 7/50
Al definir una variable es posible inicializarla, esto es, darle un valor inicial.
tipo_de_dato nombre_variable = valor;
Si intentamos acceder al valor de la variable antes de inicializarla ésta puede contener un
valor cualquiera que podría diferir dependiendo de la plataforma en la que se ejecute el
programa, por lo que siempre debemos darle un valor inicial a las variables antes de
usarlas y no confiar en la inicialización por defecto del compilador. El nombre de una
variable es una forma simbólica de llamar a la dirección de memoria donde comienza el
dato que almacena. Los nombres de las variables deben guardar relación con el objeto que
representa.
En C existen una serie de tipos de datos básicos que es posible componer para crear tipos
de datos más complejos adaptados a las necesidades particulares un programa.
Empezaremos viendo cuáles son los tipos de datos básicos.
3 Tipos de datos básicos
En C hay tres categorías básicas de tipos de datos: caracteres, números enteros y números
reales. Además, muchos lenguajes de programación incluyen como tipo básico de datos
variables lógicas o boolean.
3.1 Caracteres
El tipo de datos char se emplea para almacenar caracteres, o enteros de 8 bits. Los literales
de tipo carácter se representan mediante un único carácter encerrado entre comillas
simples. Así por ejemplo:
char letra = ‘a’;
define una variable de tipo carácter que se llama letra y que contiene el carácter a. Hay
ciertos caracteres especiales (también se les denomina secuencias de escape) cuya
representación textual no coincide con su representación en pantalla (una tabulación, el
carácter de nueva línea, etc.), pudiendo incluso no tener ningún tipo de presentación en
pantalla sino realizando alguna acción (emitir un sonido, avanzar una página, etc.) o
poseyendo un significado especial dentro del lenguaje de programación (el carácter de fin
de cadena). Estos caracteres de escape son:
Metodología y tecnología de la programación (I) 8/50
• '\0' carácter de fin de cadena
• '\a' carácter de alarma
• '\b' retroceso
• '\f' avance de hoja
• '\n' nueva línea
• '\r' retorno que carro
• '\t' tabulador horizontal
• '\v' tabulador vertical
• '\\' diagonal invertida
• '\?' interrogación
• '\'' apóstrofo
• '\"' comillas
• '\ooo' representa el carácter cuya posición de la tabla ASCII se corresponde
con el número octal "ooo".
• '\xhh' representa el carácter cuya posición de la tabla ASCII se corresponde
con el número hexadecimal "hh".
Los caracteres se representan en el ordenador mediante el código ASCII, American
Standard Code for Information Interchange (Código Estadounidense Estándar para el
Intercambio de Información), un código de caracteres basado en el alfabeto latino tal como
se usa en inglés moderno y otras lenguas occidentales. Creado en 1963 por el Comité
Estadounidense de Estándares (ASA) como una evolución de los conjuntos de códigos
utilizados entonces en telegrafía. A continuación mostramos la tabla de caracteres ASCII:
Metodología y tecnología de la programación (I) 9/50
3.2 Valores lógicos
Se emplean para representar valores lógicos, esto es, datos que sólo pueden ser ciertos o
falsos. Su representación depende de la implementación de cada lenguaje; en ocasiones se
emplea TRUE para representar una condición que se satisface y FALSE para una que no se
satisface; otra opción es emplear un 0 para representar una condición que no se satisface y
un 1 (o un valor numérico cualquiera distinto cero) para representar una condición se
satisface.
C tradicionalmente no ha contado con un tipo de dato para representar los valores lógicos.
En C cualquier valor entero que tome un valor diferente de cero se interpreta como un dato
lógico que toma el valor cierto, y cualquier valor entero que tome el valor cero se
interpreta como un dato lógico que toma el valor falso. C99 introdujo un nuevo tipo de
dato, _Bool, para representar valores lógicos. Dado lo reciente de esta especificación,
todavía hay compiladores que no lo soportan. Por otro lado, las librerías estándar de C (y
Metodología y tecnología de la programación (I) 10/50
la gran cantidad de código C que se escribió antes de esta especificación), definidas antes
de esta especificación, emplean enteros para representar valores lógicos. Finalmente, el
empleo de este nuevo tipo de dato rompe la compatibilidad entre C y C++, ya que impide
compilar con un compilador del segundo lenguaje código del primero: para C++ _Bool no
es un tipo de dato, ni una palabra reserva. Por todos estos motivos, en este texto no se
empleará el tipo de dato _Bool en los programas C, sino que se emplearán variables
enteras para representar valores lógicos.
3.3 Números enteros
Los números enteros, como su propio nombre indica, representan datos numéricos que no
tienen parte decimal. Existen varias formas de representar un número entero en código
binario.
• Números enteros sin signo:
o Binario puro: el número entero se representa por su binario correspondiente
25 → 00011001
o Decimal codificado en binario (BCD): se usa un grupo de 4 bits por cada
dígito decimal.
25 → 0010 0101
• Números enteros con signo o Representación en signo-magnitud (SM): el bit que va más a la izquierda
representa el signo (0 si es un número positivo,1 si es un número negativo)
y el resto representan la magnitud.
25 → 0 0011001
-25 → 1 0011001
El rango de valores que se puede presentar es: -2 n-1 +1 ≤ x ≤ 2 n-1 -1.
o Complemento a 1 (C-1): los números positivos se representa n igual que en
SM. En los negativos se cambian los 0s por 1s.
Metodología y tecnología de la programación (I) 11/50
25 → 0 0011001
-25 → 1 11001 10
Rango de representación: -2 n-1 +1 ≤ x ≤ 2 n-1 -1.
o Complemento a (C-2): los números positivos se representan igual que en
SM. En los negativos se cambian los 0s por 1s y se suma 1.
25 → 0 0011001
-25 → 1 1100110 + 1 = 1 1100111
Rango de representación: -2 n-1 ≤ x ≤ 2 n-1-1.
o Exceso a 2 n-1: No hay bit para el signo. Se representa en binario el valor
correspondiente con número + exceso (2 n-1), donde exceso (2 n-1) es el
número entero una unidad superior al mayor número que se puede presentar
con n-1 bits.
25 → 128 + 25 = 153 → 10011001
-25 → 128 - 25 = 103 → 01100111
Rango de representación: -2 n-1 ≤ x ≤ 2 n-1-1.
En C, los tipos de datos enteros pueden ser char, short, int o long que almacenan,
habitualmente, enteros de 8, 16, 32 o 64 bits, respectivamente.
int numero, altura, profundidad; long balance, distancia;
A los tipos char e int se les pueden aplicar los modificadores signed y unsigned para que
sean con signo o sin signo. Los tipos con signo tienen un bit menos de longitud. El tipo
char puede corresponder a signed char o unsigned char dependiendo del compilador.
Metodología y tecnología de la programación (I) 12/50
Los números enteros se pueden representar tanto el formato decimal como octal (para ello
se debe anteponer un 0 al número 0712) y en hexadecimal (se antepone un 0x al número
0xFA81). Para más información acerca de estos sistemas de numeración y las conversiones
entre distintos sistemas consultar el apéndice del capítulo.
Los tipos int y long admiten el modificador long (e int el short) para indicar el número de
bits (mayor o menor rango de valores).
3.4 Números reales
Los números reales se emplean, habitualmente, para presentar números que tienen una
parte decimal; en ocasiones también se le ampara representan números enteros cuyo
tamaño demasiado grande para ser representado por los datos de tipo enteros.
Los números reales se pueden representar como un conjunto dígitos del 0 al 9 más el punto
decimal:
25.32 -48759.4596 -0.41526 ....
O también en notación científica o exponencial: " mantisaEexponente".
Número = mantisa * Base de exponenciación exponente
• Mantisa: número real
• Base de exponenciación (E): base decimal.
• Exponente: exponente correspondiente a un número entero con su signo
2.5E3 → 2.5x103
0.25E-2 → 0.25x10-2
Internamente, los números reales se representan en notación científica; la base es 2, la
mantisa en binario puro (SM, C-1, C-2), y el exponente en exceso a 2 n-1 (ó SM).
En C los números reales de simple precisión (32 bits) se representan como sigue:
• Signo: 1 bit (posiciones 31)
• Exponente: 8 bits (posiciones 23 a 30)
Metodología y tecnología de la programación (I) 13/50
• Mantisa: 23 bits (posiciones 0 a 22)
Y los de doble precisión precisión (64 bits):
• Signo: 1 bit (posiciones 63)
• Exponente: 11 bits (posiciones 52 a 62)
• Mantisa: 52 bits (posiciones 0 a 51)
Los tipos de datos reales son float y double; el segundo almacena números de mayor
tamaño y con una mayor precisión que el primero.
Ejemplos de uso de este tipo de de datos son:
float elevacion = 2.43, x = 4.0;
El tipo double admiten el modificador long para indicar es irse un número mayor de bits
(mayor o menor rango de valores).
3.5 Rango y precisión de los tipos numéricos de C
El número de bits, alcance y precisión de los tipos (tanto enteros como reales) de datos
dependen de cada compilador, aunque suelen ser similares para una misma CPU (I80x86,
SPARC, Alpha, etc.), ya que se adaptan a los que suministra ésta. Debido esta variación
entre distintos compiladores el mejor modo de conocer el rango de valores que pueden
representar cada uno de los tipos de datos es consultar los archivos de cabecera limits.h y
float.h, que, respectivamente, nos indican los valores mínimo y máximo para cada uno de
los tipos de datos enteros y reales. Para que el alumno tenga ciertas referencias del rango la
precisión de los distintos tipos de datos listamos a continuación los valores que típicamente
se emplean actualmente para los tipos de datos más comunes. En primer lugar indicamos el
tamaño en bits del dato y a continuación su rango.
• char: 8 -128 a 127
• unsigned char: 8 0 a 255
• signed char: 8 -128 a 127
• int: 32 -2147483648 a 2147483647
Metodología y tecnología de la programación (I) 14/50
• unsigned int: 32 0 a 4294967295
• signed int: 32 -2147483648 a 2147483647
• short int: 16 -32768 a 32767
• unsigned short int: 16 0 a 65535
• signed short int: 16 -32768 a 32767
• long int: 32 -2147483648 a 2147483647
• signed long int: 32 -2147483648 a 2147483647
• unsigned long int: 32 0 a 4294967295
• long long: 64 –9,223,372,036,854,775,808 a 9,223,372,036,854,775,807
• float: 32 seis dígitos de precisión 3.4 x 10-38 a 3.4 x 1038
• double: 64 diez dígitos de precisión 1.7 x 10-308 a 1.7 x 10308
• long double: 80 17 dígitos de precisión 3.4 E -4932 a 1.1 E +4932
3.6 Declaraciones de constantes
Hemos visto una forma de representar datos cuyo valor no cambia (constantes) en un
programa C: mediante la declarativa define. Esta declarativa hace que el preprocesador
sustituya toda las ocurrencias de un identificador por un determinado valor, siendo por
tanto el valor de la constante un literal en el programa C que es compilado.
También es posible definir una constante empleando una variable cuyo contenido no puede
ser modificado durante la ejecución del programa. Para ello se emplea la palabra reservada
const:
const int i= 8;
tras esta definición cualquier intento de asignar un valor a la variable i provocará un error
en el compilador., así, el siguiente código sería ilegal:
const int i= 8; i=8;
Metodología y tecnología de la programación (I) 15/50
4 Nuestro primer programa en C
Un programa en C es un fichero de texto, normalmente con extensión .c, que contienen las
sentencias del lenguaje. A continuación mostramos un programa muy simple que imprime
en pantalla el texto "¡Hola mundo!":
/* *Nuestro primer programa. *ejemplo4_1.c */ #include <stdio.h> int main(void) { printf("¡Hola mundo!"); }
El texto que está delimitado entre /* */ es un comentario para el programador y, por tanto,
no hace que se ejecute ninguna sentencia. La ejecución del programa comienza por la
primera línea de la función principal, el main. En este caso la única sentencia que tiene la
función principal es un printf, que imprime por pantalla el texto que se le pasa como
argumento.
Para compilar este programa desde la línea de comandos empleando, por ejemplo, con el
compilador gcc emplearemos el comando "gcc ejemplo4_1.c". Como resultado tendremos
un fichero de nombre " a.out" en Linux, o " a.exe" en Windows. Si queremos indicar el
nombre del archivo ejecutable podemos emplear la opción "-o": "gcc -o ejemplo4_1
ejemplo4_1.c".
5 Componentes de un programa en C
Un programa puede contener los siguientes elementos: directivas del preprocesador,
comentarios, palabras reservadas, identificadores, símbolos, y literales. Ejemplo:
/* *ejemplo4_2.c */ #include "stdio.h" int numero; /* este programa es muy simple */
Metodología y tecnología de la programación (I) 16/50
main() { numero=5; if (numero>3) printf("El numero es %d ", numero); }
En este programa:
• #include "stdio.h" : es una directiva del preprocesador.
• /* este programa es muy simple */ : es un comentario.
• int, main, if : son palabras reservadas.
• numero, printf son identificadores.
• ; ( ) > , " { } son símbolos.
• "El numero es %d ", 5 y 3 son literales.
El formato en que se deben describir los distintos componentes de un programa en C es
bastante libre, y se rige por las siguientes reglas:
• No se pueden pegar palabras (no es correcto escribir "intnumero").
• No se pueden partir palabras (no es correcto "ma in").
• Se diferencian las mayúsculas de las minúsculas (numero es distinto de Numero).
• El número de espacios en blanco entre palabras (1 o más) o símbolos (0 o más) no
importa.
• El formato de las líneas es libre, se puede escribir el mismo programa en una sola
línea o en varias, siempre que no dividamos una palabra o un literal en dos partes.
El ejemplo siguiente muestra dos formas equivalentes de escribir una sentencia de
C.
if (numero>3) printf("El numero es %d ", numero);
es lo mismo que
if (numero>3) printf("El numero es %d ", numero);
• Cada sentencia (no cada línea) finaliza con un punto y coma (generalmente).
Metodología y tecnología de la programación (I) 17/50
• Cualquier identificador (variable, constante o función) que usemos en el programa
debe ser definido antes de ser utilizado. El compilador traduce el programa
leyéndolo de arriba a abajo y da un error si encuentra que se utiliza algo que no ha
sido definido previamente.
A continuación veremos más en detalle cada uno de los componentes que pueden aparecer
en un programa C.
5.1 Directivas del preprocesador
El preprocesador de C es un programa que se ejecuta automáticamente con el compilador y
que realiza ciertas modificaciones sobre el código fuente. El compilador actuará sobre el
código fuente modificado. Algunas de estas modificaciones son automáticas, mientras que
otras pueden ser indicadas por el usuario sobre el programa antes de que se compile. Las
modificaciones a realizar se indican por una directiva del preprocesador, que comienza por
el símbolo #. Algunas de las directivas existentes son:
#define #if #line #elif #ifdef #pragma #else #ifndef #undef #error #include
Las directivas #include y #define son las que se utilizan con más frecuencia, por lo que se
describirán a continuación.
5.1.1 La directiva #include
Esta directiva hace que el código fuente contenido en un fichero se lea de disco y se
compile como si estuviese dentro del programa que se está compilando. El formato de esta
directiva es:
# include "fichero"
o
#include <fichero>
Cuando se utilizan los caracteres < >, el preprocesador busca el fichero a incluir en un
directorio o directorios definidos en la instalación del compilador (generalmente, un
directorio llamado INCLUDE). Cuando se utilizan los caracteres " ", se busca el fichero
Metodología y tecnología de la programación (I) 18/50
primero en el directorio actual (desde el que se utiliza el compilador), y después en dichos
directorios.
Esta directiva funciona del siguiente modo. Supongamos que tenemos un fichero de
programa (prueba.c) y un fichero con definiciones adicionales (cosas.h) a incluir en el
mismo. Cuando el preprocesador encuentra el #include "cosas" lo elimina, incluye las
líneas de cosas.h el fichero prueba.c y después compila el fichero modificado. El
preprocesador no modifica realmente el fichero en disco, sino que hace todo el trabajo en
memoria o en una copia temporal del fichero, que borra después de la compilación. Todo
este proceso se realiza de forma automática al compilar el programa, sin requerirse la
intervención del programador. Veamos un ejemplo:
/* *ejemplo4_3.c */ #include "cosas.h" float Area; main() { Area=Pi*radio*radio; printf ("Area: %f", Area); }
el programa a incluir será: cosas.h
float Pi=3.1416; int radio=5;
El programa que genera el preprocesador y que será compilado por el compilador es:
float Pi=3.1416; int radio=5; float Area; main() { Area=Pi*radio*radio; printf ("Area: %f", Area); }
Los archivos que se incluyen suelen ser fragmentos de programa con definiciones de tipos,
variables o funciones, para utilizarlos en el programa principal. Se denominan archivos de
Metodología y tecnología de la programación (I) 19/50
cabecera, header files, de ahí la extensión .h. Además de los que pueda crear el usuario, el
compilador de C dispone de varios archivos de cabecera que es necesario incluir para
utilizar la mayoría de las funciones de las librerías que se suministran con el compilador.
En los manuales del compilador se indica qué fichero .h es necesario incluir para cada
función. En las versiones de C para PC's esta información suele estar disponible en la
ayuda interactiva del compilador. También es posible descargarse archivos cabecera como
librerías creadas por terceras partes.
5.1.2 La directiva #define
Esta directiva sirve, entre otras cosas, para definir constantes simbólicas. Permite asignar a
un identificador un valor determinado que nunca cambiará. Cuando se compile el
programa, el preprocesador substituye cada aparición de dicho identificador por su valor
antes de compilar esa línea. Al igual que en el caso de la directiva #include, el proceso es
transparente al usuario. Veamos cómo funciona con un ejemplo:
/* *ejemplo4_4.c */ #define PI 3.1416 int radio=5; float Area; main() { Area=PI*radio*radio; }
Generalmente las constantes simbólicas se definen con mayúsculas, para diferenciarlas de
los nombres de las variables, que generalmente se escriben con minúsculas.
5.2 Comentarios
Los comentarios en un programa sirven para documentarlo, de forma que sea comprensible
tanto para el que lo ha escrito como para otras personas. Los comentarios en C van entre
los caracteres /* y */. El compilador hace caso omiso del contenido de los comentarios. Un
comentario puede colocarse en cualquier parte del programa, salvo en medio de una
palabra o un literal, y puede ocupar varias líneas.
/* este programa es un ejemplo */ int a,b, /* coeficientes */ err; /* error */
Metodología y tecnología de la programación (I) 20/50
/* comentario de 2 lineas */ main(){ /* comienzan las sentencias */ /* hacer aqui la lectura de datos */ err=a-(a/b)*b; /* bonita formula */ /* esto no lo compilo porque esta incompleto error2= printf(); */ } /* fin de main */
Marcando como comentario una parte del programa se evita que el compilador la procese.
Esto puede ser útil para poder compilar un programa en el que algunas partes del mismo
están incompletas o con errores.
En C99 se ha añadido un nuevo tipo de comentario: "//". Este comentario afecta todo el
texto que se encuentre en la misma línea donde aparecen las dos barras y después de ellas.
A continuación volvemos a presentar el mismo código del ejemplo anterior empleando
este nuevo tipo de comentario en todas las situaciones en las que es posible
// este programa es un ejemplo int a,b, /* coeficientes */ err; // error /* comentario de 2 lineas */ main(){ // comienzan las sentencias // hacer aqui la lectura de datos err=a-(a/b)*b; // bonita formula /* esto no lo compilo porque esta incompleto error2= printf(); */ } // fin de main
5.3 Literales
Son caracteres cuyo valor es literalmente el que aparece escrito en el programa.
Los literales pueden ser numéricos o alfanuméricos. Los números que aparecen en
cualquier programa son literales numéricos. Los literales alfanuméricos son caracteres o
cadenas de caracteres, que pueden contener letras, números y otros símbolos. Los
caracteres individuales se encierran entre comillas simples ('a') y las cadenas de caracteres
entre comillas dobles ("hola"), aunque sean cadenas de un sólo carácter.
Metodología y tecnología de la programación (I) 21/50
Los literales numéricos pueden estar en base 10 (decimal) u otras bases como la base 16
(hexadecimal) o la base 8 (octal). Los números pueden ser enteros o reales. Para los reales
se utiliza el punto decimal (.) y en ningún caso se utiliza la coma (,). Los números reales se
pueden escribir en notación científica, como 1.34E-18.
5.4 Palabras reservadas
Son palabras de C que tienen un uso establecido y no pueden ser utilizadas para ninguna
otra función como, por ejemplo, para ser identificadores. El compilador de C produce un
error si estas palabras se utilizan de forma no permitida. Son palabras reservadas los
nombres de tipos de datos, instrucciones y algunas más:
auto extern sizeof break float static case for struct char goto switch const if typedef continue int union default long unsigned do register void double return volatile else short while enum signed
De estas palabras, 27 existían en la versión original de C y las 5 siguientes fueron añadidas
en el ANSI C 85: const, enum, signed, void y volatile. En C99 se han añadido las palabras
inline, _Bool, _Complex, y _Imaginary. Además, cada compilador puede añadir algunas
palabras reservadas adicionales, lo que puede romper la portabilidad de los programas.
5.5 Identificadores
Son palabras incluidas en el compilador (realmente, incluidas en las librerías que tiene el
compilador) o creadas por el usuario que sirven para dar nombre a variables, funciones y
tipos de datos. Tienen que cumplir las siguientes reglas de formación:
• Su longitud debe estar entre 1 y 32 caracteres.
• Pueden contener letras, números y el símbolo _ (guión bajo). No pueden contener
espacios y se distinguen las mayúsculas de las minúsculas.
• El primer carácter debe ser una letra o _.
Metodología y tecnología de la programación (I) 22/50
A diferencia de las palabras reservadas, cuyo significado no puede ser modificado por el
usuario, los identificadores incluidos en las librerías del compilador pueden ser redefinidos
(es decir, definidos con un nuevo significado), aunque no es conveniente, ya que en este
caso pierden su significado original.
5.6 Símbolos
En C se usan los símbolos siguientes:
• ; para indicar el final de una sentencia.
• {} para indicar el principio y el fin de un bloque de sentencias o de una función.
• () para indicar los argumentos de una función, para encerrar una expresión
lógica en las sentencias de control de flujo y para indicar la precedencia en
expresiones aritméticas.
• /* */ para indicar el principio y el fin de un comentario.
• # para indicar una directiva del preprocesador.
• , para separar varias variables en una declaración, varios parámetros de una
función. También puede separar varias sentencias en una secuencia de sentencias
(algo poco usado).
• . para separar el nombre de una variable unión o estructura del nombre de sus
campos.
• -> para separar el nombre de un puntero del de un campo.
• ? : en la sentencia-expresión condicional.
Además se utilizan los símbolos de operadores aritméticos, relacionales, lógicos y de bits:
Operadores Aritméticos
• = Asignación.
• + Suma.
• - Resta, signo negativo.
• * Multiplicación.
• / División (cociente); aplicado sobre datos enteros en la división de números
enteros (9/4=2).
• % División en módulo (resto).
Metodología y tecnología de la programación (I) 23/50
• ++ Incremento en 1.
• -- Decremento en 1.
Operadores Relacionales
• = = Igual que.
• != Distinto que.
• > Mayor que.
• >= Mayor o igual que.
• < Menor que.
• <= Menor o igual que.
Operadores Lógicos
• && Y.
• || O.
• ! No.
Operadores de bits
• & AND
• | OR.
• ~ NOT (complemento a 1).
• ^ XOR (OR exclusivo).
• >> desplazamiento a la derecha.
• << desplazamiento a la izquierda.
A continuación indicamos la precedencia (de mayor a menor), esto es, el orden de
evaluación, de estos operadores. Ésta nos permitirá saber si al escribir 5+4*2 se ejecuta la
operación (5+4)*2 ó 5+ (4*2). También mostramos su asociatividad, es decir, el orden en
el que se evaluarán los operadores cuando haya varios que tengan la misma precedencia:
• ( ) [ ] . -> a la derecha.
• ! ~ - ++ -- & * sizeof a la izquierda.
• * / % a la derecha.
Metodología y tecnología de la programación (I) 24/50
• + - a la derecha.
• << >> a la derecha.
• < <= > >= a la derecha.
• == != a la derecha.
• & a la derecha.
• ^ a la derecha.
• | a la derecha.
• && a la derecha.
• | | a la derecha.
• ?: a la izquierda.
• = += -= etc. a la izquierda.
• , a la derecha .
La precedencia disminuye de arriba a abajo. La asociatividad normal es a la derecha, por
ejemplo, a+b+c se calcula como (a+b)+c. Habitualmente, para simplificar tanto la escritura
como la lectura del programa y para evitar cometer errores, no se abusa de los órdenes de
precedencia y asociatividad por perfecto de los operadores y se emplean paréntesis (a) para
indicar el orden de las operaciones.
A continuación mostramos un código de ejemplo que muestra cómo funcionan los
operadores de incremento y decremento, así como los operadores que permiten realizar
una operación aritmética sobre una variable y asignar el resultado a esa misma variable:
/* *ejemplo4_5.c */ #include <stdio.h> main () { int entero = 1; float real = 10.0F; printf("entero: %d\n", entero); //imprimirá 1 ya que el entero se muestran antes de incrementarse printf("entero++: %d\n", entero++); //pero después de ejecutar la sentencia entero vale 2 printf("entero: %d\n", entero); //imprimirá 3 ya que se incrementa antes de mostrarse
Metodología y tecnología de la programación (I) 25/50
printf("++entero: %d\n", ++entero); //imprimirá 3 ya que el entero se muestra antes debe incrementarse printf("entero--: %d\n", entero--); //pero tras ejecutar la sentencia entero vale 2 printf("entero: %d\n", entero); //imprimirá 1 ya que se decrementa antes de mostrarse printf("--entero: %d\n", --entero); printf("real: %f\n",real); //equivalente a real = real + 2; real += 2; printf("real += 2: %f\n",real); //equivalente a real = real - 6; real -= 6; printf("real -= 6: %f\n",real); //equivalente a real = real * 3; real *= 3; printf("real *= 3: %f\n",real); //equivalente a real = real / 9; real /= 9; printf("real /= 9: %f\n",real); system ("pause"); }
es continuación presentamos un código de ejemplo que muestra cómo emplear variables
enteras para representar valores lógicos y como los operadores lógicos actúan sobre ellas:
/* *ejemplo4_6.c */ #include <stdio.h> main () { int variableLogica = 0, variableLogica2; variableLogica2 = !variableLogica; printf("variableLogica: %d, variableLogica2: %d\n", variableLogica,variableLogica2); printf("variableLogica&&variableLogica2: %d\n", variableLogica&&variableLogica2); printf("variableLogica||variableLogica2: %d\n", variableLogica||variableLogica2); printf("\n\nTabla de verdad del operador &&:\n"); printf("0 && 0: %d\n",0&&0); printf("0 && 1: %d\n",0&&1); printf("1 && 0: %d\n",1&&0);
Metodología y tecnología de la programación (I) 26/50
printf("1 && 1: %d\n",1&&1); printf("\n\nTabla de verdad del operador ||:\n"); printf("0 || 0: %d\n",0||0); printf("0 || 1: %d\n",0||1); printf("1 || 0: %d\n",1||0); printf("1 || 1: %d\n",1||1); system ("pause"); }
6 Sentencias
Las sentencias de un programa especifican una acción a realizar. Las sentencias en C
suelen finalizar con un punto y coma. Una expresión es una secuencia de operadores y
operandos que especifica un valor. Por ejemplo, la sentencia 4+5; está formada por la
expresión 4+5, que utiliza el operador suma sobre dos operandos constantes enteras y cuyo
valor es 9.
En un programa C hay una parte de declaraciones y otra de instrucciones. En la parte de
declaraciones se pueden utilizar sentencias para:
• Declaración de tipos de datos.
• Declaración de variables.
• Declaración de funciones.
Y en la parte de instrucciones, se utilizan tres tipos principales de sentencias:
• Sentencias de asignación.
• Sentencias de control.
• Llamadas a funciones.
Metodología y tecnología de la programación (I) 27/50
7 Sentencias de control de flujo
Las sentencias que se tratan en este apartado permiten realizar las estructuras de
bifurcación y bucle estudiadas en el tema sobre algoritmos. Permiten, por tanto, construir
programas cuyo flujo de ejecución sea más versátil que la ejecución secuencial.
7.1 Bloque de sentencias
Se denomina bloque de sentencias a un grupo de sentencias cualquiera encerradas entre
llaves { }. Los bloques de sentencias sirven para agrupar varias sentencias bajo el control
de otra (bifurcación, bucle). En cualquier parte del programa donde pueda ir una sentencia,
puede ir también un bloque de sentencias.
7.2 Sentencia condicional simple : if
La sentencia if se utiliza para hacer una bifurcación en el flujo del programa. Puede
aparecer de modo aislado o junto con la sentencia else:
if (condicion) if (condicion) sentencia1; sentencia1; else sentencia2;
En el ejemplo de la izquierda, si la condición es cierta, se ejecuta la sentencia1; si es falsa,
se salta. En cualquier caso, después se ejecutan las sentencias que sigan al if. En el de la
derecha, si la condición es cierta, se ejecuta la sentencia1 y si es falsa, se ejecuta la
sentencia2. Después se ejecutan las sentencias que sigan al if. Obsérvese que o bien se
ejecutan las sentencias de la parte if, o las de la parte else, nunca ambos grupos. Como se
aprecia en el ejemplo de la izquierda, la parte de else es opcional. En caso de ser necesarias
varias sentencias en la parte if o en la else se utilizará un bloque de sentencias, como se
muestra en el siguiente ejemplo:
if (a>0) { printf("a es positivo"); b=a; } else printf("a es negativo");
Metodología y tecnología de la programación (I) 28/50
En el ejemplo anterior, la rama if utiliza un bloque de sentencias, que va desde la llave {
hasta la }. La rama else comienza justo después de dicha palabra y termina en el primer
punto y coma después de ella. Para saber el alcance de una sentencia if o else se sigue la
siguiente regla: si no se utiliza un bloque de sentencias, tanto la rama if como la else
terminan en el primer punto y coma después de dichas palabras. Por tanto, en el ejemplo
siguiente
if (V1>0) V2=2*PI*R*V1/60; printf("Vel lineal: %f\n",V2);
la sentencia printf no está comprendida dentro del if, ya que éste termina en el punto y
coma que sigue al cálculo de V2. Si se coloca una sentencia else después del printf, el
compilador no la reconocerá como parte del if y se producirá un error. Aunque no es
obligatorio, es recomendable emplear siempre las llaves detrás del if y del else; de este
modo se incrementa la legibilidad del código y disminuye la posibilidad de cometer errores
en el futuro cuando, por ejemplo, añadamos más sentencias que estén bajo la acción del if.
A continuación mostramos el diagrama de flujo correspondiente con un condicional tipo if
else:
El formato de espacios o saltos de línea no influyen en la ejecución de la sentencia, sólo se
utilizan para que la estructura del programa resulte más clara al leerlo. Normalmente, las
sentencias que se ejecutan bajo el control de otra se indentan dos espacios hacia la derecha.
Metodología y tecnología de la programación (I) 29/50
Por lo tanto, la sentencia printf del último ejemplo, que no pertenece al if, debería
comenzar dos espacios hacia atrás.
7.2.1 Expresiones condicionales
Se denomina expresión condicional a la que se evalúa como VERDADERO o FALSO.
Generalmente relaciona 2 o más expresiones mediante operadores relacionales y/o lógicos.
Los operadores relacionales se utilizan para comparar expresiones numéricas, como b*b -
4*a*c > 0 o K<=sin(x). Los operadores lógicos se utilizan hacer una expresión
condicional compleja a partir de condiciones más simples, por ejemplo, la condición de la
sentencia if siguiente :
if (aciertos>=11 && sellada==1) printf(" Tengo premio ! ");
En C, cualquier expresión puede ser una expresión condicional. A diferencia de otros
lenguajes, no existe un tipo de datos para valores lógicos ni una sintaxis estricta para
dichas expresiones. Simplemente, cualquier expresión que de un resultado igual a 0 se
considera falsa y si da un resultado distinto de 0, es verdadera. Por ello, es posible ver
programas con sentencias como la siguiente:
if (a-5) x=x+1;
Esta condición es cero (FALSO) cuando a vale 5, y distinto de cero (VERDADERO) en
otro caso. Por ello es equivalente a la condición a!=5. Por claridad, es preferible utilizar la
comparación en lugar de la operación aritmética. En el ejemplo siguiente, las dos
condiciones son equivalentes:
if (opcion!=0) printf("Calculando..."); if (opcion) printf("Calculando...");
aunque la primera es más legible.
Es frecuente confundir el operador de asignación ( = ) con el de comparación ( == ). En las
expresiones lógicas hay que utilizar el de comparación, si no, la sentencia no funcionará
correctamente. Por ejemplo, en la sentencia
Metodología y tecnología de la programación (I) 30/50
if (a=5) printf("Hola")
se asigna el valor 5 a la variable "a", perdiéndose el que tuviese antes. El valor de esta
expresión es 5, por lo tanto su valor lógico es CIERTO y siempre se ejecutará el printf.
7.2.2 Sentencias if anidadas
Se dice que una sentencia if está anidada si se ejecuta dentro de una de las ramas de otra
sentencia if. El programa siguiente muestra un grupo de sentencias if anidadas para
traducir una nota numérica a un mensaje.
/* *ejemplo4_7.c */ #include <stdio.h> float Nota; main() { printf("\nDame la nota numerica : "); scanf("%f",&Nota); if (Nota<5) { printf("\nSuspenso\n"); } else { if (Nota<7) { printf("\nAprobado\n"); } else if (Nota<8.5) { printf("\nNotable\n"); } else if (Nota<9.5) { printf("\nSobresaliente\n"); } else { printf("\nMatricula de Honor\n"); } } system("pause"); }
Si se quisiera añadir dos mensajes, uno de “Por los pelos...” para los aprobados con nota
menor de 5.5 y uno de “Que fiera..” para los alumnos con sobresaliente o matricula, habría
que dejar el programa así:
/* *ejemplo4_8.c */ #include <stdio.h> float Nota; main()
Metodología y tecnología de la programación (I) 31/50
{ printf("\nDame la nota numerica : "); scanf("%f",&Nota); if (Nota<5) { printf("\nSuspenso\n"); } else { if (Nota<7) { printf("\nAprobado\n"); if (Nota<5.5){ printf("Por los pelos...\n"); } } else if (Nota<8.5) { printf("\nNotable\n"); } else if (Nota<9.5) { printf("\nSobresaliente\n"); } else { printf("\nMatricula de Honor\n"); printf("Que fiera...\n"); } } system("pause"); }
7.3 Bucles en C
Un bucle está formado por un conjunto de sentencias que se repiten bajo el control de una
condición. A diferencia de otros lenguajes como BASIC o PASCAL, donde las sentencias
del bucle se repiten hasta que una condición es cierta, en C se repiten mientras la condición
es cierta. Por lo tanto, hay que buscar una condición adecuada para que el bucle se
comporte como deseamos. Los bucles pueden llevar la condición al principio o al final.
Los bucles con la condición al final se realizan con la sentencia do - while y los que llevan
la condición al principio con las sentencias while y for.
7.3.1 Bucle do-while
La forma general de un bucle do-while es:
do sentencia; while (condicion);
Metodología y tecnología de la programación (I) 32/50
En caso de querer incluir más de una sentencia, se utiliza un bloque de sentencias. El
principio del bucle es la sentencia do y el final la sentencia while. Las sentencias entre
ambas son el cuerpo del bucle. La ejecución de este bucle es como sigue: se ejecutan las
sentencias que siguen al do, hasta el while. Se comprueba la condición. Si es cierta, se
vuelve a la primera sentencia del bucle. Si es falsa, se sale del bucle y se ejecuta la
sentencia que sigue al while. Como la condición se comprueba al final, el bucle siempre se
ejecuta al menos 1 vez. Veamos un ejemplo:
/* *ejemplo4_9.c */ #include <stdio.h> #include <stdlib.h> #include <time.h> main() { intr; srand(time(NULL)); do { r =rand(); printf("%g\n",r); } while(r <RAND_MAX- RAND_MAX/100); }
El bucle anterior se repite mientras el número aleatorio deseado sea menor que
RAND_MAX- RAND_MAX/100. A continuación presentamos el diagrama de flujo
correspondiente a este programa:
Metodología y tecnología de la programación (I) 33/50
7.3.2 Bucle while
Es similar al anterior, pero con la condición al principio. En este caso, se prueba la
condición antes de ejecutar la primera vez el bucle. Si la condición es falsa inicialmente, el
bucle no se ejecuta ninguna vez.
while (condicion) sentencia;
Nuevamente, en caso de requerir más de una sentencia, se utiliza un bloque de sentencias.
Mostramos el código del ejemplo anterior rehecho con este nuevo tipo de bucle:
/* *ejemplo4_10.c */ #include <stdio.h> #include <stdlib.h> #include <time.h> main() { srand(time(NULL)); int r=0; while(r <RAND_MAX- RAND_MAX/100) { r =rand(); printf("%g\n",r); } }
Metodología y tecnología de la programación (I) 34/50
Su diagrama de flujo correspondiente será:
7.3.3 Bucle for
Es un bucle con la condición al principio, como el while, pero que además permite incluir
una sentencia de inicialización del bucle y otra de actualización del mismo. Estos tres
elementos se separan por un punto y coma.
for (expresion_inicio ; condicion ; expresion_actualizacion) { sentencia; }
Todo bucle for es equivalente a un bucle while con la expresión inicial antes del bucle y la
expresión de actualización al final del mismo.
expresion_inicio; while (condicion) { sentencia; expresion_actualizacion; }
La expresión de inicialización se ejecuta una sola vez al comenzar el bucle. La expresión
de actualización se ejecuta cada vez que se llega al final del bucle, antes de comprobar la
Metodología y tecnología de la programación (I) 35/50
condición. Debido a esta característica, el bucle for se utiliza con frecuencia para bucles
con contadores fijos como, por ejemplo, este bucle for para sumar los cuadrados de los
números de 1 a 10 y bucle while equivalente:
for (i=1 ; i<11 ; i=i+1) { cuadrado=i*i; suma=suma+cuadrado; }
i=1; while(i<11) { cuadrado=i*i; suma=suma+cuadrado; i=i+1; }
La utilización de for en lugar de while se hace sólo por claridad, al estar agrupadas las
sentencias de control del bucle en una misma línea. A continuación mostramos el diagrama
de flujo correspondiente con este bucle:
Metodología y tecnología de la programación (I) 36/50
En un bucle for puede omitirse cualquiera de las dos sentencias, o la condición, o todas
ellas; por ejemplo, es válido el siguiente bucle:
for ( ; ; ) { sentencia1; sentencia2; }
En este caso, el bucle no termina nunca, salvo que una sentencia interna break o exit (que
veremos más tarde en este tema) lo haga terminar. Si se desea que en un bucle se inicialice
o actualice más de una variable se utiliza la secuencia de expresiones. Consiste en separar
las diferentes sentencias por una coma ( , ), como en el ejemplo siguiente:
for (i=0,j=1,s=0,a=0 ; i<10 ; i=i+1,j=j+i*2) { s=s+i; a=a+j; }
A continuación mostramos un programa que imprime los 127 primeros caracteres ASCII
junto con su valor entero equivalente:
/* *ejemplo4_11.c */ #include <stdio.h> #include <stdlib.h> main() { char c; for( c = 0; c < 127; c++){ printf("E valor: %i se corresponde con el carácter %c\n",(int)c,c); } }
7.3.4 Bucles anidados
Se dice que un bucle está anidado cuando está dentro de otro bucle más amplio. En esta
estructura, el bucle interno se ejecuta completamente (todas las repeticiones) para cada
paso del bucle externo. Este tipo de construcciones son muy empleadas para procesar
matrices, y para otros programas, como el siguiente, que escribe en pantalla una tabla de
potencias:
Metodología y tecnología de la programación (I) 37/50
/* *ejemplo4_12.c */ #include <stdio.h> #include "math.h" #define MAXBASE 15 #define MAXEXP 7 int base,exponente; main() { /* cabecera de la tabla, con los exponentes y una raya */ printf("\n\n\n "); for (exponente=1;exponente<=MAXEXP;exponente++) printf("%10i",exponente); printf("\n-------------------------------------------" "-------------------------------\n"); /* bucles anidados */ for (base=1;base<=MAXBASE;base++) { printf("%2d %c",base,179); /* base y palito (ASCII 179) */ for (exponente=1;exponente<=MAXEXP;exponente++) printf("%10li",(long) pow(base,exponente)); printf("\n"); } }
El bucle externo hace variar la base. Para cada base (cada paso del bucle externo), el bucle
interno hace variar el exponente de forma que tome todos sus valores. Esto se repite para
todos los valores de la base. La función pow(x,y) calcula x elevado a y; está definida en
math.h. Al imprimir el resultado, se convierte de double, que es el que devuelve la función,
a long, mediante el uso de un molde o cast.
7.3.5 Sentencias break y continue
A veces resulta necesario abandonar un bucle por alguna condición que se verifica cuando
se está dentro del bloque de código, sin esperar a evaluar la condición del bucle. Para salir
de un bucle puede utilizarse la sentencia break, en combinación con un if, como en el
siguiente ejemplo:
/* *ejemplo4_13.c */ #include <stdio.h> #include <stdlib.h> #include <time.h> int secreto,numero; main() { srand(time(NULL));
Metodología y tecnología de la programación (I) 38/50
secreto=rand()% 10; printf("\nAdivina el Numero secreto." " Para salir da el numero 0\n\n"); do { printf("\nDame un numero del 1 al 10 : "); scanf("%d",&numero); if (numero==0) break; /* == corta el bucle == */ if (numero!=secreto) { printf("Ese no es el numero secreto."); if (secreto>numero) printf("El numero secreto es mayor.\n"); else printf("El numero secreto es menor.\n"); } else printf(" Has acertado ! \n"); } while (numero!=secreto); }
La sentencia continue se utiliza dentro de un bucle para iniciar una nueva iteración del
mismo, saltándose las sentencias que la siguen. Es equivalente a un salto al final del bucle,
por tanto, si es un bucle for, se ejecuta la sentencia de actualización (aunque está colocada
al principio, se ejecuta al final del bucle) y si es un bucle do while se comprueba la
condición.
El siguiente programa salta los números impares, con una sentencia continue, y
descompone los pares hasta saber si son potencias de 2 o no:
/* *ejemplo4_14.c */ #include <stdio.h> Unsigned int num,pot; main() { for (num=1;num<64000;num++) { if (num%2!=0) continue; /* == siguiente iteracion == */ pot=num; printf("\n\n %u ",pot); while (pot%2==0) { pot=pot/2; printf("%u ",pot); } if (pot==1) printf("\n %u es potencia de 2\n",num); else printf("\n %u no es potencia de 2\n",num); } }
Metodología y tecnología de la programación (I) 39/50
7.4 Bifurcación múltiple: sentencia switch
La bifurcación múltiple permite que un programa tome distintas acciones según el valor de
una expresión de tipo int o char. Se realiza mediante la sentencia switch, que tiene la
siguiente sintaxis:
switch(selector) { case valor1 : Grupo de sentencias1; break; case valor2 : Grupo de sentencias2; break; case valor3 : Grupo de sentencias3; break; case valor4 : Grupo de sentencias4; break; case valor5 : Grupo de sentencias5; break; // ... default: statement; }
Dentro de los paréntesis del switch se coloca la expresión. Para cada valor para el cual se
desea ejecutar un conjunto diferente de sentencias se pone una sentencia case seguida de
dicho valor (en forma de constante, no sirve una variable). Cuando se ejecuta la sentencia
switch, se compara el valor de la expresión con cada constante por orden, y si coincide con
una, se ejecutan las sentencias que siguen al case. Una vez que se verifica una sentencia
case, se ejecutan las sentencias asociadas y las de todos los case que haya a
continuación.
Para cortar la ejecución de las sentencias y salir del switch, puede ponerse donde resulte
oportuno una sentencia break, esto es, un salto incondicional fuera del switch (la sentencia
break será explicada en detalle más adelante en este tema). Si para varios valores de la
expresión deben ejecutarse las mismas sentencias, pueden ponerse los case seguidos, con
las sentencias en el último de ellos. La etiqueta default es opcional y, si se llega a ella (si
no se sale con un break), siempre se ejecuta sea cual sea el valor de la expresión. A
continuación mostramos el diagrama de control de flujo correspondiente con un switch:
Metodología y tecnología de la programación (I) 40/50
Veamos un ejemplo de uso de esta estructura de control de flujo:
/* *ejemplo4_15.c */ #include <stdio.h> int mes, dias; main() { printf("\n\nDame el numero del mes : "); scanf("%d",&mes); switch(mes) { case 2 : dias=28; break; case 4 : case 6 : case 9 : case 11 : dias=30; break; default : dias=31; } printf("El mes %d tiene %d dias\n",mes,dias); }
Cuando el mes es 2, días toma el valor 28 y con el break se sale del switch. Si es 4, 6, 9 o
11, toma el valor 30 y se sale. Cualquier otro valor hace que tome el valor 31. Veamos a
continuación otro ejemplo; en esta ocasión se generan caracteres aleatorios y el programa
determina si los caracteres generados son consonantes o vocales:
Metodología y tecnología de la programación (I) 41/50
/* *ejemplo4_15.c */ #include <stdio.h> #include <time.h> int mes, dias; main() { int i = 0; srand(time(NULL)); for(i = 0; i < 100; i++) { char c = (char)(rand()%26 + 'a'); printf("%c: ",c); switch(c) { case 'a': case 'e': case 'i': case 'o': case 'u': printf("vocal\n"); break; default: printf("consonante\n"); } } }
7.5 El operador condicional
Aunque estrictamente hablando no es una sentencia de control de flujo sino un operador, el
operador condicional permite elegir de entre dos expresiones cuál de ellas se ejecuta y
devuelve el resultado de la ejecución de dicha sentencia. Este operador es muy similar a un
if-else. Veamos su sintaxis:
expresión1 ? expresión2 : expresión3;
esta sentencia es análoga a:
if( expresión1 ) expresión2; else expresión3;
Veamos un ejemplo donde se emplea el operador condicional para imprimir el mayor y el
menor de dos números perdidos al usuario:
/*
Metodología y tecnología de la programación (I) 42/50
*ejemplo4_17.c */ #include <stdio.h> int main(void) { int n1, n2, mayor, menor; printf("Primer número: "); scanf("%d", &n1); printf("Segundo número: "); scanf("%d", &n2); mayor = (n1 > n2) ? n1 : n2; menor = (n1 < n2) ? n1 : n2; printf("El mayor es %d\n", mayor); printf("El menor es %d\n", menor); }
Si las expresiones 2 y 3 del operador condicional son compuestas, cada proposición debe
estar separada por coma ','. Por ejemplo:
(radio > 4) ? printf("\n Funciona\n"), printf("A ver??\n") : printf("\n Es más pequeño");
El empleo de un operador condicional es más compacto que el empleo de la estructura if-
else; sin embargo la segunda resulta mucho más legible que la primera, por lo que se
recomienda no emplear el operador condicional.
7.6 Terminación del programa: función exit()
El objetivo de este apartado no es ni un operador ni una estructura de control de flujo, sino
una función que influye sobre el flujo de ejecución del programa. Esta función puede
utilizarse en cualquier punto de un programa para terminar su ejecución. Su sintaxis es:
exit(N);
donde N es un entero cualquiera. El valor de N se devuelve al Sistema Operativo como
código de retorno del programa; no tiene importancia para el programa en sí. Este valor
puede utilizarse desde el S.O.; por ejemplo, en MS-DOS puede averiguarse con la
Metodología y tecnología de la programación (I) 43/50
instrucción ERRORLEVEL y utilizarse en un fichero .BAT. La función exit() está definida
en stdlib.h y en process.h. Veamos un ejemplo:
/* *ejemplo4_18.c */ #include <stdio.h> #include <stdlib.h> unsigned char caracter; main(){ printf("\n\nTeclea caracteres, pulsa q para salir.\n\n"); while (1) { caracter=getchar(); printf(" ASCII %d \n",caracter); if (caracter==113) exit(0); } }
El bucle while del programa es infinito; para salir de él (y terminar el programa) se emplea
la función exit().
Metodología y tecnología de la programación (I) 44/50
8 Ejercicios
1. Escribir un programa que defina una variable en la que se almacene un número de
meses determinado, otra en la que se almacene un número de días, y otra la que se
almacene un número de horas. Darle un valor inicial cualquiera a estas variables y
a continuación calcular cuántos segundos son los meses, días y horas almacenados
en esas variables.
2. Escribir un programa que defina variables que representen el número de días de un
año, el número de horas que tiene un día, el número de minutos que tiene una hora
y el número de segundos que tiene un minuto. Emplear las variables que ocupen el
mínimo espacio de memoria posible. A continuación, calcular el número de
segundos que tiene un año y almacenar el valor del cálculo en otra variable.
3. Escribir un programa que almacene los coeficientes de una función de segundo
grado (ax2+bx+c) en variables reales. Inicializar con cualquier valor dichas
variables y a continuación calcular el valor de la función definida en los puntos x=
42.32 y x=27.35.
4. Modificar el programa anterior de tal modo que sólo se imprima la parte entera del
valor de la función en los mismos puntos que en el apartado anterior.
5. Escribir un programa que defina tres variables de tipo carácter contengan,
respectivamente, los caracteres J,n,8 y ?. Almacenar en una variable el valor de la
suma de las cuatro variables tipo carácter y comprobar mediante la tabla que se
proporciona en este tema el resultado de dicha suma.
6. Calcular el factorial de un número introducido por teclado. Antes de realizar el
cálculo deberá comprobarse que el número es positivo y en caso contrario se
imprimirá un mensaje de error.
7. Escribe un programa que calcule el mínimo y el máximo de una lista de números
enteros positivos introducidos por usuario. La lista finalizará cuando se introduzca
un número negativo.
8. Escribe un programa que lea un mes en número (1 para enero, 2 para febrero, etc.)
y un año e indique el número de días de ese mes. Recuerda, el año es bisiesto si es
divisible por cuatro, excepto cuando es divisible por 100, a no ser que sea divisible
por 400.
Metodología y tecnología de la programación (I) 45/50
9. Escribe un programa que lea un número entero de teclado y lo descomponga en
factores primos; por ejemplo 40 = 2 * 2 * 2 * 5.
10. Escribe un programa que muestre por pantalla la lista de los 100 primeros números
primos.
11. Escribe un programa que lea un número entero y que devuelva su correspondiente
representación binaria usando la técnica de divisiones sucesivas.
12. Escribe un programa que realice las operaciones de suma, resta, multiplicación y
división. El programa deberá mostrar siguiente menú:
Programa calculadora
1) Realizar una suma
2) Realizar una resta
3) Realizar una multiplicación
4) Realizar una división
5) Salir del programa
Introduzca su opción:
Ayuda para los ejercicios:
int main(){ int i; float k; printf ("Imprime el valor entero de la variable i: %d",i); printf ("Imprime el valor entero de la variable i: %f",k); //leemos un dato entero de la consola y lo almacenamos en la //variable i scanf ("%d",&i); //leemos un dato real de la consola y lo almacenamos en la //variable k scanf ("%f",&k); }
Metodología y tecnología de la programación (I) 46/50
9 Apéndice I: sistemas binario, octal y hexadecimal
Los sistemas de numeración son conjuntos de símbolos y reglas empleados para
representar información numérica. Se denomina sistemas posicionales a aquellos sistemas
de numeración en los que el valor de un símbolo depende de su valor absoluto y de su
posición relativa a la coma decimal.
El teorema fundamental de la numeración nos dice que: “En un sistema posicional
cualquier número puede expresarse mediante su polinomio equivalente”
NúmeroB = xixi-1... x2 x1x0 = xi*Bi + xi-1*Bi-1 +...+ x2*B2 + x1*B1 + x0*B0
donde:
• B es la base
• xi son los coeficientes, siendo todos ellos mayores o igual que cero y menores o
igual que la base.
• i es el índice
Existen básicamente 3 tipos de sistemas de numeración, a parte del sistema decimal que
todos conocemos y estamos acostumbrados a usar:
• Sistema Binario. Se compone de 2 dígitos: 0 y 1. Los primeros números de este
sistema son 0,1,10,11,100,101,110,...
• Sistema Octal. Se compone de 8 dígitos: 0,1,2,3,4,5,6,7. Los primeros números de
este sistema son: 0,1,2,3,4,5,6,7, 10, 11,..., 17, 20,...
• Sistema Hexadecimal. Se compone de 15 dígitos: 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F.
los primeros números de este sistema son: 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F, 10,
11...,1A,1B,...,1F, 20,...
Metodología y tecnología de la programación (I) 47/50
9.1 Conversiones entre bases
Para convertir un número de base B a base decimal basta con convertir el número inicial
en su polinomio equivalente y realizar el cálculo correspondiente operando en decimal.
Para convertir un número de base B a base B’ (siendo B’ distinto de B10) se suele emplear
B10 como intermediario: primero se pasa el NúmeroB a Número10 y a continuación se pasa
de Número10 a NúmeroB’. Para ello se divide sucesivamente el número decimal entre la
nueva base; la representación del número en la nueva base será el conjunto de los restos
obtenidos en las divisiones tomados en orden inverso.
Para convertir entre dos bases B y B’ tales que B’ es potencia exacta de B no es necesario
utilizar B10 como intermediario. Para realizar la conversión basta con agrupar los dígitos
del número en base B de n en n, siendo n tal que Bn= B’ y a continuación sustituir cada
grupo de dígitos por el dígito correspondiente en base B’. Para convertir de B’ a B
simplemente cambiamos cada digito de la primera base por el número correspondiente en
la segunda base (B) representado éste último con n dígitos.
9.2 Conversión Binario - Hexadecimal
Cuando se tiene un número en binario y se desea
pasarlo al sistema hexadecimal se forman parejas
de 4 en 4 empezando de derecha a izquierda. A
continuación sustituimos cada grupo de cuatro 1s y
0s por su número se ha decimal correspondiente.
Por ejemplo, para pasar el número 111011101 a
hexadecimal:
1 , 1 1 0 1 , 1 1 0 1 = 1 D D
En la tabla mostramos el número binario
correspondiente con cada uno de los 16 dígitos del
código hexadecimal.
Metodología y tecnología de la programación (I) 48/50
9.3 Conversión Hexadecimal - Binario
Para transformar un número hexadecimal a binario simplemente cogemos cada dígito del
número hexadecimal y los sustituimos por un conjunto de cuatro unos y ceros que
representen el dígito en binario. Así, por ejemplo, para pasar el número F87 a binario
simplemente tenemos en cuenta que F= 1111, 8= 1000 y 7= 0111 y por tanto F87= 1111,
1000, 0111.
9.4 Conversión Binario - Decimal
Cuando se tiene un número en binario y se desea pasarlo al sistema decimal se toma cada
uno de los dígitos empezando por la última posición hasta la primera y multiplicamos cada
dígito por la respectiva posición de la potencia de 2. Por ejemplo, para pasar el número
111011101 a decimal
1 1 1 0 1 1 1 0 1
2^0 x 1 = 1 x 1 = 1
2^1 x 0 = 2 x 0 = 0
2^2 x 1 = 4 x 1 = 4
2^3 x 1 = 8 x 1 = 8
2^4 x 1 = 16 x 1 = 16
2^5 x 0 = 32 x 1 = 0
2^6 x 1 = 64 x 1 = 64
2^7x 1 = 128 x 1 = 128
2^8 x 1 = 256 x 1 = 256
Y sumando obtenemos 477
Metodología y tecnología de la programación (I) 49/50
9.5 Conversión Decimal - Binario
Para transformar un número decimal al sistema binario, se realizan divisiones enteras
sucesivas entre 2, hasta que el resultado sea cero. El número binario correspondiente es el
conjunto de todos los restos de la división tomados en orden inverso. Por ejemplo, para
pasar a binario él número 67:
33 16 8 4 2 1 0
2 | 67 2 | 33 2 | 16 2 | 8 2 | 4 2 | 2 2| 1
1 1 0 0 0 0 1
Por tanto, 67 =1000011.
9.6 Conversión Decimal - Octal
Para transformar un número decimal al sistema octal, se realizan divisiones enteras
sucesivas entre 8, hasta que el resultado sea cero. El número es tal correspondiente se
obtiene tomando todos los restos de la división tomados en orden inverso. Por ejemplo,
para pasar a octal el número 63:
7 0
8 | 63 8 | 7
7 7
Entonces 63 10 =77.
9.7 Conversión Decimal – Hexadecimal
Para transformar un número decimal al sistema hexadecimal, se realizan divisiones enteras
sucesivas entre 16 hasta que el resultado sea cero. A continuación se sustituye cada uno de
los restos por el número se ha decimal correspondiente y se toman en orden inverso. Por
ejemplo pasar a hexadecimal el número 1000:
62 3 0
Metodología y tecnología de la programación (I) 50/50
16 | 1000 16 | 62 16 | 3
8 14=E 3
por tanto, 1000 = 3E8.
9.8 Conversión Binario – Octal
Cuando se tiene un número en binario y se desea pasarlo al sistema octal se forman parejas
de 3 en 3 empezando de derecha a izquierda y a continuación se sustituye cada grupo de 1
y 0s por su respectivo número tal. Por ejemplo, para pasar el número 111011101
1 1 1 , 0 1 1 , 1 0 12 =7 3 5 8