Está en la página 1de 75

CURSO DE LENGUAJE C

http://www.carlospes.com/curso_de_lenguaje_c/01_03_01_tipos_de_instrucciones_lenguaje_c.
php

1. Introducción (Primera entrega)


1.1 Introducción
1.2 Fases de la puesta a punto de un programa
1.3 Estructura de un programa
1.3.1 Tipos de instrucciones en lenguaje C
1.3.2 Mi primer programa en lenguaje C

1.4 Tipos de datos


1.4.1 Datos de tipo entero (int)
1.4.2 Datos de tipo real (float o double)
1.4.3 Datos de tipo carácter (char)
1.4.4 Datos sin valor (void)
1.4.5 Datos de tipo lógico
1.4.6 Datos de tipo cadena

1.5 Identificadores
1.5.1 Ejemplos de identificadores válidos y no válidos
1.5.2 Palabras reservadas

1.6 Variables
1.6.1 Ejemplos de declaración de variables

1.7 Constantes
1.7.1 Constantes de tipo entero
1.7.2 Constantes de tipo real
1.7.3 Constantes de tipo carácter
1.7.4 Constantes de tipo cadena

1.8 Operadores y expresiones


1.8.1 Expresiones aritméticas
1.8.1.1 El operador división
1.8.1.2 Conversión de tipo (casting)
1.8.1.3 La función pow

1.8.2 Expresiones lógicas


1.8.2.1 Operadores relacionales
1.8.2.2 Operadores lógicos

1.8.3 La función strcat


1.8.4 Operadores de asignación
1.8.5 La función strcpy
1.8.6 Los operadores incremento (++) y decremento (--)
1.8.7 Prioridad de operadores

1.9 Entrada y salida estándar


1.9.1 La función printf
1.9.1.1 Texto ordinario
1.9.1.2 Especificadores de formato
1.9.1.3 Secuencias de escape

1.9.2 La función scanf


1.9.2.1 Especificadores de formato
Ejercicios de entrada y salida estándar (scanf y printf)

1.10 Comentarios
1.11 La función fflush
1.12 Tipos de errores
1.12.1 Errores de sintaxis
1.12.2 Errores de ejecución
1.12.3 Errores de lógica

2. Instrucciones de control alternativas (Segunda entrega)


2.1 Alternativa doble ( la instrucción if )
Ejercicios de la instrucción alternativa doble (if else) en lenguaje C

2.2 Alternativa simple ( de nuevo la instrución if )


Ejercicios de la instrucción alternativa simple (if) en lenguaje C

2.3 Alternativa múltiple ( la instrucción switch )


Ejercicios de la instrucción alternativa múltiple (switch) en lenguaje C

2.4 Anidamiento
2.4.1 Alternativa doble en doble
2.4.2 Alternativa múltiple en doble
Ejercicios de anidamiento de instrucciones alternativas en lenguaje C

3. Instrucciones de control repetitivas (Tercera entrega)


3.1 Repetitiva mientras ( la instrucción while )
Ejercicios de la instrucción repetitiva mientras (while) en lenguaje C

3.2 Repetitiva hacer...mientras ( la instrucción do..while )


Ejercicios de la instrucción repetitiva hacer...mientras (do...while) en lenguaje C

3.3 Repetitiva para ( la instrucción for )


3.3.1 ¿Cuándo usar un bucle u otro?
Ejercicios de la instrucción repetitiva para (for) en lenguaje C

3.4 Anidamiento
3.4.1 Bucle for en do...while
3.4.2 Alternativa simple en bucle for
Ejercicios de anidamiento de instrucciones alternativas y repetitivas en lenguaje C

4. Instrucciones de control de salto (Cuarta entrega)


4.1 Instrucción break
4.2 Instrucción continue
4.3 Instrucción goto
4.4 Instrucción return
4.5 Ventajas de no usar las instrucciones de salto

5. Llamadas a subprogramas (Próxima entrega) Mantente informado en mi Blog.


1 Introducción

¡Bienvenido al Curso de lenguaje C de Carlos Pes!


Todos los contenidos de este curso han sido extraídos de los libros:

 EMPEZAR DE CERO A PROGRAMAR EN LENGUAJE C


 DOMINE LA PROGRAMACIÓN EN LENGUAJE C

y puede ser útil a todos aquellos que quieran iniciarse en la programación utilizando lenguaje C.
Aunque no es imprescindible, al lector le resultará más fácil seguir las explicaciones si ya posee
conocimientos previos de programación en otro/s lenguaje/s y, en especial, es aconsejable que
ya sepa diseñar algoritmos (véase el Curso de Diseño de Algoritmos). En cualquier caso, para
facilitar la comprensión del texto, se han añadido enlaces (de algunos conceptos) al
minidiccionario.

2 Fases de la puesta a punto de un programa en lenguaje C

Para convertir un algoritmo en un programa, se deben llevar a cabo las siguientes fases de
puesta a punto:

Edición. En esta primera fase, el programador debe convertir el algoritmo que haya diseñado
en instrucciones escritas en C. Para ello, se debe hacer uso de un editor de textos, con el cual
se obtendrá el llamado código fuente del programa. El programador deberá guardar dicho
código fuente en un archivo con extensión (.c) o (.cpp).

Si un programa escrito en C se va a compilar con un compilador de C, el código fuente debe ser


guardado, obligatoriamente, en un archivo con extensión (.c). Ahora bien, si se utiliza un
compilador de C/C++, el archivo se puede guardar con extensión (.c) o (.cpp).

Preproceso. El preproceso sirve para realizar modificaciones en el código fuente obtenido en


la fase de edición. Es el programador quien, mediante directivas del preprocesador, "dice" al
preprocesador las modificaciones que éste debe llevar a cabo.

El preprocesador es un programa característico de C, es decir, en otros lenguajes de


programación no existe, y siempre se ejecuta antes de llevarse a cabo la compilación. Esto es
debido a que, es el propio compilador quien llama al preprocesador antes de realizar la
compilación.

Compilación. Una vez que el código fuente ha sido preprocesado, el compilador traducirá
ese código fuente (modificado) a código máquina, también llamado código objeto, siempre y
cuando, el propio compilador no detecte ningún error en dicho código fuente ya preprocesado.

Como resultado de la compilación, el compilador guardará el código objeto del programa en un


archivo con otra extensión, que, dependiendo del sistema operativo puede variar. Por ejemplo,
en Windows, se guardará con la extensión (.obj), abreviatura de object.

Enlace (linkaje o montaje). Los programas pueden utilizar funciones de la biblioteca


estándar de C, tales como scanf o printf. De cada una de ellas existe un código objeto que
debe ser enlazado (unido) al código objeto del programa que las utilice. Esto se realiza
mediante un programa llamado enlazador, montador o linkador.
Como resultado del enlace, el enlazador guardará, en disco, un archivo ejecutable. En Windows,
dicho archivo tendrá extensión (.exe), abreviatura de executable. Dicho archivo será "el
ejecutable".
Además de las funciones de la biblioteca estándar de C, el programador también puede utilizar
funciones que hayan sido desarrolladas por él mismo. Éstas pueden agruparse en su propia
biblioteca de funciones (no estándar). Por lo que, también en esta fase, el código objeto de
dichas funciones deberá ser enlazado al código objeto del programa que las utilice.

Gráficamente, el proceso de puesta a punto de un programa escrito en C se puede ver en la


siguiente figura:

Figura. Fases de la puesta a punto de un programa.

Finalmente, para que el código ejecutable de un programa se ejecute en la computadora, es


necesario que un programa del sistema operativo, llamado cargador, lo lleve a la memoria
principal de la misma. A partir de ese momento, la CPU empezará a ejecutarlo.

3 Estructura de un programa en lenguaje C

Un programa escrito en lenguaje C está compuesto por una o más funciones. Como ya es
sabido, una función es un programa que sirve para realizar una tarea determinada, por
ejemplo, la función scanf sirve para leer datos desde el teclado.

Existe una función que está presente en todos los programas escritos en lenguaje C, su misión
es marcar el inicio y fin de la ejecución de cada uno de ellos; es la función principal, la primera
que se ejecuta; es la función main. Su sintaxis "básica" es:

int main()
{
<bloque_de_instrucciones>
}
La función main contiene al bloque de instrucciones principal de un programa, dentro de
los caracteres abrir llave ({) y cerrar llave (}).

Los paréntesis "()" escritos después de main sirven para indicar que el identificador main es
una función. Es importante comprender que main no es una palabra reservada de C. Ningún
identificador de función lo es.

Finalmente, no podemos pasar por alto que delante de main se ha escrito la palabra reservada
int; enseguida veremos el porqué.

3.1 Tipos de instrucciones en lenguaje C

En lenguaje C, las instrucciones, también llamadas sentencias, se pueden clasificar en:

 De expresión.
 De control.
 Compuestas.

Una instrucción compuesta siempre alberga, entre llaves ({...}), a


un <bloque_de_instrucciones>:

{
<bloque_de_instrucciones>
}

Un bloque de instrucciones puede estar compuesto por una o más instrucciones, que, a su
vez, pueden ser instrucciones de expresión, de control y/o compuestas nuevamente.

El cuerpo de toda función es una instrucción compuesta. Sirva como ejemplo el cuerpo de
la función main, el cual alberga al bloque de instrucciones principal de un programa escrito
en lenguaje C.

Las instrucciones de expresión, también conocidas como instrucciones simples o


elementales, son aquellas que representan a las acciones más pequeñas (elementales)
que se pueden ejecutar en un programa, y siempre van seguidas de un carácter punto y
coma (;), el cual indica que la instrucción ha terminado:

<instrucción_de_expresión>;

Una instrucción de expresión es, en sí misma, una expresión. De modo que, la acción que
se ejecuta es la evaluación de dicha expresión:

<expresión>;

En cuanto a las instrucciones de control, existen de distintos tipos, y todas sirven para
modificar el flujo de control de un programa. Veremos que, algunas de ellas deben ir
seguidas del carácter punto y coma (;), pero otras no.

3.2 Mi primer programa en lenguaje C

Ejemplo: Se quiere escribir un programa que muestre por pantalla un mensaje de saludo:

Hola mundo
Obsérvese que, el saludo se visualiza justo en la esquina superior izquierda de la pantalla.
Más adelante se estudiará cómo se puede mostrar en otro lugar de la pantalla.

En lenguaje C, el código fuente de dicho programa puede ser:

#include <stdio.h>
int main()
{
printf( "Hola mundo" );
return 0;
}
Programa (.c): Hola_mundo

Todas las funciones de la biblioteca estándar de lenguaje C son subprogramas que ya están
compilados, es decir, junto a cualquier compilador de lenguaje C se acompañan los códigos
objeto de todas las funciones de su biblioteca estándar, pero no sus códigos fuente. Por
tanto, aunque no sea posible modificar sus códigos fuente, sí se puede hacer uso de dichas
funciones en cualquier programa. Por ejemplo, se puede llamar a la función printf para
que muestre por pantalla el saludo "Hola mundo".

printf( "Hola mundo" );

Dentro de los paréntesis "()" de la función printf, se debe escribir, entre comillas dobles
("), el mensaje o cadena de caracteres que se desea mostrar por pantalla.

Obsérvese que, después del carácter cerrar paréntesis ")" se ha escrito un punto y
coma (;), esto implica que la llamada a la función printf es considerada como una
instrucción de expresión.

Del código fuente preprocesado de un programa, el compilador generará un código objeto


que se debe unir (enlazar) con los códigos objeto de las funciones de la biblioteca estándar
del lenguaje C que se llamen desde dicho programa. Por ejemplo, el código objeto de
nuestro primer programa se debe enlazar con el código objeto del subprograma printf.

El enlazador sabe dónde encontrar el código objeto de las funciones de la biblioteca


estándar de C que utilice un programa. Sin embargo, para poder utilizar una función (sea
de la biblioteca estándar de C o no) en un programa, la función debe ser declarada
previamente, al igual que se tienen que declarar las variables y las contantes que usa un
programa.

Para que el compilador conozca la declaración de la función printf, hay que utilizar la
directiva del preprocesador #include:

#include <stdio.h>

En este caso, la directiva #include indica, al preprocesador, que debe incluir, antes de la
compilación, en el código fuente del programa, el contenido del Archivo <stdio.h> (stdio,
Standard Input/Output). En dicho archivo están escritas las declaraciones de todas las
funciones de entrada y salida estándar de la biblioteca estándar de C, como printf. Si
el compilador no sabe quién es printf, no podrá generar el código objeto del programa.

Las funciones de la biblioteca estándar de C están clasificadas en base a su funcionalidad, y


sus declaraciones se agrupan en archivos con extensión (.h), los cuales son llamados
archivos de cabecera. Además de stdio.h, algunos de los archivos de cabecera más
utilizados en lenguaje C son: math.h, string.h y stdlib.h. En ellos están escritas,
respectivamente, las declaraciones de las funciones matemáticas, funciones de cadena y
funciones de utilidad de la biblioteca estándar de C.
Después de #include, el nombre del archivo de cabecera se puede escribir entre los
caracteres menor y mayor (<stdio.h>), o entre comillas dobles ("stdio.h"). Cuando se
escriba entre comillas dobles, el preprocesador buscará dicho archivo en el directorio actual
de trabajo, y de no encontrarlo ahí, entonces lo buscará en el directorio especificado por el
compilador. En el caso de escribirse entre el carácter menor y mayor, el proceso de
búsqueda será al revés.

Además de la directiva del preprocesador #include, existen otras, pero, ninguna de ellas
es una palabra reservada del lenguaje C.

El código objeto generado por el compilador de C tendrá "huecos" (espacios) en donde más
tarde el enlazador escribirá el código objeto correspondiente a las llamadas de las funciones
ya compiladas (como printf) y, así, generar el archivo ejecutable.

Toda función retorna un valor. En nuestro primer programa se ha escrito:

return 0;

Esto quiere decir que la función main devuelve el valor 0. Precediendo a main se ha
escrito la palabra reservada int, indicando así, que la función retornará un valor de tipo int
(entero).

int main()

En general, la instrucción return suele ser la última del bloque de instrucciónes de la


función main. Al retornar el valor 0, indica (informa al sistema operativo) que el programa
finalizó correctamente, es decir, sin producirse ningún error en su ejecución. Cuando la
función main devuelva un valor distinto de cero, esto siginificará que se ha producido algún
error en la ejecución del programa, o que ha ocurrido algo fuera de lo normal.

La instrucción return es una de las instrucciones de control que existen en lenguaje C. Por
tanto, es una palabra reservada. Después del valor de retorno (que es una expresión) se
debe escribir un punto y coma (;). La sintaxis de la instrucción return es:

return <expresión>;

Por el momento, se ha visto que la sintaxis "básica" de un programa escrito en lenguaje C


es:

[ <directivas_del_preprocesador> ]
int main()
{
<bloque_de_instrucciones>
}

Los caracteres abrir corchete ([) y cerrar corchete (]) se utilizan para indicar que lo que
contienen es opcional.

Ahora es una buena ocasión para poner en práctica lo aprendido en el apartado 1.2 Fases
de la puesta a punto de un programa. Para ello, puede consultar las Guías de uso de
algunos compiladores de C/C++.
Compiladores de C/C++
A continuación, se explican los pasos básicos que se pueden dar, en distintos
compiladores de C/C++, para editar, compilar y ejecutar el clásico primer
programa que muestra por pantalla el mensaje "Hola mundo":

#include <stdio.h>
int main()
{
printf( "Hola mundo" );
return 0;
}
Programa (.c): Hola_mundo

· Borland C++ Builder 4


Creación de un proyecto (Console Application wizard). Explicación también
válida para una versión posterior de Borland C++ Builder.
· Borland C++ 5.02
Cómo crear un archivo (Text Edit).
· Bloodshed Dev-C++ 4.9.8.0
Pasos, también válidos, para crear un archivo en Dev-C++ 5 (4.9.9.2).
· Microsoft Visual C++ 6.0
Guía básica para la creación de un Workspace, un Proyecto y un Archivo.

4 Tipos de datos en lenguaje C

En lenguaje C se dice que todos los datos que utilizan los programas son básicos (simples
predefinidos o estándares) o derivados. Los tipos básicos en lenguaje C se clasifican en:

Figura. Clasificación de los tipos de datos básicos en C.

4.1 Datos de tipo entero (int)

Un dato de tipo entero (int en lenguaje C ) es aquel que puede tomar por valor un
número perteneciente al conjunto de los números enteros ( Z), el cual está formado por los
números naturales, su opuestos (números negativos) y el cero.

Z = {..., -3, -2, -1, 0, 1, 2, 3,...}

Ejemplo: La edad de una persona y el año en que nació, son dos datos de tipo entero:

Edad...: 29
Año....: 1976
Z es un conjunto infinito de números enteros, y como el ordenador no puede representarlos
todos, un dato de tipo entero sólo puede tomar por valor un número perteneciente a un
subconjunto de Z. Los valores máximo y mínimo de dicho subconjunto varían según las
características de cada ordenador y del compilador que se utilice.

4.2 Datos de tipo real (float o double)

Un dato de tipo real (float o double en lenguaje C) es aquel que puede tomar por valor
un número perteneciente al conjunto de los números reales ( R), el cual está formado por
los números racionales e irracionales.

Ejemplo: El peso de una persona (en kilogramos) y su altura (en centímetros), son datos
que pueden considerarse de tipo real.

Peso.....: 75,3
Altura...: 172,7

R es un conjunto infinito de números reales, y como el ordenador no puede representarlos


todos, un dato de tipo real sólo puede tomar por valor un número perteneciente a un
subconjunto de R. Los valores de dicho subconjunto varían según las características de
cada ordenador y del compilador que se utilice.

La diferencia principal entre float y double está en el hecho de que un dato de


tipo double puede tomar por valor un número perteneciente a un subconjunto de R mayor
que un dato de tipo float.

4.3 Datos de tipo carácter (char)

Un dato de tipo carácter (char en lenguaje C) es aquel que puede tomar por valor un
carácter perteneciente al conjunto de los caracteres que puede representar el ordenador.

En lenguaje C, el valor de un dato de tipo carácter se debe representar entre comillas


simples (').

Ejemplo: En un examen con preguntas en las que hay que seleccionar la respuesta
correcta entre varias opciones dadas (a, b, c, d, e), la respuesta correcta de cada una de
las preguntas es un dato de tipo carácter.

Respuesta correcta a la pregunta 3...: 'c'

4.4 Datos sin valor (void)

Un dato sin valor (void en lenguaje C) es un dato que no puede tomar por valor ningún
valor, es decir, es un dato vacío (nulo). Más adelante estudiaremos su utilidad.

4.5 Datos de tipo lógico

En programación, un dato de tipo lógico es aquel que puede tomar por valor sólo uno de
los dos siguientes:

{ verdadero, falso }
Los valores verdadero y falso son contrapuestos, de manera que, un dato de tipo lógico
siempre está asociado a que algo se cumpla o no se cumpla.

Ejemplo: El estado de una barrera de paso de trenes es un dato que puede considerarse
de tipo lógico, por ejemplo, asociando verdadero a que esté subida y falso a que esté
bajada.

Estado...: falso (indica que la barrera está bajada)

En lenguaje C no existen datos de tipo lógico (que sí existen en otros lenguajes de


programación). Ahora bien, se pueden simular con datos de tipo entero, considerándose el
valor cero (0) como falso, y cualquier otro valor entero como verdadero (para ello,
generalmente, se emplea el valor uno (1)).

4.6 Datos de tipo cadena

De todos los tipos de datos que no son básicos se dice que son derivados, ya que, están
basados en alguno que sí lo es. Por ejemplo, los datos de tipo cadena son aquellos que
pueden tomar por valor una secuencia de caracteres.
En lenguaje C, el valor de un dato de tipo cadena se debe representar entre comillas dobles
(").
Ejemplo: El título de un libro y el nombre de su autor, son datos de tipo cadena.
Título...: "La Odisea" (cadena de 9 caracteres)
Autor....: "Homero" (cadena de 6 caracteres)
Obsérvese que, en la cadena "La Odisea", el carácter espacio en blanco también se cuenta.

5 Identificadores en lenguaje C

La mayoría de los elementos de un programa se diferencian entre sí por su nombre. Por


ejemplo, los tipos de datos básicos en lenguaje C se nombran como:
char, int, float, double y void.
Cada uno de ellos es un identificador. Un identificador es el nombre que se le da a un
elemento de un algoritmo (o programa). Por ejemplo, el tipo de dato int hace referencia a
un tipo de dato que es distinto a todos los demás tipos de datos, es decir, los valores que
puede tomar un dato de tipo entero, no son los mismos que los que puede tomar un dato
de otro tipo.
Los identificadores char, int, float, double y void están predefinidos, forman parte del
lenguaje C. No obstante, en el código de un programa también pueden existir
identificadores definidos por el programador. Por ejemplo, un programa puede utilizar
variables y constantes definidas por el programador.

En lenguaje C, a la hora de asignar un nombre a un elemento de un programa, se debe


tener en cuenta que todo identificador debe cumplir las siguientes reglas de sintaxis:

1. Consta de uno o más caracteres.


2. El primer carácter debe ser una letra o el carácter subrayado (_), mientras que, todos
los demás pueden ser letras, dígitos o el carácter subrayado (_). Las letras pueden ser
minúsculas o mayúsculas del alfabeto inglés. Así pues, no está permitido el uso de las
letras 'ñ' y 'Ñ'.
3. No pueden exitir dos identificadores iguales, es decir, dos elementos de un programa
no pueden nombrarse de la misma forma. Lo cual no quiere decir que un identificador
no pueda aparecer más de una vez en un programa.
De la segunda regla se deduce que un identificador no puede contener caracteres
especiales, salvo el carácter subrayado (_). Es importante resaltar que las vocales no
pueden llevar tilde ni diéresis.
5.1 Ejemplos de identificadores válidos y no válidos en lenguaje C

A continuación, se muestran algunos ejemplos de identificadores válidos en lenguaje C y


otros que no lo son:
Ejemplo 1: Algunos identificadores válidos que pueden ser definidos por el programador
son:
número
día de _mes
PINGUINO1
_ciudad
Z
Ejemplo 2: Los siguientes identificadores no son válidos por incumplir la segunda regla:
123
_DÍA
numero*
lugar de nacimiento
año
Ejemplo 3: Los siguientes identificadores no pueden ser definidos por el programador:
int
char

int y char son identificadores predefinidos (ya existen en lenguaje C), por tanto, no pueden
ser definidos por el programador, en cumplimiento de la tercera regla.
Los identificadores son sensibles a minúsculas y mayúsculas.
Ejemplo 4: Mes y mes son considerados identificadores distintos.
Por último, hay que decir que, es aconsejable que los identificadores tengan un significado
afín a lo que representan.
5.2 Palabras reservadas en lenguaje C

Las palabras reservadas son identificadores predefinidos (tienen un significado especial). En


todos los lenguajes de programación existe un conjunto de palabras reservadas. Por el
momento, en lenguaje C, se han estudiado las siguientes:
char, int, float, double y void

En la sintasis de ANSI C, puede consultar toda la lista de palabras reservadas que existen
en lenguaje C.
6 Variables en lenguaje C

En lenguaje C hay que escribir un punto y coma (;) después de la declaración de una o más
variables. Así pues, la sintaxis para declarar una variable es:

<tipo_de_dato> <variable> [ = <expresión> ];

Y para más de una variable del mismo tipo se utiliza la sintaxis:

<tipo_de_dato> <variable_1> [= <expresión_1>],


<variable_2> [= <expresión_2>],
...,
<variable_n> [= <expresión_n>];

Una expresión representa a un valor de un tipo de dato. En el apartado 1.8 Operadores y


expresiones se estudiarán en detalle las expresiones.
6.1 Ejemplos de declaración de variables en lenguaje C

A continuación, se muestran algunos ejemplos de declaración de variables en lenguaje C.

Ejemplo 1: La declaración de una variable para almacenar la edad de una persona se


escribe:

int edad;

Ejemplo 2: Para declarar varias variables del mismo tipo de dato se puede escribir:

int edad;

int numero_de_hijos;

Ejemplo 3: O también, en la misma línea separada por el carácter coma (,):

int edad, numero_de_hijos;


Ejemplo 4: Si se desea declarar una variable para almacenar un número entero y que,
inicialmente, contenga el valor 35, se debe escribir:

int numero = 35;

Ejemplo 5: A continuación, se muestra la declaración de una variable para almacenar una


letra del alfabeto y que, inicialmente, contenga el valor 'Z':

char letra = 'Z';

Ejemplo 6: Para declarar una variable que pueda almacenar el nombre de una persona y
que, inicialmente, contenga el valor "Isabel", escribiremos:

char nombre[7] = "Isabel";

Un dato de tipo cadena es un dato compuesto (estructurado), debido a que está formado
por una agrupación de caracteres. Pues bien, dicha agrupación se define por medio de un
array. Un array agrupa, bajo el mismo nombre de variable, a una colección de elementos
(datos) del mismo tipo.

Para declarar un array de caracteres, después del identificador de la variable, se tiene que
escribir, entre corchetes "[]", el número de caracteres que se van a almacenar en el array,
más uno. Por tanto, en este caso, puesto que "Isabel" tiene seis caracteres, hay que
escribir un 7 entre los corchetes.

Se tiene que escribir un número más, porque en la memoria se va a reservar espacio para
los seis caracteres de la cadena "Isabel", más uno, conocido éste como el carácter
nulo, el cual se representa mediante una barra invertida y un cero (\0). El sistema se
encarga de "poner" dicho carácter, que indica el fin de la cadena.

Por consiguiente, en la memoria se almacenarán siete caracteres consecutivos:


Los caracteres del array pueden ser referenciados mediante el identificador del mismo,
seguido de un número entre corchetes. A dicho número, de manera formal, se le llama
"índice", y puede oscilar entre el valor 0 y n-1, siendo n el número de caracteres que
pueden ser almacenados en memoria en el array, en este caso 7.

<nombre_de_la_variable>[<índice>]

Por ejemplo, nombre[3] hace referencia al espacio de memoria donde está el carácter 'b'.

Ejemplo 7: Si se declara la variable de tipo cadena:

char nombre[7] = "June";

En memoria tendremos:

Fíjese que, en esta ocasión, el array de caracteres nombre ha sido inicializado con el valor
"June". De manera que, el fin de la cadena se encuentra en nombre[4], y no en el último
espacio de memoria reservado para el array, ya que, "June" tiene, solamente, cuatro
caracteres.

7 Constantes en lenguaje C

En lenguaje C, una constante puede ser de tipo entero, real, carácter, de cadena o
enumerado. Las contantes de tipo enumerado se van a estudiar más adelante. En cuanto a
las demás, se pueden expresar de dos formas diferentes:
1. Por su valor.
2. Con un nombre (identificador).
Ejemplo 1: Las siguientes contantes de tipo entero están expresadas por su valor:
-5 10
Para expresar una constante con un nombre, la constante debe ser declarada previamente.
Las constantes que se declaran en un programa escrito en lenguaje C reciben un
tratamiento diferente al de la mayoría de los lenguajes de programación. En C, para
representar a las constantes, se utilizan constantes simbólicas. Una constante simbólica
representa (sustituye) a una secuencia de caracteres, en vez de representar a un valor
(dato almacenado en memoria).
Para declarar una constante simbólica, en lenguaje C, se utiliza una nueva directiva del
preprocesador:

#define <constante> <secuencia_de_caracteres>

La directiva #define indica al preprocesador que debe sustituir, en el código fuente del
programa, todas las ocurrencias del <nombre_de_la_constante> por la

<secuencia_de_caracteres>, antes de la compilación.

Ejemplo 2: Dos constantes muy habituales son:

#define PI 3.141592

#define NUMERO_E 2.718281

En programación es una buena práctica escribir los identificadores de las constantes en


mayúsculas, de esta forma es más fácil localizarlos en el código de un programa. Nótese
que, después de la declaración de una constante simbólica no se escribe un carácter punto
y coma (;), cosa que sí se debe hacer al declarar una variable.

Por otra parte, no se puede declarar más de una constante simbólica en una misma línea de
código.

Ejemplo 3: Para declarar las constantes simbólicas PI y NUMERO_E, no se puede escribir:

#define PI 3.141592, NUMERO_E 2.718281

Por otra parte, en C, es posible declarar una variable indicando que su valor es inalterable.

Para ello, se utiliza el cualificador const.

Ejemplo 4: Uso de const:

const int temperatura = -5;

En el ejemplo, se ha declarado la variable entera temperatura inicializada al valor -5 y, por


medio de const, que es una palabra reservada, se ha indicado que su valor no puede
cambiar durante la ejecución del programa. En cierta manera, la variable temperatura está
simulando a una constante.

Ya se sabe cómo escribir la declaración de una constante y de las variables que utilice un
programa y, también, se conoce el lugar en que se tiene que escribir la directiva del
preprocesador #define para declarar la constante.

En cuanto a las variables que utiliza un programa, su declaración puede escribirse en varios
lugares, pero, de momento las vamos a declarar inmediatamente después del carácter abrir
llave ({) de la función main.
[ <directivas_del_preprocesador> ]
int main()
{
[ <declaraciones_de_variables> ]
<lista_de_instrucciones>
}

Ejemplo 5: Si en un programa se quieren declarar dos variables (area y radio) y una


constante (PI), se puede escribir:

#define PI 3.141592
int main()
{
float area, radio;
...
}
7.1 Constantes de tipo entero

Una constante de tipo entero es aquella que representa a un valor (dato) perteneciente
al subconjunto de Z representable por el ordenador.
Ejemplo 1: Suponiendo que el ordenador (utilizando dieciséis bits) pueda representar, en
Complemento a 2, el siguiente conjunto de valores enteros:
{ -32768, -32767, ..., 1, 0, -1, ..., 32766, 32767 }
Algunos ejemplos de constantes de tipo entero son:
-32000, 0, 000077 (Los ceros a la izquierda no son significativos), +1111
Obsérvese que, además de los caracteres numéricos, dígitos del (0) al (9), también se
puede hacer uso de los caracteres especiales (+) y (-) para indicar el signo de un número
entero, el cual es positivo por omisión. Sin embargo, en lenguaje C, es incorrecto usar los
caracteres coma (,) y/o punto (.) para expresar constantes de tipo entero.
Ejemplo 2: Por tanto, es incorrecto escribir:
-32.000 0,0 +1,111.00
Ejemplo 3: Otros ejemplos incorrectos de constantes de tipo entero son:
++111 (No se puede duplicar el signo)
38000 (No pertenece al subconjunto de Z representable por el ordenador)
7.2 Constantes de tipo real

Una constante de tipo real es aquella que representa a un valor (dato) perteneciente al
subconjunto de R representable por el ordenador.
Ejemplo 1: Algunos ejemplos son:
8.12, 000.333 (Los ceros a la izquierda no son significativos), +1111.809
-3200. (También se puede escribir -3200.0), .56 (También se puede escribir 0.56)

Obsérvese que, además de los caracteres numéricos, dígitos del (0) al (9), también se
puede hacer uso de los caracteres especiales (+) y (-) para indicar el signo de un número
real. Además, en lenguaje C, obligatoriamente debe aparecer el carácter punto (.), o el
carácter (e) o (E) seguido del exponente, del cual también puede indicarse su signo con
los caracteres (+) y (-). Los signos del exponente y del número en sí, por omisión, son
positivos.
Ejemplo 2: Las siguientes constantes de tipo real están expresadas correctamente:
-77e-3, +1111e+2, 2000E+2, 3040e2
Una constante de tipo real también se puede expresar con el carácter punto (.) y el
exponente al mismo tiempo.
Ejemplo 3: Algunos ejemplos son:
-50.50e-4, 400.e-3, +65.65E+2, .7e2
El exponente tiene la función de desplazar la posición del punto decimal hacia la derecha si
es positivo o, hacia la izquierda si es negativo.
Ejemplo 4: Así pues, las siguientes constantes de tipo real representan al mismo valor:
0.004E+3 4. .4e1 +400.00e-2 4000E-3
Ejemplo 5: Algunos ejemplos de constantes de tipo real incorrectas son:
-200 (No aparece el punto ni el exponente)
-20,0 (No puede aparecer la coma)
--111. (No se puede duplicar el signo)
-111.. (No se puede duplicar el punto)
-111.11. (No puede aparecer más de un punto)
+22e (Después del carácter (e) o (E) se debe escribir el exponente)
+22ee6 (No se puede duplicar el carácter (e) o (E))
+22e 6 (No se puede escribir el carácter espacio en blanco)
38E-2.2 (El exponente debe ser una cantidad entera)

7.3 Constantes de tipo carácter

Una constante de tipo carácter es aquella que representa a un valor (dato)


perteneciente al conjunto de caracteres que puede representar el ordenador.
Ejemplo 1: Las siguientes constantes de tipo carácter están expresadas por su valor:
'a' 'T' '5' '+' '.'
Ejemplo 2: En lenguaje C, para representar el carácter comilla simple ('), se debe
anteponer el carácter barra invertida (\).
'\''

7.4 Constantes de tipo cadena

Una constante de tipo cadena es aquella que representa a un valor (dato) de tipo
cadena, es decir, representa a una secuencia de caracteres.

Ejemplo 1: Las siguientes constantes de tipo cadena están expresadas por su valor:
"Alejandro" "Lucerna" "Barcelona 2000"
Ejemplo 2: En lenguaje C, para representar el carácter comilla doble (") dentro de una
cadena, se debe anteponer el carácter barra invertida (\).
#define FIESTA "7 de julio \"San Fermín\""
8 Operadores y expresiones en lenguaje C

Nota: El comienzo de este apartado es el mismo que el del apartado 5.1 Operadores y
expresiones del Curso de Diseño de Algoritmos, pero, a partir del ejemplo 3, las diferencias
empiezan a ser significativas. No obstante, en el libro EMPEZAR DE CERO A PROGRAMAR
EN LENGUAJE C no se da está circunstancia, ya que, los contenidos están distribuidos de
forma distinta.
En un programa, el tipo de un dato determina las operaciones que se pueden realizar con
él. Por ejemplo, con los datos de tipo entero se pueden realizar operaciones aritméticas,
tales como la suma, la resta o la multiplicación.
Ejemplo 1: Algunos ejemplos son:
111 + 6 (operación suma)
19 - 72 (operación resta)
24 * 3 (operación multiplicación)
Todas las operaciones del ejemplo constan de dos operandos (constantes enteras) y un
operador. La mayoría de las veces es así, pero, también es posible realizar operaciones con
distinto número de operadores y/u operandos.
Ejemplo 2: Por ejemplo:
111 + 6 - 8 (tres operandos y dos operadores)
-( ( +19 ) + 72 ) (dos operandos y tres operadores)
-( -72 ) (un operando y dos operadores)
En las operaciones del ejemplo se puede observar que los caracteres más (+) y menos (-)
tienen dos usos:
1. Operadores suma y resta.
2. Signos de un número (también son operadores).
Los operadores de signo más (+) y menos (-) son operadores monarios, también
llamados unarios, ya que, actúan, solamente, sobre un operando.
Los caracteres abrir paréntesis "(" y cerrar paréntesis ")" se utilizan para establecer la
prioridad de los operadores, es decir, para establecer el orden en el que los operadores
actúan sobre los operandos.
Un operador indica el tipo de operación a realizar sobre los operandos (datos) que actúa.
Los operandos pueden ser:

 Constantes (expresadas por su valor o con un nombre (identificador)).


 Variables.
 Llamadas a funciones.
 Elementos de formaciones (arrays).
En este apartado se van a tratar operaciones en donde sólo aparecen constantes y
variables. Cuando se combinan uno o más operadores con uno o más operandos se obtiene
una expresión. De modo que, una expresión es una secuencia de operandos y operadores
escrita bajo unas reglas de sintaxis.
Ejemplo 3: Dadas las siguientes declaraciones de constantes y variables:
#define PI 3.141592
int numero = 2;
float radio_circulo = 3.2;
Algunos ejemplos de expresiones son:
2 * PI * radio_circulo
( PI * PI )
numero * 5
De sus evaluaciones se obtienen los valores:
20.106189 (valor real) ( 2 * 3.141592 * 3.2 )
9.869600 (valor real) ( 3.141592 * 3.141592 )
10 (valor entero) ( 2 * 5 )
Un operador siempre forma parte de una expresión, en la cual, el operador siempre actúa
sobre al menos un operando. Por el contrario, un operando sí puede aparecer solo en una
expresión.
En programación, de la evaluación de una expresión siempre se obtiene un valor. Dicho
valor puede ser de tipo: entero, real, lógico, carácter o cadena. Por consiguiente, una
expresión puede ser:

 Aritmética (devuelve un número entero o real).


 Lógica (devuelve un valor lógico: verdadero o falso)
 De carácter (devuelve un carácter representable por el ordenador).
 De cadena (devuelve una cadena).
A continuación, vamos a estudiar los operadores y las expresiones en lenguaje C, en
comparación con los operadores y expresiones en psedocódigo CEE utilizado por el autor en
el libro EMPEZAR DE CERO A PROGRAMAR EN LENGUAJE C.
8.1 Expresiones aritméticas

De la evaluación de una expresión aritmética siempre se obtiene un valor de tipo entero


o real. En lenguaje C existen algunos operadores que no se utilizan en pseudocódigo, y al
revés. A continuación, se van a ver algunas similitudes y diferencias entre ambos lenguajes.

Figura. Comparación entre operadores aritméticos en pseudocódigo y en C.

Como se puede apreciar, existen tres diferencias importantes entre los operadores
aritméticos en pseudocódigo y en lenguaje C:
1. El operador potencia (**) no existe en lenguaje C.
2. En lenguaje C, sólo existe un operador de división (/).
3. En lenguaje C, el operador módulo (mod) se escribe con el carácter porcentaje
(%).
Ejemplo: A partir de las variables:
En pseudocódigo:
entero a = 4, b = 7, c = 2
En lenguaje C:
int a = 4, b = 7, c = 2;
podemos escribir, por ejemplo, la expresión:
En pseudocódigo:
-a * ( b mod c )
En lenguaje C:
-a * ( b % c )
De la evaluación de esta expresión se obtiene el valor
-4 (actúan en orden los operadores: (%), menos (-) y (*))

8.1.1 El operador división (/)

Puesto que, en lenguaje C, sólo existe un operador de división, el resultado de una


división dependerá de los operandos. La regla a seguir es: "si ambos operandos son
enteros, el resultado de evaluar la expresión será entero, en caso contrario, es decir, si
al menos un operando es real, el resultado será real".
Ejemplo: Declaradas las variables:
int h = 3, v = 6;
De las expresiones:
v/h 5/h 5.0 / 2 5 / 2. 5.4 / 2.0
se obtienen los valores:
2 (valor entero, ambos operandos son enteros)
1 (valor entero, ambos operandos son enteros)
2.5 (valor real, el primer operando es real)
2.5 (valor real, el segundo operando es real)
2.7 (valor real, ambos operandos son reales)

8.1.2 Conversión de tipo (casting)

En lenguaje C, cuando los dos operandos de una división (/) son enteros, pero aun así,
de su evaluación se quiere obtener un valor real, hay que hacer un casting (o
conversión de tipo). Su sintaxis es:

( <tipo_de_dato> ) <expresión>;
De esta forma, se consigue cambiar el tipo de dato del valor resultante de evaluar la
<expresión> a un <tipo_de_dato> deseado.
Ejemplo: Para cambiar el tipo de dato de los valores resultantes de las siguientes
expresiones:
5 (valor entero) v (valor entero) 5.0 (valor real) v/h
5/h 5.0 / 2 5 / 2. 5.4 / 2.0
se pueden escribir:
( float ) 5 ( float ) v ( int ) 5.0 ( float ) v / h
( float ) 5 / h ( int ) 5.0 / 2 5 / ( int ) 2. ( int ) ( 5.4 / 2.0 )
de tal forma que, los resultados de evaluar las expresiones anteriores son:
5.000000 (valor real)
6.000000 (valor real)
5 (valor entero)
2.000000 (actúan en orden los operadores: "( <tipo> )" y (/))
1.666667 (actúan en orden los operadores: "( <tipo> )" y (/))
2 (actúan en orden los operadores: "( <tipo> )" y (/))
2 (actúan en orden los operadores: "( <tipo> )" y (/))
2 (actúan en orden los operadores: (/) y "( <tipo> )")
8.1.3 La función pow

En lenguaje C, para realizar operaciones con potencias se utiliza una función de su


biblioteca estándar, en concreto la función pow, a la que hay que "darle" (pasarle) dos
operandos entre paréntesis. La sintaxis de su llamada es:

pow( <operando_número_base>, <operando_exponente> )

La función pow devuelve, sobre el propio identificador de la función, el resultado que


se obtiene de elevar el <operando_número_base> al <operando_exponente>. El valor
de retorno de la función es de tipo double, con independencia de que los operandos
sean reales o enteros.
Ejemplo: Partiendo de la variable:
En pseudocódigo:
entero numero = 9
En lenguaje C:
int numero = 9;
De la expresión:
En pseudocódigo:
1 + numero ** 2
En lenguaje C:
1 + pow( numero, 2 )
La función pow devuelve el resultado de elevar el valor de la variable numero a 2. De
manera que, el resultado de evaluar la expresión anterior es:
82.000000 (se obtiene de 1 + 81. 000000)

La declaración de la función pow se encuentra en el archivo de cabecera math.h. Por


tanto, si en un programa se utiliza dicha función, habrá que escribir también:
#include <math.h>
8.2 Expresiones lógicas

De la evaluación de una expresión lógica siempre se obtiene un valor de tipo lógico


(verdadero o falso). En las expresiones lógicas se pueden utilizar dos tipos de operadores:

 Relacionales.
 Lógicos.
8.2.1 Operadores relacionales

Un operador relacional se utiliza para comparar los valores de dos expresiones. Éstas
deben ser del mismo tipo (aritméticas, lógicas o de carácter).

En la siguiente figura se comparan los operadores relacionales en pseudocódigo y en


lenguaje C:

Figura. Comparación entre operadores relacionales en pseudocódigo y en C.

Las diferencias son dos:


1. En C, el operador igual que (=) se escribe con los caracteres igual-igual (==).
2. En C, el operador distinto que (<>) se escribe con los caracteres admiración-igual
(!=).
Ejemplo: A partir de las variables:
En pseudocódigo:
entero p = 45, q = 186
En lenguaje C:
int p = 45, q = 186;
Podemos escribir la expresión:
En pseudocódigo:
p <> q
En lenguaje C:
p != q
De su evaluación se obtiene:
En pseudocódigo:
verdadero ( p es distinta de q )
En lenguaje C:
1 (C simula el valor lógico verdadero con el valor entero 1)
En lenguaje C, los datos de tipo lógico se simulan con datos de tipo entero,
considerándose el valor 0 como falso, y cualquier otro valor entero como verdadero.
8.2.2 Operadores lógicos

Un operador lógico actúa, exclusivamente, sobre valores de expresiones lógicas.


En la siguiente figura se comparan los operadores lógicos en pseudocódigo y en
lenguaje C:

Figura. Comparación entre operadores lógicos en pseudocódigo y en C.

Ejemplo: Habiendo declarado las variables:


En pseudocódigo:
entero r = 2, s = 9, t = 8
En lenguaje C:
int r = 2, s = 9, t = 8;
se puede escribir
En pseudocódigo:
no( r = s o r <= t )
En lenguaje C:
!( r == s || r <= t )
La expresión se evalúa a
En pseudocódigo:
falso (actúan en orden los operadores: (<=), (==), (||) y (!))
En lenguaje C:
0 (C simula el valor lógico falso con el valor entero 0)

8.3 La función strcat

En lenguaje C, no existe el operador concatenación (+), que sí existe en otros lenguajes.


Sin embargo, para concatenar cadenas, se puede utilizar la función strcat, que está
disponible en la biblioteca estándar de C. La sintaxis de una llamada a strcat es:

strcat( <cadena_destino>, <cadena_fuente> )

La función strcat añade el contenido de la <cadena_fuente> a la <cadena_destino>.


Ejemplo: Dadas las siguientes declaraciones de arrays de caracteres:
En pseudocódigo:
cadena nombre = "Ana", apellido = "Luz"
En lenguaje C:
char nombre[8] = "Ana", apellido[4] = "Luz";

es posible escribir la expresión:


En pseudocódigo:
nombre + apellido
En lenguaje C:
strcat( nombre, apellido )
Observe el efecto que tiene, en la memoria de la computadora, la ejecución de la
función strcat. El contenido del array apellido se concatena (añade) al array nombre.
La declaración de la función strcat se encuentra en el archivo de cabecera string.h. Por
tanto, para poder usar dicha función en un programa, hay que escribir:
#include <string.h>
8.4 Operadores de asignación

En lenguaje C existen expresiones de asignación y, para escribirlas, se utilizan los siguientes


operadores de asignación:

Figura. Clasificación de los operadores de asignación en C.

De ellos, el más utilizado es el operador de asignación (=). Su funcionalidad es equiparable


a la de una instrucción de asignación en psedocódigo, y su sintaxis es muy similar.

<nombre_de_la_variable> = <expresión>;

Existen dos diferencias:


1. En vez del símbolo reservado flecha izquierda (←), se utiliza el carácter igual (=).
2. Se debe escribir un punto y coma (;) al final.

Ejemplo 1: Partiendo de la constante simbólica


#define PI 3.141592
y de las variables
float area, longitud, radio;
una instrucción de asignación puede ser:
radio = 5.78;
Técnicamente, en lenguaje C, una asignación (=) es una operación, al igual que lo es una
suma (+) o una resta (-). En consecuencia, radio = 5.78 es una expresión de asignación,
que entra dentro de la categoría de las instrucciones de expresión.

<instrucción_de_expresión>;

De la evaluación de una expresión de asignación siempre se obtiene el mismo valor que el


asignado a la variable, en este caso, 5.78.
Si ahora escribimos:
area = PI * pow( radio, 2 );
longitud = 2 * PI * radio;
De la evaluación de estas instrucciones de expresión se obtienen los valores 57.046290
y 36.316804, los cuales coinciden con los valores asignados a las variables area y longitud,
respectivamente.

Cuando el operador de asignación (=) se escribe precedido de un operador aritmético: suma


(+), resta (-), multiplicación (*), división (/) o módulo (%), la unión de ambos se convierte
en un nuevo operador de asignación que opera de la siguiente manera:
"A la variable se le asigna el valor que se obtiene de evaluar
<variable> <operador_aritmético> <expresión>."
Ejemplo 2: Dada la siguiente declaración de variables:
int m = 4, n = 1;

se puede escribir la instrucción de expresión m += 3;


que es equivalente a la instrucción m = m + 3;
En la memoria, cambiará el valor almacenado en el espacio representado por la variable m.

Si, a continuación, se ejecuta la instrucción m *= n += 2;


ahora, los valores de las variables m y n son:

Primero, se evalúa la expresión n += 2 (equivalente a n = n + 2). Esto produce que a la


variable n se le asigne un 3. En segundo lugar, se evalúa la expresión m *= 3 (equivalente
a m = m * 3), asignándosele a la variable m el valor 21.

8.5 La función strcpy

En lenguaje C, para asignar una expresión de cadena a un array de caracteres, no se puede


utilizar el operador de asignación (=). Para ello, se puede utilizar la función strcpy, que
está disponible en la biblioteca estándar de C. La sintaxis de una llamada a strcpy es:

strcpy( <variable_destino>, <cadena_fuente> )

La función strcpy copia el contenido de la <cadena_fuente> en la <variable_destino>,


siendo ésta un array de caracteres.
Ejemplo: Habiendo declarado el siguiente array de caracteres:
En pseudocódigo:
cadena ciudad
En lenguaje C:
char ciudad[6];
es posible escribir
En pseudocódigo:
ciudad ← "Roma" (instrucción de asignación)
En lenguaje C:
strcpy( ciudad, "Roma" ) (instrucción de expresión)

Por tanto, en memoria tendremos:


La declaración de la función strcpy se encuentra en el archivo de cabecera string.h. Por
tanto, para poder usar dicha función en un programa, hay que escribir:
#include <string.h>
8.6 Los operadores incremento (++) y decremento (--)

En lenguaje C, tanto el operador incremento (++) como el operador decremento (--)


actúan siempre sobre un solo operando, normalmente una variable. Por tanto, son
operadores monarios, y sirven para incrementar o decrementar en una unidad el valor de
dicho operando.
Ejemplo 1: Declaradas las variables:
int r = 8, s = 3;

se pueden escribir las instrucciones de expresión:


r++;
s--;
Dichas instrucciones son equivalentes a:
r = r + 1;
s = s - 1;
Y también se pueden escribir como:
++r;
--s;
Tras su ejecución, el aspecto de la memoria será:

En estas instrucciones, ambos operadores se pueden escribir, indistintamente, antes o


después de los operandos sobre los que actúan. Pero, cuando en una expresión, además
del operador incremento o decremento, también aparecen otros operadores, entonces sí
que hay que tener en cuenta la diferencia que supone el escribirlos antes o después.

Ejemplo 2: A partir de las variables:


int i = 5, j, k = 5, m;
Si se ejecutan las instrucciones:
j = i++;
m = ++k;
Los valores de las variables en memoria serán:

Obsérvese que, los valores de j y m son diferentes. Esto es debido a que, cuando se evalúa
la expresión j = i++, en primer lugar, se le asigna a j el valor de i (es decir, un 5) y, a
continuación, se incrementa el valor de la variable i. Por el contrario, cuando se evalúa la
expresión m = ++k, primero, se incrementa el valor de k (de 5 pasa a ser 6) y, después,
este nuevo valor de k se le asigna a m.
En resumen, cuando en una expresión el operador incremento (++) o decremento (--)
precede al operando sobre el que actúa (por ejemplo ++k), antes de utilizar el valor de
dicho operando para otro propósito, este se incrementa. De ser al revés, es decir, si es el
operando quien precede al operador (por ejemplo i++), el valor de dicho operando se
incrementa después de ser utilizado para otro fin.
8.7 Prioridad de operadores en lenguaje C

La prioridad de todos los operadores del lenguaje C estudiados hasta el momento es:
Figura. Prioridad de los operadores aritméticos; de índice de un array, de llamada a una
función, relacionales, lógicos, de asignación y de conversión de tipo en C.
Obsérvese que, en lenguaje C, tanto los paréntesis "()" que se utilizan para llamar a una
función, como los corchetes "[]" que albergan el índice de un array, también son
considerados operadores. Además, son los operadores más prioritarios y, en una expresión,
se evalúan de izquierda a derecha.
Por otra parte, los operadores incremento (++), decremento (--) y conversión de tipo "(
<tipo> )" entran dentro de la categoría de operadores monarios. De manera que, al igual
que los operadores signo más (+), signo menos (-), negación (!) y de asignación, todos
ellos se evalúan de derecha a izquierda en una expresión, al revés que todos los demás.
9 Entrada y salida estándar en lenguaje C

En lenguaje C no existen palabras reservadas para realizar entradas y salidas. Para ello, el
programador puede hacer uso de las funciones de entrada y salida estándar proporcionadas
por la biblioteca estándar de lenguaje C, como son printf y scanf, entre otras que
estudiaremos más adelante.
9.1 La función printf

La función printf permite llevar hacia la salida estándar (la pantalla) los valores (datos)
obtenidos de la evaluación de una lista de argumentos. La sintaxis de su llamada es:

printf( <cadena_de_control> [, <lista_de_argumentos> ] )

En programación, los argumentos (también llamados parámetros) se emplean para


transferir datos de un programa (o subprograma) llamante a otro llamado, y viceversa (del
llamado al llamante).
Cuando desde un programa llamante se invoca a la función printf, a ésta se le pasa una
lista de argumentos (expresiones). Los valores (datos) obtenidos de la evaluación de esa
lista de expresiones son los que se van a mostrar por la pantalla. También
la <cadena_de_control> es un argumento.
En la <cadena_de_control>, el programador debe indicar el formato de salida de los datos
que se van a mostrar por la pantalla. Para ello, se puede hacer uso de:

 Texto ordinario (texto normal).


 Especificadores de formato.
 Secuencias de escape.
La <cadena_de_control> es, en sí misma, una cadena de caracteres, que se debe escribir
entre comillas dobles (").
9.1.1 Texto ordinario

En la función printf de la biblioteca estándar del lenguaje C, el texto ordinario que se


puede utilizar es texto normal y corriente, a diferencia de los especificadores de
formato y de las secuencias de escape, que se les considera texto especial.

Ejemplo (ejemplo_11_28.c del libro): En la llamada a la función printf de nuestro


primer programa, la cadena de control sólo contenía texto ordinario:

#include <stdio.h>
int main()
{
printf( "Hola mundo" );
return 0;
}
Nótese que, en este ejemplo, a la función printf no se le pasa ningún argumento,
aparte de la cadena de control.
Por pantalla aparecerá:

Hola mundo

9.1.2 Especificadores de formato

Cuando a la función printf de la biblioteca estándar del lenguaje C se le pase una lista
de argumentos (expresiones), se debe escribir un especificador de formato por cada
argumento. En la printf, los especificadores de formato establecen el formato de
salida por pantalla de los argumentos. La forma más sencilla de escribir un
especificador de formato es con el carácter tanto por ciento (%) seguido de un
carácter de conversión que indique el tipo de dato del argumento. De momento, no
es necesario conocer todos los especificadores de formato que se pueden usar en la
función printf, pero sí, los más utilizados:

Figura. Especificadores de formato más utilizados en la función printf.


Ejemplo 1 (ejemplo_11_29.c del libro): Dada la constante simbólica
#define NOMBRE "Raquel"
si escribimos
printf( "Hola %s", NOMBRE );
por pantalla se verá:

Hola Raquel

El especificador de formato (%s) escrito en la cadena de control, indica que, por


pantalla, se va a mostrar un dato de tipo cadena en ese lugar, en este caso, "Raquel".
Ejemplo 2 (ejemplo_11_30.c del libro): Si se ejecuta el programa

#include <stdio.h>
int main()
{
char nombre[8] = "Timoteo";
int hermanos = 2, sobrinos = 4;
printf( "%s tiene %d hermanos y %d sobrinos.",
nombre, hermanos, sobrinos );
return 0;
}
por pantalla se verá:

Timoteo tiene 2 hermanos y 4 sobrinos.

En la cadena de control del ejemplo, los especificadores de formato (%s), (%d) y


(%d) indican que, en esos lugares, y en dicho orden, va a aparecer un dato de tipo
cadena, un dato de tipo entero y otro dato de tipo entero, respectivamente. En este
caso, se muestran los valores "Timoteo", 2 y 4.
Cada especificador de formato de la cadena de control se hace corresponder con un
argumento (expresión), en el mismo orden de aparición, de izquierda a derecha. En el
caso de que existan más argumentos que especificadores de formato, los "sobrantes"
son ignorados. Por el contrario, si existen menos argumentos que especificadores de
formato, en pantalla se mostrarán datos inverosímiles.
9.1.3 Secuencias de escape

Una secuencia de escape siempre representa a un carácter del ASCII. Dichos


caracteres se pueden clasificar en:

 Gráficos (se corresponden con los símbolos más usados para escribir por los
humanos).
 No gráficos (representan a acciones, como por ejemplo, mover el cursor de la
pantalla al principio de la línea siguiente).
La forma más sencilla de escribir una secuencia de escape es con el carácter barra
invertida (\), seguido de un carácter especial. Por tanto, cuando en la cadena de
control de la función printf se escriba una secuencia de escape, o bien se mostrará un
carácter gráfico por pantalla, o bien se realizará una acción. Por ahora, no es necesario
conocer todas las secuencias de escape que existen en lenguaje C, pero sí, algunas de
las más utilizadas:

Figura. Secuencias de escape más utilizadas.

En general, cuando se diseña el algoritmo de un programa, el programador no se


preocupa del lugar exacto de la pantalla en donde van a aparecer los datos de salida
del programa, ya que, este aspecto suele concretarse en la codificación.
En Windows, la patanlla (de la consola) está compuesta por 25 filas (líneas) y 80
columnas, es decir, en pantalla se pueden visualizar 2000 caracteres a la vez (25*80).
Normalmente, al ejecutar un programa escrito en lenguaje C, el cursor se posiciona
(por defecto) en la primera columna de la primera fila.

_ (cursor)
A partir de esa posición, se mostrarán por pantalla los datos de salida de dicho
programa.

Ejemplo 1 (ejemplo_11_33_1.c del libro): Si se escribe

#include <stdio.h>
int main()
{
printf( "uno dos tres" );
return 0;
}

Tal cual está escrita la función printf, por pantalla se verá el texto "uno dos tres"
pegado a la esquina superior izquierda de la misma.

uno dos tres

Hasta ahora, no nos hemos preocupado del lugar exacto de la pantalla donde queremos
que se muestren los datos de salida. Sin embargo, si deseamos visualizar dicho texto en
otro lugar de la pantalla, por ejemplo, en la segunda línea:

uno dos tres

Esto se puede conseguir haciendo uso de la secuencia de escape nueva línea (\n).
printf( "\nuno dos tres" ); (ejemplo_11_33_2.c del libro)
Partiendo de que, inicialmente, el cursor se encuentre en la primera columna de la
primera fila, es decir, en la esquina superior izquierda de la pantalla, la secuencia de
escape nueva línea (\n) lo moverá al principio de la segunda fila y, a continuación, se
escribirá el texto "uno dos tres". Obsérvese que, los caracteres que forman la
secuencia de escape, (\) y (n), no aparecen en pantalla.
La instrucción anterior hace lo mismo que las dos siguientes
printf( "\n" );
printf( "uno dos tres" ); (ejemplo_11_33_3.c del libro)
Ejemplo 2: Si por pantalla se quiere ver

uno
dos
tres

hay que escribir


printf( "uno\ndos\ntres" ); (ejemplo_11_34_1.c del libro)
El proceso de ejecución de esta instrucción es el siguiente: justo en la esquina superior
izquierda de la pantalla (primera línea) se muestra el texto "uno". Después, una
secuencia de escape nueva línea (\n) mueve el cursor al principio de la línea siguiente
(segunda línea), en donde se visualiza el texto "dos". Posteriormente, otra secuencia
de escape nueva línea (\n) vuelve a mover el cursor al principio de la línea siguiente
(tercera línea) y, finalmente, se muestra el texto "tres".
La instrucción anterior es equivalente a:
printf( "uno" );
printf( "\ndos" );
printf( "\ntres" ); (ejemplo_11_34_2.c del libro)
Igualmente, se podría escribir
printf( "uno\n" );
printf( "dos\n" );
printf( "tres" ); (ejemplo_11_34_3.c del libro)
Ejemplo 3: Para visualizar

uno dos tres

se puede escribir
printf( "\n uno dos tres" ); (ejemplo_11_35.c del libro)
Ejemplo 4: Y para mostrar

uno
dos
tres

escribiremos, por ejemplo,


printf( "\n uno\n dos\n tres" ); (ejemplo_11_36.c del libro)
La secuencia de escape tabulador horizontal (\t) mueve el cursor a la posición siguiente del
tabulador horizontal de la pantalla. Entre cada posición hay ocho caracteres, por tanto, dichas
posiciones están en las columnas 1, 9, 17, 25, 33, 41, 49, 57, 65 y 73.
Ejemplo 5: De la instrucción
printf( "diez\tveinte\ttreinta" ); (ejemplo_11_37.c del libro)
se obtiene por pantalla

diez veinte treinta

Obsérvese que, la d (de diez), la v (de veinte) y la primera t (de treinta) están en las
posiciones del tabulador horizontal 1, 9 y 17, respectivamente. Gráficamente, representando los
espacios en blanco mediante guiones (-), en pantalla se muestra:

1 9 17 25 ...

diez----veinte--treinta

Entre el carácter d (de diez) y la v (de veinte) hay exactamente ocho caracteres (la v no se
cuenta), al igual que entre la v (de veinte) y la primera t (de treinta).
Las secuencias de escape comilla doble (\") y barra invertida (\\) sirven para mostrar por la
pantalla los caracteres comilla doble (") y barra invertida (\), respectivamente.
Ejemplo 6 (ejemplo_11_39_1.c del libro): Al escribir
printf( "\n\t\t7 de julio \"San Fermin\"" );
en la segunda línea de la pantalla se mostrará, a partir de la tercera posición del tabulador
horizontal (columna 17), el mensaje: "7 de julio "San Fermin""
1 9 17 25 ...

7 de julio "San Fermin"

9.2 La función scanf

La función scanf de la biblioteca estándar del lenguaje C permite asignar a una o más
variables, uno o más valores (datos) recibidos desde la entrada estándar (el teclado). La
sintaxis de su llamada es:

scanf( <cadena_de_control> [, <lista_de_argumentos> ] )

En la <cadena_de_control>, el programador debe indicar el formato de entrada de los


datos que se van a recoger por teclado. Para ello, se puede hacer uso de:

 Especificadores de formato.
 Otros caracteres
Por ahora, sólo vamos a estudiar algunos de los especificadores de formato más utilizados
en la función scanf.
9.2.1 Especificadores de formato

En la fución scanf, por cada argumento (variable) que se le pase, se debe escribir un
especificador de formato, que establecerá el formato de entrada por teclado del
argumento. La forma más sencilla de escribir un especificador de formato en la
función scanf es con el carácter tanto por ciento (%) seguido de un carácter de
conversión que indique el tipo de dato del argumento. De momento, no es necesario
conocer todos los especificadores de formato que se pueden usar en la función scanf,
pero sí, los más usados, que son los mismos que en la función printf:

Figura. Especificadores de formato más utilizados en la función scanf.


Ejemplo 1: (ejemplo_11_40.c del libro) Dado el programa

#include <stdio.h>
int main()
{
int numero;
printf( "\n Introduzca un numero entero: " );
scanf( "%d", &numero );
return 0;
}

En la memoria se reservará espacio para la variable numero. Y si el usuario teclea, por


ejemplo, un 5, en pantalla se verá

Introduzca un numero entero: 5

Puesto que la variable numero es de tipo entero, en la cadena de control se tiene que
escribir el especificador de formato asociado a la entrada de un número entero (%d).
Por otro lado, la variable numero se ha escrito precedida del carácter ampersand (&).
Se trata de un nuevo operador, el operador dirección. El operador dirección (&)
siempre actúa sobre un operando (normalmente una variable) y, de su evaluación, se
obtiene la dirección de memoria de dicha variable.
Es sabido que, una variable representa a un espacio de memoria en el cual se puede
almacenar un dato. Pues bien, en realidad, a la función scanf no se le pasa una lista de
variables, sino, las direcciones de memoria de los espacios de memoria a los que
representan dichas variables.
Para todas las variables declaradas en un programa se reservan espacios de memoria
en donde se almacenarán datos. La memoria del computador está dividida en celdas
numeradas de forma consecutiva, por lo que, cada una de ellas tiene una dirección (un
número). Un dato puede necesitar una o más celdas de memoria. Así pues, en
el ejemplo_11_40, la expresión &numero hace referencia a la primera celda donde se
va a almacenar el valor 5 introducido por el usuario. La dirección de memoria de la
variable numero podría ser, por ejemplo, 0012FF88. En informática, las direcciones de
memoria suelen representarse con números hexadecimales. Gráficamente, se puede
representar de la siguiente manera:

El operador dirección (&) entra dentro de la categoría de operadores monarios y,


siguiendo con el ejemplo, de la evaluación de la expresión
&numero
se obtiene el valor 0012FF88, que es la dirección de memoria de la variable numero.
Esa dirección la necesita conocer la función scanf para localizar la primera celda del
espacio de memoria en donde se va a almacenar el 5 introducido por el usuario.
La dirección de memoria de la variable numero se puede visualizar en pantalla
escribiendo

printf ( "%p", &numero );

Puesto que, de la expresión &numero se obtiene una dirección de memoria, en la


cadena de control de la función printf se tiene que escribir el especificador de formato
asociado a la salida de una dirección de memoria, (%p).
Obsérvese que, en la cadena de control de printf, se ha eludido escribir con tilde la
palabra numero, ya que, de haberlo hecho, por pantalla hubiesemos visto algo parecido
a:
Introduzca un n·mero entero: 5

Para visualizar el carácter 'ú', podemos escribir:

printf( "\n Introduzca un n%cmero entero: ", 163 );

Fíjese que, 163 es el número decimal que corresponde al carácter 'ú' en ASCII.

Ejemplo 2: (ejemplo_11_41.c del libro) Ahora, estudiemos el siguiente programa:

#include <math.h>
#include <stdio.h>

#define PI 3.141592

int main()
{
float area, radio;

printf( "\n Introduzca radio: " );


scanf( "%f", &radio );
area = PI * pow( radio, 2 );
printf( "\n El area de la circunferencia es: %f", area );

return 0;
}

Inicialmente, en la memoria se reservará espacio para las dos variables del programa.

Si el usuario teclea, por ejemplo, el valor 3.8 para el radio, en pantalla se visualizará:

Introduzca radio: 3.8

El area de la circunferencia es: 45.364588

La variable radio es de tipo real y, por tanto, en la cadena de control de la función scanf se
tiene que escribir el especificador de formato asociado a la entrada de un número real, (%f).
Y, puesto que, en la función printf, el resultado de evaluar la expresión area también es de
tipo real, en su cadena de control hay que escribir, de igual forma, el especificador de formato
asociado a la salida de un número real, (%f).

Para que el área se muestre sólo con dos cifras decimales, es decir, 45.36 en vez de
45.364588, en la cadena de control de la función printf se debe escribir %.2f en vez de %f.

printf( "\n El area de la circunferencia es: %.2f", area );

En pantalla se verá

Introduzca radio: 3.8

El area de la circunferencia es: 45.36

Aunque sólo se muestren dos cifras decimales, en memoria el area seguirá


valiendo 45.364588.

Por otra parte, hemos dicho que, para conocer la dirección de memoria de una variable, se
puede utilizar el operador dirección (&). Pero, esta regla no es general. Por ejemplo, no es
aplicable a las variables (arrays) de tipo cadena.

Ejemplo 3: (ejemplo_11_42.c del libro) Si se desea desarrollar un programa para leer un


nombre de persona

Introduzca nombre: Elsa

se puede escribir

#include <stdio.h>

int main()
{
char nombre[5];

printf( "\n Introduzca nombre: " );


scanf( "%s", nombre );

return 0;
}

Obsérvese que, a la función scanf se le "pasa" nombre en vez de &nombre. Esto es así, ya
que, para las variables de tipo cadena (arrays de caracteres), su propio identificador (nombre,
en este caso) ya hace referencia a la dirección de memoria donde se va a almacenar el dato.
Más concretamente, hace referencia al espacio reservado en memoria para guardar el primer
carácter de la cadena. Para el resto de caracteres de la cadena, el sistema habrá reservado, en
memoria, espacios contiguos al primero.
Nótese que, la variable nombre ha sido declarada con un tamaño de cinco caracteres. Por
consiguiente, con este programa sólo se podrá almacenar en memoria un nombre de persona
de hasta cuatro caracteres, ya que, en el quinto debe guardarse el carácter nulo (\0).
1.10 Comentarios en lenguaje C
En lenguaje C, los comentarios se escriben entre los caracteres barra-asterisco (/*) y asterisco-
barra (*/).

Ejemplo (ejemplo_11_43.c del libro): Al código fuente del ejemplo_11_41 se le pueden


añadir los siguientes comentarios:

/*********************************************/
/* Programa: Area_de_una_circunferencia */
/* */
/* Descripción: Recibe por teclado el radio */
/* de una circunferencia, mostrando su área */
/* por pantalla. */
/* */
/* Autor: Carlos Pes */
/* */
/* Fecha: 31/03/2005 */
/*********************************************/

#include <math.h>
#include <stdio.h>

#define PI 3.141592 /* Definición de una constante */

int main()
{
/* Variables del programa */

float area, radio;

printf( "\n Introduzca radio: " );


scanf( "%f", &radio ); /* Entrada de dato */

/* Cálculo del área de la circunferencia */

area = PI * pow( radio, 2 );

/* Salida por pantalla del resultado */


printf( "\n El area de la circunferencia es: %f", area );

return 0;
}

Los comentarios serán ignorados por el compilador y, por tanto, su presencia en el código
fuente es, meramente, informativa.
1.11 La función fflush
Ejemplo 1 (ejemplo_11_44.c del libro): Si ejecutamos el siguiente programa:

#include <stdio.h>

int main()
{
int a, b;

printf( "Introduzca el primer numero: " );


scanf( "%d", &a );
printf( "Introduzca el segundo numero: " );
scanf( "%d", &b );
printf( "Los valores son: %d, %d ", a, b );

return 0;
}

por pantalla veremos algo parecido a:

Introduzca el primer numero: 76


Introduzca el segundo numero: 45
Los valores son: 76, 45

Obsérvese que, cuando se ejecuta scanf, por ejemplo, en la primera vez

scanf( "%d", &a );

el programa se detiene a la espera de que el usuario teclee el dato de entrada requerido, el


cual es almacenado, temporalmente, en el buffer (memoria intermedia) de la entrada
estándar. Y cuando se pulsa la tecla INTRO, es, en ese momento, cuando a la variable a se le
asigna el valor introducido. Pero, además, se produce un salto de línea automático, de forma
que, después de introducir el número 76, la siguiente instrucción se muestra una línea más
abajo. De igual forma, después de la instrucción

scanf( "%d", &b );

también se produce un salto de línea automático. En este ejemplo todo ha ido muy bien, sin
embargo, se tiene que tener especial cuidado si utilizados scanf para leer caracteres.

Ejemplo 2 (ejemplo_11_45.c del libro): En el siguiente programa:

#include <stdio.h>

int main()
{
char a, b, c;

printf( "Introduzca primer caracter: " );


scanf( "%c", &a );
printf( "Introduzca segundo caracter: " );
scanf( "%c", &b );
printf( "Introduzca tercer caracter: " );
scanf( "%c", &c );
printf( "Los valores son: %c, %c, %c ", a, b, c );

return 0;
}

por pantalla se verá algo similar a:

Introduzca primer caracter: f


Introduzca segundo caracter: Introduzca tercer caracter: h
Los valores son: f,
, h

En esta ocasión, ¿por qué no se ejecuta, correctamente, la siguiente instrucción?

scanf( "%c", &b );

La razón es la siguiente: cuando se ejecuta la primera instrucción de entrada

scanf( "%c", &a );

después de asignar el carácter 'f' a la variable a, se produce un salto de línea automático, pero,
en el buffer del teclado también se ha quedado almacenada la secuencia de escape (\n), que
es, precisamente, un carácter. En consecuencia, cuando se ejecuta la instrucción

scanf( "%c", &b );

a la variable b se le asigna el salto de línea almacenado en el buffer de la entrada estándar, y la


ejecución del programa continua con la siguiente instrucción. Ahora, el buffer vuelve a estar
vacío y, por tanto, la entrada de la variable c sí que se ejecuta de forma correcta.

Para comprobar que esto es así, podemos sustituir la instrucción

printf( "Los valores son: %c, %c, %c ", a, b, c );

por esta otra:

printf( "Los valores son: %d, %d, %d ", a, b, c );

En pantalla veremos:

Introduzca primer caracter: f


Introduzca segundo caracter: Introduzca tercer caracter: h
Los valores son: 102, 10, 104
y como se puede comprobar en las tablas del ASCII, los números 102, 10 y 104 corresponden
a los caracteres 'f', LF (Salto de Línea) y 'h', respectivamente.

Para resolver este problema, antes de leer un carácter con scanf, hay que vaciar (limpiar) el
buffer del teclado. Para ello, se utiliza la función fflush.

Ejemplo 3 (ejemplo_11_46.c del libro): De forma que, el código quedaría de la siguiente


manera:

#include <stdio.h>

int main()
{
char a, b, c;

printf( "Introduzca primer caracter: " );


scanf( "%c", &a );
printf( "Introduzca segundo caracter: " );
fflush( stdin );
scanf( "%c", &b );
printf( "Introduzca tercer caracter: " );
fflush( stdin );
scanf( "%c", &c );
printf( "Los valores son: %c, %c, %c ", a, b, c );

return 0;
}

La primera vez que se ejecuta scanf, el buffer del teclado está vacío, por tanto, no es preciso
utilizar fflush, pero sí, en los dos casos posteriores. Obsérvese que, a fflush hay que indicarle
el buffer a limpiar, Standar Input (stdin) en este caso.
1.12 Tipos de errores
Una vez escrito el código fuente de un programa, siempre se debe comprobar si se han
cometido errores. Estos pueden ser de tres tipos:

 De sintaxis (sintácticos).
 De ejecución.
 De lógica (lógicos).
1.12.1 Errores de sintaxis
Los errores de sintaxis son los más fáciles de detectar. Un error de sintaxis se produce al
escribir, incorrectamente, alguna parte del código.

Ejemplo (ejemplo_11_47.c del libro): Estúdiese el siguiente código fuente de un programa


escrito en lenguaje C:

include <stdio.h>

imt main()
{
int a, b;
a = 4;
b = a * 6;

printf( "%d", b )

retunr 0;
}

Existen cuatro errores de sintaxis:

1. Se ha escrito include en vez de #include.


2. Se ha escrito imt en vez de int.
3. Falta un punto y coma (;) después de la llamada a printf.
4. Se ha escrito retunr en vez de return.
1.12.2 Errores de ejecución
Una vez corregidos los errores de sintaxis, se debe revisar que no se puede producir ningún
error en la ejecución del programa. Un error de ejecución se produce cuando el ordenador
no puede ejecutar alguna instrucción de forma correcta.

Ejemplo (ejemplo_11_48.c del libro): En el programa:

#include <stdio.h>

int main()
{
int a;
float b;

a = 0;
b = 6.4 / a;

printf( "%f", b );

return 0;
}

5.
se produce un error de ejecución, ya que, al intentar evaluar la expresión

6.4 / a

a vale 0, y no se puede dividir entre cero.


1.12.3 Errores de lógica
Los errores de lógica son los más difíciles de detectar. Cuando un programa no tiene errores de
sintaxis ni de ejecución, pero, aún así, no funciona bien, esto es debido a la existencia de algún
error lógico. De manera que, un error de lógica se produce cuando los resultados obtenidos no
son los esperados.

Ejemplo (ejemplo_11_49.c del libro): Estúdiese el siguiente código:

#include <stdio.h>

int main()
{
float base, altura;

base = 6.3;
altura = 4.;

printf( "El area es: %f", base * altura / 3 );

return 0;
}

Su salida por pantalla es:

El area es: 8.4

No existen errores de sintaxis ni de ejecución, sin embargo, la salida esperada es:

El area es: 12.6

Por consiguiente, existe algún error lógico que hay que corregir. El error está en la expresión

base * altura / 3

que, aunque no es incorrecta, no sirve para calcular el área de un triángulo. En su lugar se


debe escribir

base * altura / 2
2.1 Alternativa doble ( la instrucción if )
En lenguaje C, para escribir una instrucción alternativa doble se utiliza la sintaxis:

if ( <expresión_lógica> )
{
<bloque_de_instrucciones_1>
}
else
{
<bloque_de_instrucciones_2>
}

A la <expresión_lógica> de una instrucción alternativa doble también se le denomina condición.

Para que se ejecute el <bloque_de_instrucciones_1>, la condición tiene que ser verdadera. Por
el contrario, si la condición es falsa, se ejecutará el <bloque_de_instrucciones_2>.

En resumen, una instrucción alternativa doble (o simplemente alternativa doble) permite seleccionar,
por medio de una condición, el siguiente bloque de instrucciones a ejecutar, de entre dos posibles.

Ejemplo: Se quiere escribir un programa que:


1º) Pida por teclado la nota (dato real) de una asignatura.
2º) Muestre por pantalla:

 "APROBADO", en el caso de que la nota sea mayor o igual que 5.


 "SUSPENDIDO", en el caso de que la nota sea menor que 5.
De modo que, por pantalla se verá, por ejemplo:

Introduzca nota (real): 7.5

APROBADO

Otra posibilidad es:

Introduzca nota (real): 3.5


SUSPENDIDO

Cuando un bloque de instrucciones sólo contiene una instrucción, los caracteres abrir llave ({) y cerrar
llave (}) son opcionales. Por tanto, en lenguaje C, para resolver el problema del ejemplo se puede
escribir:

#include <stdio.h>

int main()
{
float nota;
printf( "\n Introduzca nota (real): " );
scanf( "%f", &nota );

if ( nota >= 5 )
printf( "\n APROBADO" );
else
printf( "\n SUSPENDIDO" );

return 0;
}
Programa (.c): Calificación según nota (Versión 1)

Cuando en el código fuente de un programa existe una condición de la cual depende que a continuación
se ejecuten unas instrucciones u otras, se dice que existe una bifurcación.
2.2 Alternativa simple ( de nuevo la instrucción if )
Una instrucción alternativa simple (o simplemente alternativa simple) es una variante (más sencilla)
de una instrucción alternativa doble. En lenguaje C, para escribir una alternativa simple se utiliza la
sintaxis:

if ( <expresión_lógica> )
{
<bloque_de_instrucciones>
}

Ejemplo: Se quiere escribir un programa que:


1º) Pida por teclado la nota (dato real) de una asignatura.
2º) Muestre por pantalla:

 "APROBADO", en el caso de que la nota sea mayor o igual que 5.

Introduzca nota (real): 7.5

APROBADO

Obsérvese que, en este problema, no se va a mostrar por pantalla "SUSPENDIDO" en el caso de que la
nota sea menor que 5, como sí se hacía en el problema del apartado anterior.

Introduzca nota (real): 3.5

Al igual que ocurre con una instrucción alternativa doble, cuando el <bloque_de_instrucciones>
de una alternativa simple sólo contiene una instrucción, los caracteres abrir llave ({) y cerrar llave (})
también son opcionales. De modo que, para resolver el problema del ejemplo se puede escribir:

#include <stdio.h>

int main()
{
float nota;

printf( "\n Introduzca nota (real): " );


scanf( "%f", &nota );

if ( nota >= 5 )
printf( "\n APROBADO" );

return 0;
}
Programa (.c): Calificación según nota (Versión 2)

2.3 Alternativa múltiple ( la instrucción switch )


Una instrucción alternativa múltiple (o simplemente alternativa múltiple) permite seleccionar, por
medio de una expresión, el siguiente bloque de instrucciones a ejecutar de entre varios posibles. En
lenguaje C, para escribir una alternativa múltiple se utiliza la sintaxis:

switch ( <expresión> )
{
case <expresión_1> : [ <bloque_de_instrucciones_1> ]
[ break; ]
case <expresión_2> : [ <bloque_de_instrucciones_2> ]
[ break; ]
...
case <expresión_n> : [ <bloque_de_instrucciones_n> ]
[ break; ]
[ default : <bloque_de_instrucciones_n+1> ]
}

El resultado de evaluar la <expresión> debe ser un valor perteneciente a un tipo de dato finito y
ordenado, es decir, entero, lógico, carácter, enumerado o subrango.

Dependiendo del valor obtenido al evaluar la <expresión>, se ejecutará un bloque de instrucciones u


otro.

Opcionalmente, se puede escribir un <bloque_de_instrucciones_n+1> después de default


:. Este bloque de instrucciones se ejecutará en el caso de que el valor obtenido al evaluar la
<expresión>, no se encuentre en ninguna de las expresiones después de cada case.

Ejemplo 1: Se quiere escribir un programa que:


1º) Pida por teclado el número (dato entero) de un día de la semana.
2º) Muestre por pantalla el nombre (dato cadena) correspondiente a dicho día.

Nota: Si el número de día introducido es menor que 1 ó mayor que 7, se mostrará el mensaje: "ERROR:
Día incorrecto.".

En pantalla:

Introduzca dia de la semana: 2

Martes
Introduzca dia de la semana: 9
ERROR: Dia incorrecto.

Solución propuesta:

#include <stdio.h>

int main()
{
int dia;

printf( "\n Introduzca dia de la semana: " );


scanf( "%d", &dia );

switch ( dia )
{
case 1 : printf( "\n Lunes" );
break;
case 2 : printf( "\n Martes" );
break;
case 3 : printf( "\n Miercoles" );
break;
case 4 : printf( "\n Jueves" );
break;
case 5 : printf( "\n Viernes" );
break;
case 6 : printf( "\n Sabado" );
break;
case 7 : printf( "\n Domingo" );
break;
default : printf( "\n ERROR: Dia incorrecto." );
}

return 0;
}
Programa (.c): Día de la semana

En la sintaxis de una instrucción alternativa múltiple, obsérvese que, después de cada bloque de
instrucciones se puede escribir, opcionalmente, la instrucción break. Dicha instrucción no se va a
estudiar con detenimiento en este apartado, ya que, de momento, basta con saber que en una
instrucción switch, la escribiremos, casi siempre, después de cada bloque de instrucciones, a excepción
del último. Para comprender su funcionamiento, pruebe a ver que ocurre si omite algún break en el
código del programa del ejemplo 1.

Estúdiese también el siguiente ejemplo.

Ejemplo 2: En la siguiente tabla se muestran las categorías a las que pertenecen los signos del zodíaco:
Se quiere escribir un programa que:
1º) Muestre el listado de los signos del zodíaco, con sus números asociados.
2º) Pida por teclado un número (dato entero) asociado a un signo del zodíaco.
3º) Muestre la categoría a la que pertenece el signo del zodíaco seleccionado.

Nota: Si el número introducido por el usuario, no está asociado a ningún signo del zodíaco, se mostrará el
mensaje: "ERROR: <número> no está asociado a ningún signo.".

En pantalla:

Listado de signos del zodiaco:

1. Aries
2. Tauro
3. Geminis
4. Cancer
5. Leo
6. Virgo
7. Libra
8. Escorpio
9. Sagitario
10. Capricornio
12. Acuario
13. Piscis

Introduzca numero de signo: 7

Es un signo de Aire.
Listado de signos del zodiaco:

1. Aries
2. Tauro
3. Geminis
4. Cancer
5. Leo
6. Virgo
7. Libra
8. Escorpio
9. Sagitario
10. Capricornio
12. Acuario
13. Piscis

Introduzca numero de signo: 15

ERROR: 15 no esta asociado a ningun signo.

Una posible solución es:

#include <stdio.h>

int main()
{
int numero;

printf( "\n Listado de signos del zodiaco:" );


printf( "\n\n 1. Aries" );
printf( "\n 2. Tauro" );
printf( "\n 3. Geminis" );
printf( "\n 4. Cancer" );
printf( "\n 5. Leo" );
printf( "\n 6. Virgo" );
printf( "\n 7. Libra" );
printf( "\n 8. Escorpio" );
printf( "\n 9. Sagitario" );
printf( "\n 10. Capricornio" );
printf( "\n 11. Acuario" );
printf( "\n 12. Piscis" );
printf( "\n\n Introduzca numero de signo: " );

scanf( "%d", &numero );

switch ( numero )
{
case 1 :
case 5 :
case 9 : printf( "\n Es un signo de Fuego." );
break;
case 2 :
case 6 :
case 10 : printf( "\n Es un signo de Tierra." );
break;
case 3 :
case 7 :
case 11 : printf( "\n Es un signo de Aire." );
break;
case 4 :
case 8 :
case 12 : printf( "\n Es un signo de Agua." );
break;
default : printf( "\n ERROR: %d no esta asociado a ningun
signo.", numero );
}

return 0;
}
Programa (.c): Signo del zodíaco (Solución 1)

Otra solución es:

#include <stdio.h>
#include <string.h>

int main()
{
int numero;
char categoria[7];

printf( "\n Listado de signos del zodiaco:" );


printf( "\n\n 1. Aries" );
printf( "\n 2. Tauro" );
printf( "\n 3. Geminis" );
printf( "\n 4. Cancer" );
printf( "\n 5. Leo" );
printf( "\n 6. Virgo" );
printf( "\n 7. Libra" );
printf( "\n 8. Escorpio" );
printf( "\n 9. Sagitario" );
printf( "\n 10. Capricornio" );
printf( "\n 11. Acuario" );
printf( "\n 12. Piscis" );
printf( "\n\n Introduzca numero de signo: " );

scanf( "%d", &numero );

switch ( numero % 4 )
{
case 1 : strcpy( categoria, "Fuego" );
break;
case 2 : strcpy( categoria, "Tierra" );
break;
case 3 : strcpy( categoria, "Aire" );
break;
case 0 : strcpy( categoria, "Agua" );
}

if ( numero >= 1 && numero <= 12 )


printf( "\n Es un signo de %s.", categoria );
else
printf( "\n ERROR: %d no esta asociado a ningun signo.",
numero );

return 0;
}
Programa (.c): Signo del zodíaco (Solución 2)

En esta segunda solución existen las siguientes diferencias importantes con respecto a la solución
anterior:

 En el código se utiliza una alternativa doble (if), además de una alternativa múltiple (switch).
 En la alternativa múltiple no se escribe el <bloque_de_instrucciones_n+1>.
 La <expresión> de la alternativa múltiple es diferente.
 La expresión "\n Es un signo de " sólo se escribe una vez.
 Se ha utilizado una variable más (un array de caracteres): categoria
 Se ha empleado la función strcpy, que, como ya vimos en el apartado 1.8 Operadores y
expresiones, está disponible en la biblioteca estándar de C.
2.4 Anidamiento
Las instrucciones alternativas y repetitivas pueden escribirse una dentro de otra. A este hecho se le conoce
como anidamiento.

Las instrucciones alternativas permiten realizar las siguientes combinaciones de anidamiento:

 Doble en doble.
 Doble en simple.
 Doble en múltiple.
 Simple en simple.
 Simple en doble.
 Simple en múltiple.
 Múltiple en múltiple.
 Múltiple en doble.
 Múltiple en simple.
De ellas, vamos a estudiar, como ejemplo, las siguientes combinaciones:

 Doble en doble.
 Múltiple en doble.
2.4.1 Alternativa doble en doble
En lenguaje C, para anidar una alternativa doble en otra, se utiliza la sintaxis:

if ( <expresión_lógica_1> )
{

/* Inicio del anidamiento */


if ( <expresión_lógica_2> )
{
<bloque_de_instrucciones_1>
}
else
{
<bloque_de_instrucciones_2>
}
/* Fin del anidamiento */

}
else
{
<bloque_de_instrucciones_3>
}

O también:

if ( <expresión_lógica_1> )
{
<bloque_de_instrucciones_1>
{
else
{

/* Inicio del anidamiento */


if ( <expresión_lógica_2> )
{
<bloque_de_instrucciones_2>
}
else
{
<bloque_de_instrucciones_3>
}
/* Fin del anidamiento */

Ejemplo: Se quiere escribir un programa que:


1º) Pida por teclado la nota (real) de una asignatura.
2º) Muestre por pantalla:

 "APTO", en el caso de que la nota sea mayor o igual que 5 y menor o igual que 10.
 "NO APTO", en el caso de que la nota sea mayor o igual que 0 y menor que 5.
 "ERROR: Nota incorrecta.", en el caso de que la nota sea menor que 0 o mayor que 10.
En pantalla:

Introduzca nota (real): 7.5

APTO

Introduzca nota (real): 12.2


ERROR: Nota incorrecta.

Una solución al problema es:

#include <stdio.h>

int main()
{
float nota;

printf( "\n Introduzca nota (real): " );


scanf( "%f", &nota );

if ( nota >= 5 && nota <= 10 )


printf( "\n APTO" );
else

/* Inicio del anidamiento */


if ( nota >= 0 && nota < 5 )
printf( "\n NO APTO" );
else
printf( "\n ERROR: Nota incorrecta." );
/* Fin del anidamiento */

return 0;
}
Programa (.c): Calificación según nota (Versión 3)

Fíjese que, en este caso, se puede prescindir de los caracteres abrir llave ({) y cerrar llave (}) de la
sintaxis, ya que, los bloques de instrucciones sólo contienen una instrucción.

Como se puede observar, el anidamiento de instrucciones alternativas permite ir descartando valores hasta
llegar al bloque de instrucciones que se debe ejecutar.

2.4.2 Alternativa múltiple en doble


En lenguaje C, para anidar una alternativa múltiple en una alternativa doble, se utiliza la sintaxis:

if ( <expresión_lógica> )
{

/* Inicio del anidamiento */


switch ( <expresión> )
{
case <expresión_1> : [ <bloque_de_instrucciones_1> ]
[ break; ]
case <expresión_2> : [ <bloque_de_instrucciones_2> ]
[ break; ]
...
case <expresión_n> : [ <bloque_de_instrucciones_n> ]
[ break; ]
[ default : <bloque_de_instrucciones_n+1> ]
}
/* Fin del anidamiento */
}
else
{
<bloque_de_instrucciones_n+2>
}

Ejemplo: Así por ejemplo, el primer ejemplo del apartado 2.3 Alternativa múltiple, también se puede
resolver anidando una alternativa múltiple en una alternativa doble.

#include <stdio.h>

int main()
{
int dia;

printf( "\n Introduzca dia de la semana: " );


scanf( "%d", &dia );

if ( dia >= 1 && dia <= 7 )

/* Sólo si el día es válido, se ejecuta la


instrucción alternativa múltiple */

/* Inicio del anidamiento */


switch ( dia )
{
case 1 : printf( "\n Lunes" );
break;
case 2 : printf( "\n Martes" );
break;
case 3 : printf( "\n Miercoles" );
break;
case 4 : printf( "\n Jueves" );
break;
case 5 : printf( "\n Viernes" );
break;
case 6 : printf( "\n Sabado" );
break;
case 7 : printf( "\n Domingo" );
}
/* Fin del anidamiento */

else
printf( "\n ERROR: Dia incorrecto." );

return 0;
}
Programa (.c): Día de la semana (Alternativa múltiple en doble)

3.1 Repetitiva mientras ( la instrucción while )


En lenguaje C, para escribir una instrucción repetitiva mientras se utiliza la sintaxis:

while ( <expresión_lógica> )
{
<bloque_de_instrucciones>
}

Cuando el <bloque_de_instrucciones> sólo contiene una instrucción, los caracteres abrir llave
({) y cerrar llave (}) son opcionales.

Por otra parte, al igual que en las instrucciones alternativas doble y simple, a la
<expresión_lógica> de una instrucción repetitiva while, también se le llama condición.

Para que se ejecute el <bloque_de_instrucciones>, la condición tiene que ser verdadera. Por el
contrario, si la condición es falsa, el <bloque_de_instrucciones> no se ejecuta.

Por tanto, cuando el flujo de un programa llega a un bucle while, existen dos posibilidades:

1. Si la condición se evalúa a falsa, el bloque de instrucciones no se ejecuta, y el bucle while


finaliza sin realizar ninguna iteración.
2. Si la condición se evalúa a verdadera, el bloque de instrucciones sí que se ejecuta y, después, se
vuelve a evaluar la condición, para decidir, de nuevo, si el bloque de instrucciones se vuelve a
ejecutar o no. Y así sucesivamente, hasta que, la condición sea falsa.
El <bloque_de_instrucciones> de un bucle while puede ejecutarse cero o más veces
(iteraciones). Si el <bloque_de_instrucciones> se ejecuta al menos una vez, seguirá
ejecutándose repetidamente, mientras que, la condición sea verdadera. Pero, hay que tener cuidado de
que el bucle no sea infinito.

Cuando la condición de un bucle while se evalúa siempre a verdadera, se dice que se ha producido un
bucle infinito, ya que, el programa nunca termina. Un bucle infinito es un error lógico.

Es importante hacer hincapié en el hecho de que, en un bucle while, primero se evalúa la condición y,
en el caso de que ésta sea verdadera, entonces se ejecuta el bloque de instrucciones. Veremos que, en el
bucle do...while, el procedimiento es al revés. En él, primero se ejecuta el bloque de instrucciones y,
después, se evalúa la condición.

Para que un bucle while no sea infinito, en el bloque de instrucciones debe ocurrir algo para que la
condición deje de ser verdadera. En la mayoría de los casos, la condición se hace falsa al cambiar el
valor de una variable.

En resumen, una instrucción repetitiva while permite ejecutar, repetidamente, (cero o más veces) un
bloque de instrucciones, mientras que, una determinada condición sea verdadera.

Ejemplo 1: Se quiere escribir un programa que muestre por pantalla los primeros diez números naturales:

1 2 3 4 5 6 7 8 9 10

En lenguaje C, para resolver el problema de este ejemplo se puede escribir:

#include <stdio.h>

int main()
{
int contador;

printf( "\n " );


contador = 1; /* Inicialización del contador */
while ( contador <= 10 ) /* Condición */
{
printf( "%d ", contador ); /* Salida */
contador++; /* Incremento del contador */
}

return 0;
}
Programa (.c): Números del 1 al 10 (while)

Ejemplo 2: Se quiere escribir un programa que:


1º) Pida por teclado la nota (dato real) de una asignatura.
2º) En el caso de que la nota sea incorrecta, muestre por pantalla el mensaje:

 "ERROR: Nota incorrecta, debe ser >= 0 y <= 10".


3º) Repita los pasos 1º y 2º, mientras que, la nota introducida sea incorrecta.
4º) Muestre por pantalla:

 "APROBADO", en el caso de que la nota sea mayor o igual que 5.


 "SUSPENDIDO", en el caso de que la nota sea menor que 5.
En pantalla:

Introduzca nota (real): 12.4

ERROR: Nota incorrecta, debe ser >= 0 y <= 10

Introduzca nota (real): -3.3

ERROR: Nota incorrecta, debe ser >= 0 y <= 10

Introduzca nota (real): 8.7


APROBADO

El código propuesto es:

#include <stdio.h>

int main()
{
float nota;

printf( "\n Introduzca nota (real): " );


scanf( "%f", &nota );

/* Si la primera nota introducida por el


usuario es correcta,
el bucle no itera ninguna vez. */

while ( nota < 0 || nota > 10 )


{
printf( "\n ERROR: Nota incorrecta, debe ser >= 0 y <= 10\n"
);
printf( "\n Introduzca nota (real): " );
scanf( "%f", &nota );
}

/* Mientras que el usuario introduzca una


nota incorrecta, el bucle iterará.
Y cuando introduzca una nota correcta,
el bucle finalizará. */

if ( nota >= 5 )
printf( "\n APROBADO" );
else
printf( "\n SUSPENDIDO" );

return 0;
}
Programa (.c): Calificación según nota

En el programa, el bucle while se ha usado para validar la nota introducida por el usuario. En
programación, es muy frecuente usar el bucle while para validar (filtrar) datos. Al bucle que se utiliza
para validar uno o más datos, también se le conoce como filtro.

3.2 Repetitiva hacer...mientras ( la instrucción do...while )


En lenguaje C, para escribir una instrucción repetitiva hacer...mientras se utiliza la sintaxis:

do
{
<bloque_de_instrucciones>
} while ( <expresión_lógica> );

Cuando el <bloque_de_instrucciones> sólo contiene una instrucción, los caracteres abrir llave
({) y cerrar llave (}) son opcionales.

Además, como se puede apreciar, la instrucción repetitiva do...while, también hace uso de una
condición.

En un bucle do...while, primero se ejecuta el bloque de instrucciones y, después, se evalúa la


condición. En el caso de que ésta sea verdadera, se vuelve a ejecutar el bloque de instrucciones. Y así
sucesivamente, hasta que, la condición sea falsa.

Por consiguiente, cuando el flujo de un programa llega a un bucle do...while, existen dos
posibilidades:

1. Se ejecuta el bloque de instrucciones y, después, si la condición se evalúa a falsa, el bloque de


instrucciones no se vuelve a ejecutar, de manera que, el bucle do...while finaliza, habiendo
realizado una sola iteración.
2. Se ejecuta el bloque de instrucciones y, a continuación, si la condición se evalúa a verdadera, el
bloque de instrucciones se vuelve a ejecutar. Y así sucesivamente, hasta que la condición sea
falsa.
El <bloque_de_instrucciones> de un bucle do...while puede ejecutarse una o más veces
(iteraciones). También hay que prevenir que el bucle no sea infinito.
En resumen, una instrucción repetitiva do...while permite ejecutar repetidamente (una o más veces)
un bloque de instrucciones, mientras que, una determinada condición sea verdadera.

Ejemplo 1: De modo que, utilizando un bucle do...while, el problema del ejemplo 1 del apartado
anterior, 3.1 Repetitiva mientras, se puede resolver con el código:

#include <stdio.h>

int main()
{
int contador;

printf( "\n " );

contador = 1; /* Inicialización del contador */


do
{
printf( "%d ", contador ); /* Salida */
contador++; /* Incremento */
} while ( contador <= 10 ); /* Condición */

return 0;
}
Programa (.c): Números del 1 al 10 (do...while)

Como ya se ha dicho, el bucle do...while puede iterar una o más veces, por tanto, cuando un bloque
de instrucciones debe iterar al menos una vez, generalmente, es mejor utilizar un bucle do...while
que un bucle while, como por ejemplo, en el siguiente problema.

Ejemplo 2: Se quiere escribir un programa que:


1º) Pida por teclado un número (dato entero).
2º) Pregunte al usuario si desea introducir otro o no.
3º) Repita los pasos 1º y 2º, mientras que, el usuario no responda 'n' de (no).
4º) Muestre por pantalla la suma de los números introducidos por el usuario.

En pantalla:

Introduzca un numero entero: 7

¿Desea introducir otro (s/n)?: s


Introduzca un numero entero: 16

¿Desea introducir otro (s/n)?: s

Introduzca un numero entero: -3


¿Desea introducir otro (s/n)?: n

La suma de los numeros introducidos es: 20

El código propuesto es:

#include <stdio.h>
int main()
{
char seguir;
int acumulador, numero;

/* En acumulador se va a guardar la suma de


los números introducidos por el usuario. */

acumulador = 0;
do
{
printf( "\n Introduzca un numero entero: " );
scanf( "%d", &numero);

acumulador += numero;

printf( "\n Desea introducir otro numero (s/n)?: " );


fflush( stdin );
scanf( "%c", &seguir);
} while ( seguir != 'n' );

/* Mientras que el usuario desee introducir


más números, el bucle iterará. */

printf( "\n La suma de los numeros introducidos es: %d",


acumulador );

return 0;
}
Programa (.c): Suma de números introducidos por el usuario

3.3 Repetitiva para ( la instrucción for )


En lenguaje C, para escribir una instrucción repetitiva para se utiliza la sintaxis:

for ( <expresión_1> ; <expresión_2> ; <expresión_3> )


{
<bloque_de_instrucciones>
}

Cuando el <bloque_de_instrucciones> sólo contiene una instrucción, los caracteres abrir llave
({) y cerrar llave (}) son opcionales.

Por otro lado, el bucle for es ideal usarlo cuando, de antemano, ya se sabe el número de veces
(iteraciones) que tiene que ejecutarse un determinado bloque de instrucciones.

El bucle para es una variante del bucle mientras y, al igual que éste, puede iterar cero o más veces
(véase el apartado 10.1 Repetitiva mientras, del Curso de Diseño de Algoritmos). Sin embargo, el
bucle for sólo se suele usar cuando se conoce el número exacto de veces que tiene que iterar el bucle.
Éste es el caso del problema planteado en el ejemplo 1 del apartado 3.1 Repetitiva mientras, en el cual,
se sabe de antemano que el bucle tiene que iterar, exactamente, diez veces.

Ejemplo: Por tanto, dicho problema, se puede resolver con una instrucción repetitiva for de la siguiente
forma:
#include <stdio.h>

int main()
{
int contador;

printf( "\n " );

for ( contador=1 ; contador<=10 ; contador++ )


printf( "%d ", contador );

return 0;
}
Programa (.c): Números del 1 al 10 (for)

En este caso, <expresión_1>, <expresión_2> y <expresión_3>, se corresponden,


respectivamente, con:

 la inicialización de la variable contador,


 la condición de salida del bucle y
 el incremento de la variable contador
de una instrucción repetitiva mientras.

3.3.1 ¿Cuándo usar un bucle u otro?


En programación, a la hora de elegir un bucle u otro, debemos hacernos la siguiente pregunta:

 ¿Se conoce, de antemano, el número de veces (iteraciones) que tiene que ejecutarse un
determinado bloque de instrucciones?
Si la respuesta es afirmativa, habitualmente se usa un bucle for. En caso contrario, nos plantearemos la
siguiente pregunta:
 ¿El bloque de instrucciones debe ejecutarse al menos una vez?
En este caso, si la respuesta es afirmativa, generalmente haremos uso de un bucle do...while, y si la
respuesta es negativa, usaremos un bucle while.
3.4 Anidamiento
Al igual que las instrucciones alternativas, las instrucciones repetitivas también se pueden anidar,
permitiendo las siguientes combinaciones de anidamiento:

 while en while
 while en do...while
 while en for
 do...while en do...while
 do...while en for
 do...while en while
 for en for
 for en while
 for en do...while
De ellas, vamos a estudiar, como ejemplo, la combinación:

 for en do...while

Por otro lado, las instrucciones alternativas y repetitivas también se pueden anidar entre sí, permitiendo
realizar 18 combinaciones más de anidamiento:

 while en doble
 while en simple
 while en múltiple

 do...while en doble
 do...while en simple
 do...while en múltiple

 for en doble
 for en simple
 for en múltiple

 Doble en while
 Doble en do...while
 Doble en for

 Simple en while
 Simple en do...while
 Simple en for
 Múltiple en while
 Múltiple en do...while
 Múltiple en for
De ellas, vamos a estudiar, como ejemplo, la combinación:

 Simple en for.
3.4.1 Bucle for en do...while

 En lenguaje C, para anidar un bucle for en un bucle do...while, se utiliza la sintaxis:

do
{

/* Inicio del anidamiento */


for ( <expresión_1> ; <expresión_2> ; <expresión_3> )
{
<bloque_de_instrucciones>
}
/* Fin del anidamiento */

} while ( <expresión_lógica> );


Ejemplo: Se quiere escribir un programa que muestre por pantalla la tabla de multiplicar de un
número entero introducido por el usuario. El proceso debe repetirse mientras que el usuario lo
desee:

Introduzca un numero entero: 7

La tabla de multiplicar del 7 es:

7 * 1 = 7
7 * 2 = 14
7 * 3 = 21
7 * 4 = 28
7 * 5 = 35
7 * 6 = 42
7 * 7 = 49
7 * 8 = 56
7 * 9 = 63
7 * 10 = 70
¿Desea ver otra tabla (s/n)?: s

Introduzca un numero entero: -12

La tabla de multiplicar del -12 es:


-12 * 1 = -12
-12 * 2 = -24
-12 * 3 = -36
-12 * 4 = -48
-12 * 5 = -60
-12 * 6 = -72
-12 * 7 = -84
-12 * 8 = -96
-12 * 9 = -108
-12 * 10 = -120
¿Desea ver otra tabla (s/n)?: n


En lenguaje C, para resolver este problema se puede escribir:

#include <stdio.h>

int main()
{
char seguir;
int i, numero;

do
{
printf( "\n Introduzca un numero entero: " );
scanf( "%d", &numero );

printf( "\n La tabla de multiplicar del %d es:\n", numero );

/* Inicio del anidamiento */


for ( i = 1 ; i <= 10 ; i++ )
{
printf( "\n %d * %d = %d",
i, numero, i * numero );
}
/* Fin del anidamiento */

printf( "\n\n Desea ver otra tabla (s/n)?: " );


fflush( stdin );
scanf( "%c", &seguir );

} while ( seguir != 'n' );

return 0;
}

 Programa (.c): Tabla de multiplicar de un número (for en do...while)

3.4.2 Alternativa simple en bucle for


En lenguaje C, para anidar una alternativa simple en un bucle for, se utiliza la sintaxis:

for ( <expresión_1> ; <expresión_2> ; <expresión_3> )


{

/* Inicio del anidamiento */


if ( <expresión_lógica> )
{
<bloque_de_instrucciones>
}
/* Fin del anidamiento */

}
Ejemplo: Se quiere escribir un programa que muestre por pantalla todos los números enteros del 1 al 100
(ambos inclusive) que sean divisibles entre 17 ó 21:

17 21 34 42 51 63 68 84 85

Anidando una alternativa simple en un bucle for, el problema se puede resolver con el código:

#include <stdio.h>

int main()
{
int numero;

printf( "\n " );

for ( numero = 1 ; numero <= 100 ; numero++ )


{

/* Inicio del anidamiento */


if ( numero % 17 == 0 || numero % 21 == 0 )
printf( "%d ", numero );
/* Fin del anidamiento */

return 0;
}
Programa (.c): Números enteros divisibles entre 17 ó 21 (Alternativa simple en for)
4.1 Instrucción break
En lenguaje C, para escribir una instrucción de salto break (interrumpir), se utiliza la sintaxis:

break;

La instrucción de salto break se usa para interrumpir (romper) la ejecución normal de un bucle, es decir,
la instrucción break finaliza (termina) la ejecución de un bucle y, por tanto, el control del programa se
transfiere (salta) a la primera instrucción después del bucle.

Ejemplo 1: Estúdiese el siguiente código fuente:

#include <stdio.h>

int main()
{

int n, a;

a = 0;
do
{
printf( "Introduzca un numero entero: " );
scanf( "%d", &n );

if ( n == 0 )
{
printf( "ERROR: El cero no tiene opuesto.\n" );
break;
/* En el caso de que n sea un cero,
el bucle se interrumpe. */
}
printf( "El opuesto es: %d\n", -n );
a += n;
} while ( n >= -10 && n <= 10 );

printf( "Suma: %d", a );

return 0;
}
Programa (.c): Números opuestos del -10 al 10 (con instrucción break)

El programa puede ser la solución del problema siguiente:

Escriba un programa que:

1º) Pida por teclado un número (dato entero).


2º) Si el número introducido por el usuario es distinto de cero, muestre por pantalla el mensaje:

 "El opuesto es: <-número>".

3º) Repita los pasos 1º y 2º, mientras que, el usuario introduzca un número mayor o igual que -10 y menor
o igual que 10.
Pero, si el usuario introduce un cero, el bucle también finaliza, mostrándose por pantalla el mensaje:

 "ERROR: El cero no tiene opuesto.".

4º) Muestre por pantalla la suma de los números introducidos por el usuario.
En pantalla:

Introduzca un número entero: 15

El opuesto es: -15

Suma: 15

La traza del programa es:

Secuencia: Acción (instrucción): Valor de:


a n
1 a = 0 0 ?
Inicio de la iteración 1.
2 printf( "Introduzca un número entero:" ) 0 ?
3 scanf( "%d",n ) 0 15
4 (Comprobar si n == 0) 0 15
La condición de la alternativa simple (if) es falsa.
5 printf( "El opuesto es: %d\n", -n ) 0 15
6 a += n 15 15
Fin de la iteración 1.
7 (Comprobar si n >= -10 && n <= 10) 15 15
La condición del bucle (do...while) es falsa.
El bucle finaliza después de 1 iteración.
8 printf( "Suma: %d", a ) 15 15

Figura. Traza del ejemplo 1.

El bucle ha finalizado porque la condición ( n >= -10 && n <= 10 ) es falsa, ya que, 15 no es
mayor o igual que -10 y menor o igual que 10.

Sin embargo, el bucle también puede finalizar, no porque sea falsa la condición ( n >= -10 && n
<= 10 ), sino, porque se ejecute la instrucción break. Esto ocurrirá cuando el usuario introduzca un
cero. Por ejemplo:

Introduzca un número entero: 8

El opuesto es: -8

Introduzca un número entero: -7

El opuesto es: 7

Introduzca un número entero: 0

ERROR: El cero no tiene opuesto.

Suma: 1
La traza en este caso es:

Secuencia: Acción (instrucción): Valor de:


a n
1 a = 0 0 ?
Inicio de la iteración 1.
2 printf( "Introduzca un número entero:" ) 0 ?
3 scanf( "%d",n ) 0 8
4 (Comprobar si n == 0) 0 8
La condición de la alternativa simple (if) es falsa.
5 printf( "El opuesto es: %d\n", -n ) 0 8
6 a += n 8 8
Fin de la iteración 1.
7 (Comprobar si n >= -10 && n <= 10) 8 8
La condición del bucle (do...while) es verdadera.
Inicio de la iteración 2.
8 printf( "Introduzca un número entero:" ) 8 8
9 scanf( "%d",n ) 8 -7
10 (Comprobar si n == 0) 8 -7
La condición de la alternativa simple (if) es falsa.
11 printf( "El opuesto es: %d\n", -n ) 8 -7
12 a += n 1 -7
Fin de la iteración 2.
13 (Comprobar si n >= -10 && n <= 10) 1 -7
La condición del bucle (do...while) es verdadera.
Inicio de la iteración 3.
14 printf( "Introduzca un número entero:" ) 1 -7
15 scanf( "%d",n ) 1 0
16 (Comprobar si n == 0) 1 0
La condición de la alternativa simple (if) es verdadera.
17 printf( "ERROR: El cero no tiene opuesto." ) 1 0
18 break 1 0
El bucle (do...while) se interrumpe en la 3ª iteración.
El control del programa se transfiere (salta)
a la primera instrucción después del bucle.
19 printf( "Suma: %d", a ) 1 0

Figura. Traza del ejemplo 1.

Normalmente, cuando en un bucle se utiliza una instrucción break, la ejecución de ésta se condiciona.

En el ejemplo 1, el bucle se interrumpe si la condición ( n == 0 ) es verdadera. Nótese que, dicha


condición no está contemplada en la condición de salida estándar del bucle, por lo que, a la condición
( n == 0 ) se le considera condición de salida interna del bucle.

Ejemplo 2: No obstante, el problema también se puede resolver sin hacer uso de la instrucción break:
#include <stdio.h>

int main()
{

int numero, acumulador;

acumulador = 0;
do
{
printf( "Introduzca un numero entero: " );
scanf( "%d", &numero );

if ( numero == 0 )
{
printf( "ERROR: El cero no tiene opuesto.\n" );
}
else
{
printf( "El opuesto es: %d\n", -numero );
acumulador += numero;
}

} while ( numero >= -10 && numero <= 10 && numero != 0 );

printf( "Suma: %d", acumulador );

return 0;
}
Programa (.c): Números opuestos del -10 al 10 (sin instrucción break)

Obsérvese que, en este programa, sí se contempla en la condición de salida del bucle la posibilidad de que
el usuario teclee un cero, en cuyo caso, el bucle deja de iterar de forma natural.

Los resultados por pantalla de este código fuente son idénticos a los del código anterior.

Por otra parte, en lenguaje C, como ya vimos en el apartado 2.3 Alternativa múltiple (la instrucción
switch), la instrucción break también se usa para interrumpir (salir de) una alternativa múltiple.
4.2 Instrucción continue
En lenguaje C, para escribir una instrucción de salto continue (continuar) , se utiliza la sintaxis:

continue;

La instrucción de salto continue siempre se usa para interrumpir (romper) la ejecución normal de
un bucle. Sin embargo, el control del programa no se transfiere a la primera instrucción después del bucle
(como sí hace la instrucción break, véase el apartado anterior), es decir, el bucle no finaliza, sino que,
finaliza la iteración en curso, transfiriéndose el control del programa a la condición de salida del bucle,
para decidir si se debe realizar una nueva iteración o no.

Por tanto, la instrucción continue finaliza (termina) la ejecución de una iteración de un bucle, pero, no
la ejecución del bucle en sí. De forma que, la instrucción continue salta (no ejecuta) las instrucciones
que existan después de ella, en la iteración de un bucle.

Ejemplo 1: En el programa siguiente se muestra como se puede utilizar la instrucción continue:

#include <stdio.h>
int main()
{

int n, a;

a = 0;
do
{
printf( "Introduzca un numero entero: " );
scanf( "%d", &n );

if ( n == 0 )
{
printf( "ERROR: El cero no tiene opuesto.\n" );
continue;
/* En el caso de que n sea un cero,
la iteración en curso del bucle
se interrumpe aquí. */
}
printf( "El opuesto es: %d\n", -n );
a += n;
} while ( n >= -10 && n <= 10 );

printf( "Suma: %d", a );

return 0;
}
Programa (.c): Números opuestos del -10 al 10 (con instrucción continue)

El código del programa es el mismo que el del ejemplo 1 del apartado anterior, 4.1 Instruccion break,
excepto por la instrucción break, que ha sido sustituida por la instrucción continue. El programa
puede ser la solución para el problema siguiente, el cual se diferencia del ejemplo 1 del apartado anterior
en que si el usuario introduce un cero, el bucle no deja de iterar.

Diseñe el agoritmo de un programa que:

1º) Pida por teclado un número (dato entero).


2º) Si el número introducido por el usuario es distinto de cero, muestre por pantalla el mensaje:

 "El opuesto es: <-número>".

En caso contrario, muestre el mensaje:

 "ERROR: El cero no tiene opuesto.".

3º) Repita los pasos 1º y 2º, mientras que, el usuario introduzca un número mayor o igual que -10 y menor
o igual que 10.
4º) Muestre por pantalla la suma de los números introducidos por el usuario.

En pantalla:

Introduzca un número entero: 2

El opuesto es: -2
Introduzca un número entero: 0

ERROR: El cero no tiene opuesto.


Introduzca un número entero: -59
El opuesto es: 59

Suma: -57

La traza del programa es:

Secuencia: Acción (instrucción): Valor de:


a n
1 a = 0 0 ?
Inicio de la iteración 1.
2 printf( "Introduzca un número entero:" ) 0 ?
3 scanf( "%d",n ) 0 2
4 (Comprobar si n = 0) 0 2
La condición de la alternativa simple (if) es falsa.
5 printf( "El opuesto es: %d\n", -n ) 0 2
6 a += n 2 2
Fin de la iteración 1.
7 (Comprobar si n >= -10 y n <= 10) 2 2
La condición del bucle (do...while) es verdadera.
Inicio de la iteración 2.
8 printf( "Introduzca un número entero:" ) 2 2
9 scanf( "%d",n ) 2 0
10 (Comprobar si n = 0) 2 0
La condición de la alternativa simple (if) es verdadera.
11 printf( "ERROR: El cero no tiene opuesto." ) 2 0
12 continue 2 0
La 2ª iteración se interrumpe (finaliza) aquí.
El control del programa se transfiere (salta) a la
condición de salida del bucle (do...while).
13 (Comprobar si n >= -10 y n <= 10) 2 0
La condición del bucle (do...while) es verdadera.
Inicio de la iteración 3.
14 printf( "Introduzca un número entero:" ) 2 0
15 scanf( "%d",n ) 2 -59
16 (Comprobar si n = 0) 2 -59
La condición de la alternativa simple (if) es falsa.
17 printf( "El opuesto es: %d\n", -n ) 2 -59
18 a += n -57 -59
Fin de la iteración 3.
19 (Comprobar si n >= -10 y n <= 10) -57 -59
La condición del bucle (do...while) es falsa.
El bucle finaliza después de 3 iteración.
20 printf( "Suma: %d", a ) -57 -59
Figura. Traza del ejemplo 1.

La instrucción continue se ejecuta cuando el usuario introduce un cero, interrumpiendo la iteración en


curso; pero, el bucle solamente finaliza cuando la condición ( n >= -10 y n <= 10 ) sea falsa.

Normalmente, al igual que ocurre con la instrucción break, cuando en un bucle se utiliza una
instrucción continue, la ejecución de ésta también se condiciona.

En el ejemplo 1, la iteración en curso del bucle se interrumpe si es verdadera la condición ( n = 0 ).

Ejemplo 2: No obstante, el problema también se puede resolver sin hacer uso de la


instrucción continue:

#include <stdio.h>

int main()
{

int numero, acumulador;

acumulador = 0;
do
{
printf( "Introduzca un numero entero: " );
scanf( "%d", &numero );

if ( numero == 0 )
{
printf( "ERROR: El cero no tiene opuesto.\n" );
}
else
{
printf( "El opuesto es: %d\n", -numero );
acumulador += numero;
}

} while ( numero >= -10 && numero <= 10 );

printf( "Suma: %d", acumulador );

return 0;
}
Programa (.c): Números opuestos del -10 al 10 (sin instrucción continue)

Los resultados por pantalla de este programa son idénticos a los del algoritmo anterior.
4.3 Instrucción goto
En lenguaje C, para escribir una instrucción de salto goto (ir_a), se utiliza la sintaxis:

goto <nombre_de_la_etiqueta>

La instrucción de salto goto se puede usar en un programa, para transferir incondicionalmente el control
del mismo a la primera instrucción después de una etiqueta, o dicho de otra forma, al ejecutar una
instrucción goto, el control del programa se transfiere (salta) a la primera instrucción después de una
etiqueta. Una etiqueta se define mediante su nombre (identificador) seguido del carácter dos puntos (:).
Ejemplo: En el siguiente programa se utiliza la instrucción goto para resolver el mismo problema que el
del ejemplo 1 del apartado 4.1 Instrucción break:

#include <stdio.h>

int main()
{

int n, a;

a = 0;
do
{
printf( "Introduzca un numero entero: " );
scanf( "%d", &n );

if ( n == 0 )
{
printf( "ERROR: El cero no tiene opuesto.\n" );
goto etiqueta_1;
/* En el caso de que n sea un cero,
el control de programa salta a la
primera instrucción después de
etiqueta_1. */
}
printf( "El opuesto es: %d\n", -n );
a += n;
} while ( n >= -10 && n <= 10 );

etiqueta_1:
printf( "Suma: %d", a );

return 0;
}
Programa (.c): Números opuestos del -10 al 10 (con instrucción goto)

Los resultados por pantalla de este programa son idénticos a los de los programas de los ejemplos 1 y 2
del apartado 4.1 Instrucción break.

En pantalla:

Introduzca un número entero: -4

El opuesto es: 4

Introduzca un número entero: 12

El opuesto es: -12

Introduzca un número entero: 0


ERROR: El cero no tiene opuesto.

Suma: 8

La traza del programa es:


Valor de:
Secuencia: Acción (instrucción):
a n
1 a = 0 0 ?
Inicio de la iteración 1.
2 printf( "Introduzca un número entero:" ) 0 ?
3 scanf( "%d",n ) 0 -4
4 (Comprobar si n == 0) 0 -4
La condición de la alternativa simple (if) es falsa.
5 printf( "El opuesto es: %d\n", -n ) 0 -4
6 a += n -4 -4
Fin de la iteración 1.
7 (Comprobar si n >= -10 && n <= 10) -4 -4
La condición del bucle (do...while) es verdadera.
Inicio de la iteración 2.
8 printf( "Introduzca un número entero:" ) -4 -4
9 scanf( "%d",n ) -4 12
10 (Comprobar si n == 0) -4 12
La condición de la alternativa simple (if) es falsa.
11 printf( "El opuesto es: %d\n", -n ) -4 12
12 a += n 8 12
Fin de la iteración 2.
13 (Comprobar si n >= -10 && n <= 10) 8 12
La condición del bucle (do...while) es verdadera.
Inicio de la iteración 3.
14 printf( "Introduzca un número entero:" ) 8 12
15 scanf( "%d",n ) 8 0
16 (Comprobar si n == 0) 8 0
La condición de la alternativa simple (if) es verdadera.
17 printf( "ERROR: El cero no tiene opuesto." ) 8 0
18 goto etiqueta_1 8 0
El bucle se interrumpe en la 3ª iteración.
El control del programa se transfiere (salta) a la
primera instrucción después de etiqueta_1.
19 printf( "Suma: %d", a ) 8 0

Figura. Traza del ejemplo 1.

Normalmente, al igual que ocurre con las instrucciones break y continue, cuando en un algoritmo se
utiliza una instrucción goto, la ejecución de ésta también se condiciona.
4.4 Instrucción return
En lenguaje C, para escribir una instrucción de salto return (volver), se utiliza la sintaxis:

return <expresión>;

La instrucción de salto return es utilizada en lenguaje C para indicar el valor de retorno de una función.
Por tanto, vamos a hacer uso de la instrucción return cuando definamos subprogramas de tipo función,
que estudiaremos en el apartado 5. Llamadas a subprogramas.

Por otra parte, recuérdese que, en el apartado 1.3.2 Mi primer programa en lenguaje C, ya estudiamos la
utilidad de la instrucción return en la función main.
4.5 Ventajas de no usar las instrucciones de salto
Las ventajas de no usar las instrucciones de salto, especialmente la instrucción goto, se pueden resumir
en:

 La legibilidad del código fuente de los programas es mayor.


 La probabilidad de cometer errores en el algoritmo diseñado es menor.
 Es más fácil realizar cambios o corregir errores en el algoritmo del programa.
 Nunca se altera (rompe) la secuencia de ejecución normal del programa. Dicho de otro modo, el
programa siempre se ejecuta de un modo natural

También podría gustarte