Logo Studenta

apuntes

¡Este material tiene más páginas!

Vista previa del material en texto

INFORMÁTICA
ALGORITMIA Y PROGRAMACIÓN EN C
Pablo Carmona del Barco
Dpto. Ingeniería de Sistemas Informáticos y Telemáticos
Universidad de Extremadura
ÍNDICE
Tema 1: Introducción a la programación
1.1. Introducción.......................................................................................1
1.2. Metodología de la programación........................................................2
1.3. Los lenguajes de programación..........................................................6
Tema 2: Tipos de datos y expresiones
2.1 Tipos de datos, constantes y variables..............................................10
2.1 Expresiones...................................................................................... 15
2.2 Funciones internas............................................................................18
2.3 Punteros............................................................................................ 19
2.4 Reglas de prioridad...........................................................................20
Tema 3: Representación gráfica de los algoritmos y su traducción a C
3.1 Métodos de representación algorítmica............................................23
3.2 Operaciones primitivas.....................................................................24
3.3 Estructura de un programa en C.......................................................29
3.4 Estructuras de control.......................................................................30
Tema 4: Estructuras de datos (I): Arrays. Cadenas de caracteres
4.1 Introducción.....................................................................................43
4.2 Arrays............................................................................................... 44
4.3 Cadenas de caracteres.......................................................................49
Tema 5: Modularidad
5.1 Introducción a la modularidad..........................................................55
5.2 Definición de funciones....................................................................57
5.3 Invocación de funciones...................................................................59
5.4 Módulos que no devuelven ningún valor..........................................62
5.5 Módulos que devuelven más de un valor.........................................63
5.6 Arrays como parámetros..................................................................65
Tema 6: Estructuras de datos (II): Registros
6.1 Registros........................................................................................... 70
1
INTRODUCCIÓN A LA PROGRAMACIÓN
1.1 INTRODUCCIÓN
Una breve definición de informática es la siguiente: «Ciencia del tratamiento racional,
mediante máquinas automáticas, de la información». De ella se derivan dos hechos importantes.
Por un lado, el tratamiento de la información es llevado a cabo mediante máquinas automáticas: los
ordenadores. Por otro lado, la racionalidad en dicho tratamiento introduce el componente humano
como elemento indispensable de cualquier proceso informático, ya que será el ser humano quien
determine el modo de tratar la información.
La informática es una disciplina académica relativamente joven. Baste con señalar que el
término Computer Science no fue acuñado hasta los años 60 por el matemático George Forsythe y
que el primer Departamento de Informática en una Universidad se formó en el año 1962. Sin
embargo, la vertiginosa evolución de las tecnologías de la información ha llevado a la informática a
estar presente en la actualidad en gran parte de los campos científico, económico y social.
La principal herramienta que emplea la informática para llevar a cabo las tareas relacionadas
anteriormente es el ordenador o computador. Su definición nos aporta nuevas claves:
«Máquina automática para el tratamiento de la información que ejecuta programas
formados por una sucesión de operaciones aritméticas y lógicas”
Es decir, para realizar el tratamiento de la información, el ordenador acepta una entrada (los
datos), que mediante un programa transforma para proporcionar una salida (el resultado). Es
precisamente en la determinación del programa que el ordenador debe ejecutar donde el ser humano
interviene de forma decisiva. La Ilustración 1 esquematiza este proceso para el tratamiento
1 
Ilustración 1: Tratamiento automático de la información mediante el ordenador
ENTRADA ORDENADOR SALIDA
datos
programa
resultado
1. INTRODUCCIÓN A LA PROGRAMACIÓN
automático de la información mediante el ordenador.
En general, la secuencia de operaciones necesarias para resolver un problema se denomina
algoritmo, que puede considerarse como una fórmula o receta para la resolución de un problema.
Cuando se pretende que el problema sea resuelto por un ordenador, dicho algoritmo debe traducirse
a una sintaxis adecuada: el programa. Un programa está formado por una serie de instrucciones que
se corresponden con los distintos pasos del algoritmo que representa. Además, las instrucciones del
programa deben ajustarse a las normas que dicte el lenguaje de programación utilizado.
Finalmente, el conjunto de actividades que llevan al desarrollo de un programa informático se
denomina programación. En la Ilustración 2 se representan todos estos conceptos.
1.2 METODOLOGÍA DE LA PROGRAMACIÓN
Un programador es alguien que resuelve problemas. Para llegar a ser un programador eficaz
es necesario primero aprender a resolver problemas de un modo riguroso y sistemático, lo que se
denomina metodología de la programación. Aunque un problema puede resolverse normalmente de
muchas formas distintas y se requiere cierta dosis de práctica e incluso de habilidad para obtener
programas eficientes y de resolución clara, existen pautas que guían al programador de forma
genérica para alcanzar una buena solución. En esta sección se estudiarán dichas pautas.
La tarea de resolución de problemas se divide en tres fases:
 Análisis del problema: consiste en definir y comprender el problema en toda su
extensión, analizando todo aquello que es relevante para su resolución.
 Diseño del algoritmo: determinar y representar genéricamente el método de resolución
del problema (algoritmo).
 Resolución del problema mediante el ordenador: traducir el algoritmo a un lenguaje
de programación y comprobar que se ha hecho correctamente.
2 
Ilustración 2: Relación entre algoritmo y programa
ALGORITMO PROGRAMA
Lenguaje de
programación
escribir
('Es par')
escribir
('Es impar')
leer (n)
n mod 2 = 0
if then elseescribir
('Un nº:')
paridad
BLOCK
program paridad(input,output);
var n:integer;
begin
 write('Introduzca un número entero: ');
 readln(n);
 if n mod 2 = 0 then
 writeln('El número es PAR')
 else
 writeln('El número es IMPAR')
end.
1. INTRODUCCIÓN A LA PROGRAMACIÓN
1.2.1 ANÁLISIS DEL PROBLEMA
La fase de análisis del problema tiene como objetivo conseguir que el programador alcance a
comprender el problema en toda su extensión. Esto requiere que el problema esté bien definido, es
decir, que se disponga de una descripción del problema suficientemente detallada. A menudo, es
tarea del propio programador desarrollar este “enunciado” y completarlo durante el análisis
mediante la celebración de entrevistas con personal experto en el área de aplicación del problema
(directivos de la empresa, personal especializado, etc.).
La correcta definición del problema debe ir acompañada de la identificación y descripción de
los datos de entrada y de salida del problema. Es decir, el programador debe determinar de qué
datos relevantes para la resolución del problema se dispone (entrada) y qué información debe
proporcionarse como resolución del problema (salida).
Un dato de entrada puede definirse como un dato del que depende la salida del problema y
que, a su vez, no depende de ningún otro (no puede calcularse a partir de otros datos de entrada).
Para cada dato de entrada,deberá especificarse lo siguiente:
 Identificador del dato, que permita referenciarlo durante la fase de análisis.
 Descripción del dato: ¿en qué consiste el dato?
 Procedencia: Un dato de entrada puede solicitarse desde un dispositivo de entrada,
generarse aleatoriamente o integrarse directamente en el propio programa.
La primera alternativa deberá emplearse cuando se trate de información de entrada
que varía habitualmente de una resolución a otra del problema y se indicará como
procedencia el dispositivo de entrada receptor (teclado, etc.).
La segunda alternativa se corresponde con programas donde alguno de los datos está
sujeto al azar (por ejemplo, el valor de la tirada de un dado en un juego de azar). En tal
caso, se indicará como procedencia aleatorio.
La tercera alternativa es más apropiada cuando se trate de datos de entrada con
valores que habitualmente no varían, evitando así que el usuario tenga que introducir
dichos valores idénticos en cada resolución del problema. En este caso, se indicará
como procedencia dato fijo.
 Valor (sólo para datos fijos): Cuando el dato se integre directamente en el programa
(dato fijo), se indicará el valor asociado.
 Restricciones (sólo para datos procedentes de un dispositivo de entrada o aleatorios):
deberán indicarse las restricciones impuestas a los valores que el dato pueda tomar para
que se considere válido. El cumplimiento de estas restricciones deberá posteriormente
ser exigido por el programa mediante el correspondiente mecanismo de control de
entrada (en el caso de datos procedentes de teclado) o durante la generación de los
números aleatorios (en el caso de datos aleatorios).
Un dato de salida es aquél que proporciona toda o parte de la solución del problema y deberá
poder obtenerse a partir de los datos de entrada especificados en el apartado anterior. Para cada dato
de salida se proporcionará:
 Identificador del dato, que permita referenciarlo durante la fase de análisis.
 Descripción del dato: ¿en qué consiste el dato?
 Destino: deberá indicarse el dispositivo de salida hacia el que se dirigirá el dato
(monitor, impresora, etc.).
3 
1. INTRODUCCIÓN A LA PROGRAMACIÓN
Una última sección de la fase de análisis estará reservada a la inclusión de aquellos
comentarios que el programador considere oportunos para clarificar aún más el problema a resolver.
EJEMPLO 1.1. Se desea realizar un programa que determine el precio de una llamada telefónica entre teléfonos fijos.
El precio de la llamada lo constituye el coste por establecimiento de llamada (0.10 euros) y un coste por paso (0.03
euros/paso). La duración de un paso depende del tramo horario en el que se efectúe la llamada, según la siguiente
tabla:
Tramo 1 Tramo 2 Tramo 3
60 seg. 20 seg. 40 seg.
El usuario indicará la duración de la llamada y el tramo horario en el que se efectuó.
ANÁLISIS:
a) Datos de entrada:
 EST_LLAM=0.10. Coste del establecimiento de llamada (en euros). Dato fijo.
 PASO=0.03. Coste de un paso (en euros). Dato fijo.
 DUR1=60. Duración de un paso en el primer tramo horario (en segundos). Dato fijo.
 DUR2=20. Duración de un paso en el segundo tramo horario (en segundos). Dato fijo.
 DUR3=40. Duración de un paso en el tercer tramo horario (en segundos). Dato fijo.
 duracion: Duración de la llamada (valor entero, en segundos). Teclado. (duracion > 0).
 tramo: Tramo en el que se efectuó la llamada (valor entero). Teclado. (tramo  {1,2,3}).
b) Datos de salida:
 precio: Coste de la llamada (en euros). Monitor.
c) Comentarios:
 Las fracciones de pasos se computarán como pasos completos.
 Emplearemos una variable intermedia para calcular el número de pasos.
1.2.2 DISEÑO DEL ALGORITMO
Como ya sabemos, el algoritmo es la representación de los pasos necesarios para resolver un
problema. Estos pasos serán después trasladados a instrucciones que el ordenador podrá ejecutar.
Aprender a diseñar algoritmos correctamente se considera esencial en la práctica de la
programación, más que el conocimiento específico del lenguaje de programación más novedoso. El
algoritmo determinará el método de resolución del problema, y si dicho método se ha desarrollado
adecuadamente su traducción a un lenguaje de programación u otro es una cuestión menor.
Igualmente, el conocimiento de las particularidades internas de un tipo de ordenador u otro tampoco
será crucial para el diseño del algoritmo. Esto se debe a que el algoritmo es independiente tanto del
lenguaje de programación que vaya a emplearse como del ordenador donde finalmente se ejecute el
programa que lo represente: de ahí su gran importancia.
Para la descripción de un algoritmo pueden utilizarse representaciones gráficas (diagramas) o
textuales (pseudocódigo, lenguaje natural).
Además, el diseño de algoritmos requiere conocer de qué herramientas se dispone para
describir los pasos de resolución de un problema y cómo debemos utilizarlas. Esto dependerá de la
metodología de programación que vayamos a emplear. En este curso nos centraremos en la
4 
1. INTRODUCCIÓN A LA PROGRAMACIÓN
metodología de la programación denominada programación estructurada y emplearemos
diagramas estructurados para la representación de los algoritmos, los cuales serán estudiados en el
siguiente capítulo.
La fase de diseño se descompone en dos subfases:
a) Parte declarativa: en ella se incluirá la definición de constantes y la declaración de variables
que se estudiarán en el Capítulo 2, en este orden.
b) Representación algorítmica: descripción del algoritmo empleando alguno de los métodos de
representación mencionados.
EJEMPLO 1.2. La fase de diseño del problema planteado en el Ejemplo 1.1, empleando pseudocódigo para la
representación algorítmica, sería la siguiente:
a) Parte declarativa:
CONSTANTES
EST_LLAM=0.10
PASO=0.03
DUR1=60
DUR2=20
DUR3=40
VARIABLES
duracion,tramo,numPasos: entero
precio: real
b) Representación algorítmica:
inicio
 leer desde teclado duracion
 mientras duracion ≤ 0 hacer
 escribir mensaje de error
 leer desde teclado duracion
 leer desde teclado tramo
 mientras tramo < 1 o tramo > 3 hacer
 escribir mensaje de error
 leer desde teclado tramo
 si tramo=1 entonces
 almacenar en numPasos el valor techo(duracion/DUR1)
 sino (es tramo=1)
 si tramo=2 entonces
 almacenar en numPasos el valor techo(duracion/DUR2)
 sino (es tramo=2)
 almacenar en numPasos el valor techo(duracion/DUR3)
 almacenar en precio el valor EST_LLAM+numPasos×PASO
 escribir precio
fin
1.2.3 RESOLUCIÓN DEL PROBLEMA MEDIANTE EL ORDENADOR
Tras el diseño del algoritmo, este debe traducirse a las instrucciones de un lenguaje de
programación para que pueda ser resuelto por el ordenador. Esta fase se divide en tres subfases:
a) Codificación o implementación del algoritmo: es la conversión de los pasos del algoritmo a
las instrucciones equivalentes en un lenguaje de programación. El algoritmo escrito en un
lenguaje de programación se denomina programa, código fuente o, simplemente, código.
b) Verificación del programa: consiste en la comprobación de que la codificación del algoritmo
se ha realizado correctamente, empleando adecuadamente de las reglas gramaticales y
sintácticas del lenguaje utilizado.
5 
1. INTRODUCCIÓN A LA PROGRAMACIÓN
c) Validación del programa: consiste en la comprobación de que los resultados proporcionados
por el programa se corresponden con los establecidos en el análisis del problema.
Veremos un ejemplo de esta última fase en el siguiente capítulo, una vez que se conozcan las
instrucciones en lenguaje C.
1.3 LOS LENGUAJES DE PROGRAMACIÓN
Para el desarrollo de un programa es necesario conocer al menos un lenguaje de
programación. Esta sección se centra en estos, estableciendo una clasificación atendiendo al grado
de abstracción del lenguaje y describiendo ciertas herramientas deprogramación necesarias para
que el ordenador pueda realizar la tarea descrita en el lenguaje de programación empleado.
1.3.1 NIVELES DE ABSTRACCIÓN
El nivel de abstracción de un lenguaje se refiere a en qué medida la sintaxis y uso de ese
lenguaje se encuentra cercano al modo de trabajar de la máquina o, por el contrario, al modo de
pensar y hablar del ser humano. La clasificación de los lenguajes atendiendo al nivel de abstracción
está relacionada con la evolución de los lenguajes de programación, ya que el grado de abstracción
de los lenguajes ha ido aumentando con el paso de los años. A grandes rasgos, podemos distinguir
tres grupos: lenguajes máquina, lenguajes de bajo nivel y lenguajes de alto nivel.
LENGUAJES MÁQUINA
El ordenador representa internamente la información que maneja utilizando código binario.
En los primeros tiempos, los programadores tenían que realizar la tediosa tarea de traducir sus
algoritmos directamente a las secuencias binarias que representaban las instrucciones y los datos
contenidos en el programa. Estas instrucciones, conocidas como instrucciones de código máquina,
constituyen el lenguaje máquina de un ordenador.
La ventaja de programar en lenguaje máquina es que el código generado puede ser muy
eficiente, es decir, emplear poca memoria y ser muy rápido, y, por tanto, utilizar la mínima cantidad
de recursos. Sin embargo, la importancia de sus inconvenientes ha acabado con el uso de este tipo
de lenguajes en la actualidad. Uno de estos inconvenientes es la dependencia respecto al hardware
del ordenador, ya que, el lenguaje máquina de una familia de microprocesadores (por ejemplo, Intel
Pentium) no tiene porqué ser compatible con el de otra. Otro inconveniente es la dificultad en la
codificación. Por ejemplo, la operación aritmética 4 3+5✶ podría representarse esquemáticamente
en un hipotético lenguaje máquina como
multiplicación 4 3 dirección
0110 0100 0011 0001
suma 5 dirección
0101 0101 0001
donde puede observarse que tanto los códigos de operación como las direcciones de memoria y los
valores se representan mediante código binario. Obsérvese que la equivalencia real en instrucciones
máquina sería exclusivamente la cadena binaria 0110010000110001010101010001, difícilmente
comprensible de forma directa por el programador.
6 
1. INTRODUCCIÓN A LA PROGRAMACIÓN
LENGUAJES DE BAJO NIVEL (ENSAMBLADORES)
Si bien en los primeros tiempos el programador utilizaba lenguaje máquina para describir sus
programas, pronto se extendió la costumbre de emplear, durante el diseño de los algoritmos,
mnemotécnicos para representar sus pasos (es decir, abreviaturas en inglés de las instrucciones de
código máquina a las que equivalen). Esto permitía a los programadores abstraerse de las
particularidades de la representación interna de las instrucciones durante el desarrollo del método
de resolución del problema y propició el siguiente paso en la evolución de los lenguajes de
programación, los lenguajes ensambladores, donde las instrucciones se expresaban utilizando un
lenguaje simbólico (no binario) que aumentó la legibilidad de los programas. Sin embargo, estos
lenguajes mantienen su dependencia de la máquina, siendo por tanto cada lenguaje ensamblador
específico de una familia de microprocesadores. Además, cada instrucción en lenguaje ensamblador
equivale a una única instrucción en código máquina. Por ejemplo, la operación aritmética anterior
tendría en un hipotético lenguaje ensamblador un aspecto parecido al siguiente:
MUL 4,3,A
SUM 5,A
Debido a lo todavía complejo y poco intuitivo de su programación, actualmente los
ensambladores se utilizan en áreas muy reducidas donde las exigencias en velocidad de ejecución o
aprovechamiento de recursos son elevadas.
LENGUAJES DE ALTO NIVEL
Aunque la introducción de los lenguajes ensambladores supuso un importante paso hacia
adelante en la evolución de los lenguajes de programación, aún existían inconvenientes importantes
que salvar, tales como la dependencia respecto al hardware y la obligación de describir los métodos
de resolución como una secuencia de los pequeños pasos que podían realizarse en lenguaje
máquina.
Se advirtió la necesidad de proporcionar instrucciones de más alto nivel que permitieran
describir acciones de mayor envergadura, las cuales equivaldrían luego a un conjunto de
instrucciones en código máquina. De esta idea surgieron los lenguajes de alto nivel, más cercanos al
modo de expresarse del ser humano y, por tanto, más fáciles de aprender y de utilizar. Igualmente,
debido a su fácil comprensión, los programas escritos en un lenguaje de alto nivel son más fáciles
de actualizar y corregir.
El lenguaje C, que se trata en este curso, es un lenguaje de alto nivel. El ejemplo anterior se
expresaría en C con una única instrucción:
A = 4 3+5✶
fácilmente entendible. Obsérvese que esta única instrucción en un lenguaje de alto nivel equivale a
varias instrucciones en el código máquina y el ensamblador del ejemplo anterior.
Además de su mayor legibilidad, otra de las características esenciales de los lenguajes de alto
nivel es que son transportables. Esto significa que, a diferencia de los lenguajes de más bajo nivel,
el mismo programa puede ser válido con pocos o ningún cambio en distintas plataformas, esto es,
en ordenadores con distintos microprocesadores. Por tanto, los lenguajes de alto nivel son
independientes del hardware.
Sus inconvenientes se corresponden con las ventajas de los lenguajes máquina y
ensambladores, ya que tanto en ocupación de memoria como en tiempo de ejecución los lenguajes
de alto nivel suelen presentar un consumo mayor que aquéllos.
7 
1. INTRODUCCIÓN A LA PROGRAMACIÓN
1.3.2 TRADUCTORES DE LENGUAJES
El ordenador sólo entiende directamente programas escritos en lenguaje máquina. Cuando la
codificación se realiza utilizando un lenguaje simbólico (ensambladores y lenguajes de alto nivel),
será necesario traducir dicho programa al código correspondiente en lenguaje máquina. Como
puede suponerse, el programador no tiene que hacer esto por sí mismo, sino que existen programas
que realizan dicha traducción de forma automática.
Al programa escrito en lenguaje simbólico se le llama programa o código fuente y al
resultado de la traducción programa o código objeto:
Distinguimos tres tipos de traductores: ensambladores, compiladores e intérpretes.
Los ensambladores traducen programas escritos en ensamblador a código máquina, mientras
que los compiladores e intérpretes traducen programas escritos en un lenguaje de alto nivel.
Por otra parte, los intérpretes traducen el programa instrucción a instrucción, de forma que
hasta que no terminan de ejecutar la última instrucción traducida no proceden a traducir la
siguiente, por lo que no generan programa objeto en disco. Por contra, tanto compiladores como
ensambladores traducen primero todo el programa fuente, generando un programa objeto en disco,
y una vez terminada la traducción, el programa podrá ejecutarse.
Las diferencias entre estos tres tipos de traductores están esquematizadas en la Tabla 1.
Ahora bien, cuando se desarrolla un programa, este puede incluir referencias a tareas que no
son instrucciones del lenguaje de programación, sino que están descritas en las llamadas bibliotecas
de funciones que suelen acompañar al traductor del lenguaje para hacerlo más versátil. Dichas
tareas son frecuentes y comunes a muchos programas, tales como operaciones gráficas (dibujar un
círculo, cambiar el color del texto), matemáticas (logarítmicas, trigonométricas), etc.
Por otro lado, un programa puede hacer referencia a otros programas desarrollados por el
propio programador que resuelven tareas no incluidas en la biblioteca de funciones (por ejemplo, C
no incorpora una función para calcular el factorial de un número). Estos programas se denominan
programas fuentessecundarios y requerirán también un proceso de traducción.
Por ello, después de traducir el programa principal mediante un ensamblador o un compilador
(que solo conoce la equivalencia a lenguaje máquina de las instrucciones propias del lenguaje que
traduce), será necesario unir el programa objeto generado con el resto de módulos donde existan
tareas a las que se haga referencia desde dicho programa principal (programas fuentes secundarios y
bibliotecas de funciones). Para conseguir el programa ejecutable resultado de esta operación de
unión se debe utilizar una herramienta denominada montador, enlazador o linkador.
8 
Programa
fuente
Programa
objeto
Simbólico Máquina
TRADUCTOR
Lenguaje fuente Traductor Método
L. ensamblador Ensambladores
L. de alto nivel Compiladores
Todo el programa
(programa objeto en disco)
Intérpretes Instrucción a instrucción
Tabla 1: Diferencias entre los tres tipos de traductores
1. INTRODUCCIÓN A LA PROGRAMACIÓN
De este modo, cuando estamos empleando un compilador o un ensamblador, el esquema de
funcionamiento es el que se muestra en la Ilustración 5.
9 
 bibliotecas
programa fuente
principal ENSAMBLADOR
O COMPILADOR
programa objeto
ENLAZADOR
programa
ejecutable
programas fuentes
secundarios ENSAMBLADOR
O COMPILADOR
otros
módulos
Ilustración 5: Esquema de funcionamiento de compiladores y ensambladores
2
TIPOS DE DATOS
Y EXPRESIONES
En el capítulo anterior se definió la informática como la ciencia que estudia el tratamiento
automático de la información. Ahora bien, un ordenador puede manejar dos categorías de
información: instrucciones y datos. Mientras las instrucciones describen el proceso a realizar, los
datos representan la información a procesar. En este capítulo estudiaremos las distintas alternativas
de que dispone el programador para representar los datos (los tipos de datos), así como el modo de
operar con ellos (las expresiones).
2.1 TIPOS DE DATOS, CONSTANTES SIMBÓLICAS Y VARIABLES
Toda información, ya sea numérica, alfabética, gráfica o de cualquier otro tipo, se representa
internamente en el ordenador mediante una secuencia de bits. En los primeros tiempos de la
informática, esto suponía que el programador debía estar familiarizado con dicha representación
interna, debiendo realizar por sí mismo la conversión de los datos al correspondiente código binario.
Sin embargo, con la introducción del concepto de tipo de datos, los lenguajes actuales permiten que
el programador pueda abstraerse de la representación interna de los datos y trabajar con ellos de una
forma más natural.
En la resolución de problemas mediante ordenadores, la estructura seleccionada para representar
los datos con los que trabaja un programa es tan importante como el diseño del algoritmo que
determina su comportamiento, ya que de dicha estructura va a depender en gran parte la claridad,
eficiencia y requisitos de memoria del programa resultante.
Existen dos categorías de datos: simples y estructurados. En este capítulo nos centraremos en los
tipos de datos simples y los tipos de datos estructurados se estudiarán en los Capítulos 4 y 6.
2.1.1 TIPOS DE DATOS SIMPLES
Un dato simple puede definirse como un elemento de información que se trata dentro de un
programa como una unidad (por ejemplo, un número o una letra). El lenguaje C dispone
fundamentalmente de tres tipos de datos simples: son los tipos entero, real y carácter.
10
2. TIPOS DE DATOS Y EXPRESIONES
TIPO ENTERO
El tipo entero se representa en C mediante la palabra clave int y consiste en el subconjunto de
valores enteros contenido en el intervalo [-2147483648, 2147483647] (equivalente al intervalo
[-231, 231-1] que permite representar 232=4.294.967.296 valores distintos y ocupa 4 bytes1). Un literal
entero es una secuencia de uno o más dígitos entre el 0 y el 9, debiendo ser el primer dígito distinto
de 0 cuando el literal esté formado por más de un dígito. Al literal puede añadírsele un operador
unario positivo o negativo (+ o −), aunque se asumirá el signo positivo cuando no se especifique
ningún signo. Sin embargo, no admite el uso de separadores de unidades de millar ni el empleo del
separador decimal aunque la parte decimal no sea significativa, debiendo por tanto aparecer
únicamente los dígitos que constituyen la cifra.
Ejemplos de literales válidos de tipo int son:
5 -15 2003
Ejemplos de literales no válidos como tipo int son:
-1050.0 3.456 3,200 034
TIPO REAL
El tipo real consiste en un subconjunto de los números reales. Un literal real consta de una parte
entera y una parte decimal, separadas por un punto decimal. En C, existen dos tipos básicos para
representar valores reales: simple precisión (float) y doble precisión (double). El tipo float
ocupa 4 bytes y permite representar valores en el rango [1.2×10-38, 3.4×1038] (positivo y negativo),
además del cero. El tipo double ocupa 8 bytes y permite representar valores en el rango
[2.2×10-308, 1.8×10308] (también positivo y negativo), además del cero.
En aplicaciones científicas, a menudo se emplea una representación especial para manejar
números muy grandes o muy pequeños. Por ello, en C existe una representación denominada
notación exponencial donde cada literal consta de un número entero o real (mantisa) y de un
número entero (exponente), separados por la letra "e" (en minúscula o mayúscula). Por ejemplo, el
literal 1.345e2 es equivalente a 1.345×102 o 134.5, y el literal 2.058e-3 es equivalente a
2.058×10-3 o 0.002058. En el primer valor, el punto decimal se desplaza dos lugares hacia la
derecha porque el exponente es +2. En el segundo, el punto decimal se desplaza tres lugares hacia la
izquierda porque el exponente es -3.
Ejemplos de literales reales válidos en C son:
0.45 .23 1234. 1e10 -2e-3 0.2E4
Ejemplos de literales reales no válidos en C son:
1e0.1 12.0a10 1,345.5 1.345,5 2.3-e5 34
TIPO CARÁCTER
El tipo carácter se representa en C con la palabra clave char y consiste en el conjunto finito y
ordenado de los caracteres representables por el ordenador (en el caso de los PC's, consiste en el
conjunto de caracteres incluido en la tabla de códigos ASCII). Un literal de tipo carácter se
representa en C mediante un solo carácter encerrado entre comillas simples o apóstrofos.
1 Los intervalos de valores válidos y el número de bytes ocupados por los datos de cada tipo pueden variar según el
compilador y plataforma usadas.
11
2. TIPOS DE DATOS Y EXPRESIONES
Ejemplos válidos de literales de tipo carácter de C serán:
'a' ',' '>' 'A' '3'
Ejemplos de literales de tipo carácter no válidos en C serán:
'ab' 'A q "b"
Existen ciertos caracteres especiales que se representan en C mediante las denominadas
secuencias de escape. Algunas de las más frecuentes son las siguientes:
Carácter Secuencia de escape
Tabulador horizontal \t
Nueva línea (inicio de la siguiente línea) \n
Retorno de carro (inicio de la línea actual) \r
Carácter nulo \0
Comillas \"
Apóstrofo \'
Barra inclinada \\
2.1.2 CONSTANTES SIMBÓLICAS Y VARIABLES
Tanto las constantes simbólicas como las variables permiten almacenar durante la ejecución del
programa valores de los tipos de datos que acabamos de ver.
Cada variable o constante simbólica lleva asociado un nombre o identificador que la designa.
Los nombres elegidos deben ser significativos, es decir, deben hacer referencia al dato que
representan. Por ejemplo:
edad para almacenar la edad de una persona
IVA para almacenar el porcentaje de IVA
Es costumbre habitual por parte de los programadores emplear distinta notación para constantes
simbólicas y variables, por ejemplo, emplear sólo letras mayúsculas para las constantes simbólicas y
una combinación de mayúsculas y minúsculas para las variables. Aunque esta práctica no es
obligatoria,facilita la comprensión del código al permitir determinar a simple vista y en cualquier
lugar del programa si un identificador hace referencia a una constante simbólica o a una variable.
Las reglas sintácticas que deben seguir los identificadores en C son:
 El primer carácter debe ser una letra o el carácter de subrayado.
 El resto pueden ser letras, dígitos o el carácter de subrayado.
El diagrama sintáctico2 de un identificador será:
2 Un diagrama sintáctico representa las reglas de construcción sintácticas de un componente de un lenguaje de
programación. Para determinar si una construcción determinada es sintácticamente válida basta con seguir su
diagrama sintáctico en el sentido de las flechas e ir comprobando que la construcción cumple los requisitos indicados
en el diagrama hasta salir del mismo.
12
letra
subraya
dígito
letra
subraya
2. TIPOS DE DATOS Y EXPRESIONES
Además, un identificador en C no puede contener espacios, ni acentos, ni la letra ñ, ni puede
coincidir con una palabra clave (por ejemplo, no pueden utilizarse int o float como
identificadores).
Por último, debe tenerse en cuenta que el lenguaje C es sensible a mayúsculas/minúsculas. Así,
los identificadores Suma y suma hacen referencia a distintos datos dentro de un mismo programa.
Una constante simbólica denomina un valor que no cambia nunca durante la ejecución del
programa. La definición de una constante simbólica consiste en la asociación de un identificador
con un valor y en C se realiza de la siguiente forma:
Una constante simbólica no ocupa espacio en memoria, ya que el propio compilador sustituye
cada aparición de la constante simbólica en el programa por su valor correspondiente durante el
proceso de traducción.
En algoritmia, la definición de constantes simbólicas utiliza el siguiente diagrama:
A continuación se muestran definiciones válidas de constantes simbólicas construidas utilizando
los diagramas sintácticos anteriores:
En algoritmia:
CONSTANTES
 LETRA='a'
 NUMERO=-3.141592
 PI=-NUMERO
En C:
#define LETRA 'a'
#define NUMERO -3.141592
#define PI -NUMERO
Algunas de las ventajas que puede proporcionar la definición de constantes simbólicas frente al
uso directo de literales son las siguientes:
 Facilita la comprensión del programa: la elección de un identificador alusivo al
significado del valor que representa puede facilitar la comprensión del programa. Por
ejemplo, si en un programa hacemos referencia al porcentaje del IVA, será más
comprensible leer el identificador IVA que el literal 21.
 Facilita la modificación del código del programa: si es necesario modificar un dato
considerado como constante en el programa, la definición de una constante simbólica
permite hacerlo en un solo paso en lugar de tener que explorar todo el código en busca
de literales que hagan referencia a ese dato. Por ejemplo, si el IVA variase, bastaría con
modificar el valor asociado a la constante simbólica en la definición para que dicha
modificación actuara sobre todas las referencias incluidas en el programa.
No obstante, antes de emplear una constante simbólica en lugar de un literal en un programa,
debe considerarse si alguna de las ventajas mencionadas va a ser aprovechada, pues en caso
contrario sólo se conseguirá aumentar el tamaño del programa y hacerlo menos claro. Por ejemplo,
si en un programa quisiéramos contabilizar el número de valores que el usuario introduce por
teclado, no sería adecuado definir una constante simbólica para representar al literal 1 que debe
tomar el contador como valor inicial, ya que, por un lado, referirse a dicho valor mediante un
13
identificadorCONSTANTES = expresión
identificador#define expresión
2. TIPOS DE DATOS Y EXPRESIONES
identificador como UNO o PRIMER_VALOR no facilitaría la lectura el programa y, por otro, el
primer valor que toma un contador no es susceptible de cambiar en un futuro (siempre
comenzaremos a contar desde el valor 1).
Una variable denota a un dato cuyo valor puede cambiar durante la ejecución del programa.
Cabe aclarar que el concepto de variable en el ámbito de la programación es distinto que en el
ámbito de las matemáticas, ya que en programación las variables no representan incógnitas sino
datos almacenados en memoria principal. Cada variable, además de un identificador, lleva asociado
un tipo que determina su uso, de forma que dicha variable sólo podrá tomar valores de ese tipo. Por
ejemplo, una variable de tipo entero sólo podrá almacenar valores enteros.
Toda variable debe ser declarada antes de su utilización. Este proceso servirá para reservar
espacio en memoria para el valor asociado a dicha variable. En la declaración deberán especificarse
el identificador y el tipo de la variable. En algoritmia, se empleará el diagrama sintáctico siguiente
utilizando la palabra entero para hacer referencia al tipo entero de C, la palabra real para los
diferentes tipos de reales y la palabra carácter para el tipo char.
En C, el diagrama sintáctico es el siguiente:
Declaraciones válidas de variables serían:
En algoritmia:
VARIABLES
radio,diametro:real
grupo:carácter
edad:entero
En C:
float radio,diametro;
char grupo;
int edad;
2.1.3 EL TIPO CADENA DE CARACTERES3
Un literal de tipo cadena de caracteres es una secuencia de cero o más caracteres incluidos en la
tabla de códigos ASCII y encerrados entre comillas dobles. Todo valor de tipo cadena de caracteres
finaliza con el carácter especial '\0' (carácter nulo). Este carácter es insertado automáticamente,
por lo que el programador no tendrá que preocuparse de incluirlo en los literales de tipo cadena. Así,
3 Aunque el tipo cadena de caracteres es un tipo estructurado y sus características serán estudiadas en profundidad en
el Capítulo 4, se introduce aquí para que se pueda trabajar con información de tipo cadena de caracteres desde un
principio.
14
tipo
identificador
de variable
;
,
tipo
identificador
de variable
:
,
VARIABLES
2. TIPOS DE DATOS Y EXPRESIONES
el literal
"Pulsa una tecla para continuar"
es una cadena de caracteres con 31 caracteres (las 30 letras más el carácter nulo que indica el fin de
cadena).
Las variables de tipo cadena de caracteres permiten almacenar cadenas con una longitud máxima
que se indica en la declaración entre corchetes junto al identificador. Por ejemplo, para declarar una
variable frase de tipo cadena de caracteres con un máximo de 15 caracteres se utiliza la siguiente
sintaxis:
char frase[15];
que permitirá almacenar frases de hasta 14 caracteres significativos, pues el carácter nulo de fin de
cadena ocupará la última posición.
2.2 EXPRESIONES
Una expresión matemática tradicional está formada por una combinación de operandos,
operadores y paréntesis. Por ejemplo:
En los lenguajes de programación también es posible representar expresiones como una
combinación de literales, identificadores (de variables o constantes simbólicas), símbolos de
operación básicos, paréntesis y nombres de funciones especiales. Todos estos elementos podrán
indistintamente estar o no separados por uno o más espacios. Los literales e identificadores actúan
como operandos, mientras que los símbolos de operación y las funciones especiales lo hacen como
operadores.
Cada expresión toma el valor resultante de aplicar los operadores a los operandos. Dependiendo
del tipo de este valor resultante, distinguimos dos categorías de expresiones fundamentales:
aritméticas y lógicas.
2.2.1 EXPRESIONES ARITMÉTICAS
Los operandos serán habitualmente de tipo numérico (real o entero). Los símbolos de operación
básicos son:
+ suma y signo positivo
- resta y signo negativo
* multiplicación
/ división
% módulo (resto)
El operador % se debe aplicar siempre a operandos de tipo entero. Cuando la división se aplique a
operandos de tipo entero, el resultado será la división entera (por ejemplo,5/3 dará como resultado
1, que es la parte entera de 1.666).
15
∑ x−xn 
2
n−1
2. TIPOS DE DATOS Y EXPRESIONES
El resultado de una expresión aritmética será de tipo numérico. En concreto,
 Cuando los operandos implicados en la expresión sean del mismo tipo, el resultado será
de ese tipo.
 Por el contrario, cuando en una expresión aritmética se incluyan operandos numéricos
de distinto tipo, el resultado obtenido será del tipo correspondiente al operando de
mayor precisión. Por ejemplo, si un operando es double y el otro float, el resultado
será double, si un operando es int y el otro float, el resultado será float, etc.
Para modificar el tipo de un operando o del resultado de una expresión es posible utilizar la
conversión explicita de tipos (casting). Para ello, basta con preceder a la expresión que quiere
convertirse a un nuevo tipo, de dicho tipo encerrado entre paréntesis. Así, aunque f sea una variable
de tipo float, (int) f % 2 será una expresión válida, pues el operando f ha sido convertido
previamente al tipo int antes de aplicar la operación de módulo (adviértase que en esa conversión
se descartaría la parte decimal del valor de f).
Reglas de prioridad:
Es posible que en una expresión aritmética concurran varios operadores. En ese caso, el orden de
aplicación de los mismos puede influir en el resultado final. Por ejemplo, en la expresión aritmética
6+4/2 el resultado será 5 u 8 dependiendo del orden en que se apliquen los operadores + y /.
Por lo tanto, es necesario establecer unas reglas para determinar qué operadores se aplican
primero en estos casos. Estas reglas se denominan reglas de prioridad y en C son las siguientes:
1. Operadores unarios signo positivo (+), signo negativo (-) y casting (tipo)
2. Operadores *, /, %.
3. Operadores binarios suma (+) y resta (-).
Si coincidieran varios operadores de igual prioridad en una expresión, el orden de evaluación es
de izquierda a derecha, excepto para los operadores unarios que será de derecha a izquierda. Por
ejemplo, el resultado de 4+8/-2*6 es -20.
Los paréntesis permiten alterar la prioridad por defecto de los operadores, ya que las expresiones
encerradas entre paréntesis serán las primeras que se evalúen. Si existen paréntesis anidados
(interiores unos a otros), las operaciones internas se evalúan primero. Por ejemplo, el resultado de
(4+8)/(-2*6) es -1.
2.2.2 EXPRESIONES LÓGICAS
Las expresiones lógicas permiten incluir en un programa instrucciones que se ejecutarán
solamente bajo ciertas condiciones. Podrán tomar únicamente dos posibles valores: verdadero (1) o
falso (0). Se forman combinando identificadores (de variables o constantes simbólicas), literales y
subexpresiones con operadores relacionales (de relación o comparación) y operadores lógicos.
16
2. TIPOS DE DATOS Y EXPRESIONES
Los operadores relacionales permiten realizar comparaciones. Son los siguientes:
< menor que
> mayor que
== igual a
<= menor o igual a
>= mayor o igual a
!= distinto de
El formato general de una expresión relacional es:
expresión1 operador de relación expresión2
La aplicación a valores numéricos es evidente. Si X=4 e Y=3, entonces:
X > Y es 1 (verdadero)
(X - 2) < (Y – 4) es 0 (falso)
Cuando se comparan valores de tipo carácter, el resultado de la comparación será el de la
comparación de los valores ASCII asociados a los caracteres implicados. Por ejemplo, 'A'<='B'
dará como resultado 1 (verdadero), ya que el código ASCII de la A (65) es menor que el de la B
(66), mientras que 'X'=='Z' dará como resultado 0 (falso), ya que el código ASCII de la X (88) es
distinto del de la Z (90).
Los operadores relacionales no pueden aplicarse directamente a valores de tipo cadena de
caracteres.
Las reglas de prioridad entre operadores relacionales son:
1. <, <=, >, >=
2. ==, !=
Los operadores lógicos son: ! (no-lógico), && (y-lógico) y || (o-lógico). Se aplican casi
siempre a operandos que son subexpresiones lógicas, aunque en general pueden aplicarse a
cualquier valor entero. En este sentido, el 0 se interpretará como falso y cualquier entero distinto de
0 (no solo el 1) se interpretará como verdadero. El resultado será 1 o 0 (verdadero o falso,
respectivamente). Los operadores && y || son operadores binarios, mientras que ! es unario.
Los operadores &&, || y ! vienen definidos por sus tablas de verdad:
a b a && b
distinto de 0
distinto de 0
0
0
distinto de 0
0
distinto de 0
0
1
0
0
0
Devuelve un resultado
verdadero si y sólo si los
dos operandos son
verdadero
a b a || b
distinto de 0
distinto de 0
0
0
distinto de 0
0
distinto de 0
0
1
1
1
0
Devuelve un resultado
verdadero si uno
cualquiera de los
operandos es verdadero
17
2. TIPOS DE DATOS Y EXPRESIONES
a !a
distinto de 0
0
0
1
Devuelve un resultado
opuesto al del operando
Las reglas de prioridad entre operadores lógicos son:
1. no-lógico (!)
2. y-lógico (&&)
3. o-lógico (||)
Si aparecen dos o más operadores lógicos iguales en una expresión, los operadores ! se aplicarán
de derecha a izquierda y los operadores && y || de izquierda a derecha.
Por ejemplo, si X=4 e Y=3, la expresión lógica (X > 3) || (Y > 5) && !(X=4) será
verdadero (1).
2.3 FUNCIONES ESPECIALES
Los operadores básicos que acaban de estudiarse no son suficientes para realizar ciertas
operaciones de cálculo (trigonométricas, logarítmicas, etc.). No obstante, algunas de estas
operaciones se encuentran disponibles en los lenguajes de programación a través de bibliotecas de
funciones y se denominan funciones internas. Otras, como veremos en el Capítulo 5 pueden ser
definidas por el programador y se denominan funciones externas. Cada función, cuando es invocada
desde un programa, provoca la ejecución de un conjunto específico de instrucciones y puede
devolver uno o más valores, que en cada caso serán de un tipo determinado.
La mayoría de las funciones requieren datos de entrada que se denominan parámetros y que
aparecen entre paréntesis detrás del nombre de la función. Estos parámetros también deberán ser
datos de un tipo concreto, que vendrá determinado por la función en cuestión.
Además, para poder utilizar una determinada función interna, es necesario conocer en qué
biblioteca se encuentra e incluir al comienzo del programa una instrucción para hacer referencia al
archivo de cabecera de la biblioteca correspondiente, que será un archivo con extensión “.h” (por
ejemplo, stdio.h para las funciones de entrada/salida estándar o math.h para las funciones
matemáticas). El diagrama sintáctico de esta instrucción es el siguiente:
Los tipos de datos de los parámetros y del valor devuelto por algunas de las funciones internas
más usuales se muestran en la siguiente tabla. El tipo de los parámetros se representa entre los
paréntesis de las funciones (i=int, d=double, c=char), si bien los parámetros de tipo double
también admiten valores de cualquier otro tipo numérico (que será convertido a double).
18
archivo de 
cabecera#include < >
2. TIPOS DE DATOS Y EXPRESIONES
Función Tipo Devuelto Cabecera Propósito
abs(i) int math.h Valor absoluto de i
fabs(d) double math.h Valor absoluto de d
ceil(d) double math.h Redondeo por exceso (el entero más pequeño mayor o igual a d)
floor(d) double math.h Redondeo por defecto (el entero más grande menor o igual a d)
cos(d) double math.h Coseno de d
sin(d) double math.h Seno de d
tan(d) double math.h Tangente de d
exp(d) double math.h Exponencial de d (ed)
log(d) double math.h Logarítmo neperiano de d
pow(d1,d2) double math.h Potencia de d1 elevado a d2
sqrt(d) double math.h Raíz cuadrada de d
tolower(c) char ctype.h Convertir c a minúsculas
toupper(c) char ctype.h Convertir c a mayúsculas
2.4 PUNTEROS
Un puntero es un dato que representa la dirección de memoria donde se almacena otro dato. Por
ello, se dice que el valor de un puntero apuntaa otro valor. Los punteros son usados muy
frecuentemente en C y están relacionados con otros conceptos como los de arrays y modularidad
que se estudiarán en capítulos posteriores.
Para trabajar con punteros es necesario conocer los operadores de dirección e indirección. El
operador de dirección (&) permite obtener la dirección de memoria en la que se encuentra
almacenado un dato (es decir, la dirección de memoria asociada a una variable). El resultado de la
operación de dirección será, por tanto, de tipo puntero. Por ejemplo, si v es una variable declarada
de tipo real, en el siguiente esquema
v representa el contenido de la variable (el valor real 3.154) y &v representa la dirección de
memoria donde se almacena dicho valor (la posición 65522). Se dice que &v es un puntero a v.
El operador de indirección (*) permite obtener el valor al que apunta un puntero (es decir, el
valor contenido en la dirección de memoria que representa el puntero). Por ejemplo, si pv es una
variable puntero que apunta a la variable v (es decir, pv es igual a &v), entonces *pv representa el
valor al que apunta la variable puntero pv (es decir, *pv es igual a v).
En el siguiente esquema se representa la relación entre v y pv mediante los operadores de
dirección e indirección:
19
3.154
65522pv=&v
*pv=v65522
65520
pv
3.154
65522&v
v
2. TIPOS DE DATOS Y EXPRESIONES
La declaración de una variable de tipo puntero requiere indicar el tipo del valor al que apuntará el
puntero y preceder al identificador del operador de indirección. En el ejemplo anterior, la
declaración de pv tanto en algoritmia como en C sería:
En algoritmia:
VARIABLES
*pv:real
En C:
float *pv;
2.5 REGLAS DE PRIORIDAD
A continuación se muestran las reglas de prioridad y el orden de evaluación de todos los
operadores vistos en este capítulo:
1. Funciones especiales
2. + (positivo), - (negativo), !, (tipo) (casting), &, * (indirección)
3. * (multiplicación), /, %
4. + (suma), - (resta)
5. <, >, <=, >=
6. ==, !=
7. &&
8. ||
Los operadores de la misma prioridad se aplicarán de izquierda a derecha, exceptos los
operadores unarios (!, +, -, (tipo), & y *) que se aplicarán de derecha a izquierda.
20
2. TIPOS DE DATOS Y EXPRESIONES
EJERCICIOS
1º) Indicar cuáles de los siguientes identificadores no son válidos:
a) _Id
b) 23
c) duración
d) Id-1
e) D/2
f) 3D
g) xXx
h) D3
i) μm
j) años
2º) Indicar cuáles de los siguientes literales son válidos y, de los válidos, de qué tipo son:
a) 432
b) 40,000
c) 2.7×10
d) -9.237
e) 5/3
f) 2,933
g) -87E-5
h) 3.5e+1
i) '9'
j) "A"
k) '\"'
l) 24e1.2
3º) Escribir las siguientes expresiones algebraicas como expresiones aritméticas en C, empleando
el menor número posible de paréntesis:
a) 8 x−3 x y
b) 20 ' 2 x224 ' 5 x−40
c) 2 y
2
− y−10
y2
d)
a 2 b
2 c
×
a c2
2b
b2 c
2 a
e)
3
2 a ba b
f)
25×10−4 x
2 y
g) q
3
q−2
h) b2−4a c
i) ln x1x2y 
j)
3,2
2
y
k) 2 lg
l)
2cos
1−tan2
4º) Escribir las siguientes expresiones aritméticas en C como expresiones algebraicas:
a) sqrt(x/y+x/z)
b) x+3/y+2
c) exp(-pow(1-2*x/a,2))
5º) Determinar el valor y tipo del resultado de las siguientes expresiones o decir si no son válidas:
a) sqrt(25)/2
b) pow(sqrt(9),2)
c) 44%(6/3.0)
d) 44%6/3.0
e) 16/5%3
f) 16/5*5
g) 16/5*(double) 5
h) 16/(double)5*5
i) !(floor(6.6)==ceil(5.3)) || *&p==p && ceil(5./3)==5/3
j) 4/2*3/6+fabs(6/2-pow(3,2))*2
k) "A" <= "B"
l) 6>2 && 5<4 || !(toupper(tolower('A'))=='A')
21
2. TIPOS DE DATOS Y EXPRESIONES
6º) Suponiendo la siguiente información en memoria, responder a las siguientes preguntas:
a) ¿Cuál sería el valor de *v2, si v2 vale &v1?
b) ¿Cuál sería el valor de *v2, si v2 vale v1?
c) ¿Cuál sería el valor de &v2, si v2 vale &v1?
d) ¿Cuál sería el valor de &v2, si v2 vale v1?
7º) Suponiendo la siguiente información en memoria, responder a las siguientes preguntas:
a) ¿Cuál sería el valor de *v3, si v3 vale &v1?
b) ¿Cuál sería el valor de *v3, si v3 vale v1?
c) ¿Cuál sería el valor de *v3, si v3 vale &v2?
d) ¿Cuál sería el valor de *v3, si v3 vale v2?
e) ¿Cuál sería el valor de &v3, si v3 vale &v1?
f) ¿Cuál sería el valor de &v3, si v3 vale &v2?
22
3
REPRESENTACIÓN GRÁFICA
DE LOS ALGORITMOS
Y SU TRADUCCIÓN A C
En el Capítulo 1 estudiamos que un algoritmo nos permite describir paso a paso el proceso
necesario para resolver un problema. La representación de un algoritmo se hace bien mediante texto
(pseudocódigo), bien mediante fórmulas, o bien de forma gráfica utilizando símbolos geométricos
en lo que se denominan diagramas.
La representación de algoritmos mediante diagramas es una forma clara e intuitiva de describir
los distintos pasos del método de resolución, su orden y su estructura. En este capítulo se tratará la
representación de los distintos elementos de un algoritmo mediante diagramas. Paralelamente, se
irán introduciendo las reglas sintácticas para traducir a lenguaje C cada uno de esos elementos.
3.1 MÉTODOS DE REPRESENTACIÓN ALGORÍTMICA
Las técnicas de programación tienen un papel primordial en el desarrollo del software. Una de
estas técnicas es la llamada programación estructurada, desarrollada por Edsger W. Dijkstra1 en
1972 y referida a un conjunto de directrices que aumentan considerablemente la productividad de
los programadores, reduciendo el tiempo requerido para escribir, depurar y mantener los programas.
La programación estructurada se basa en el Teorema de la Estructura, enunciado por Bohm y
Jacopini2 en 1966 y según el cual todo programa puede ser escrito utilizando solamente tres tipos de
estructuras básicas (también llamadas estructuras de control): secuenciales, selectivas y repetitivas.
Este teorema permite minimizar la complejidad de los métodos de resolución al reducir el juego de
estructuras empleado por los programas y facilitar así el seguimiento de la lógica de los mismos.
1 Edsger W. Dijkstra. Notes on structured programming, en Ole-Johan Dahl, Edsger W. Dijkstra y C. A. R. Hoare,
editores, Structured Programming. Academic Press, 1972.
2 Bohm, C. y Jacopini, G, Flow Diagrams, Turing Machines and Languages with Only Two Formation Rules,
Communications of the ACM, No. 5, Mayo 1966, págs. 366-371.
23 
3. LA REPRESENTACIÓN GRÁFICA DE LOS ALGORITMOS Y SU TRADUCCIÓN A C
Los diagramas estructurados son herramientas que permiten representar adecuadamente
algoritmos que respetan las reglas de la programación estructurada. Aunque existen diferentes
métodos, en este libro nos centraremos en el denominado método de Tabourier (Ilustración 1),
según el cual, todo diagrama estructurado comienza por un rectángulo dividido horizontalmente, en
cuya parte superior aparece el nombre del programa y en la inferior la palabra BLOCK. De este
rectángulo parten, unidos mediante líneas, los pasos que conforman el algoritmo encerrados en
rectángulos y rombos. La estructura arborescente resultante se recorre en preorden, es decir, de
izquierda a derecha y de arriba a abajo, de forma que la operación situada a la derecha de la actual
se examina sólo después de haber examinado todas las que “cuelgan” de dicha operación actual.
3.2 OPERACIONES PRIMITIVAS
Las operaciones primitivas son los elementos básicos de cualquier algoritmo o programa. Éstas,
junto con las estructuras de control que se estudiarán a continuación, nos permitirán construir
cualquier programa. En C, las instrucciones primitivas acaban todas en punto y coma (;), las
instrucciones de control, no.
3.2.1 LA OPERACIÓN DE ASIGNACIÓN
La operación de asignación permite almacenar valores en las variables. El operador de asignación
se representa en un algoritmo mediante el símbolo ←. El formato general de una operación de
asignación en un diagrama de Tabourier es:
identificador de variable ← expresión
Por ejemplo, la operación
edad ← 25
asigna a la variable de identificador edadel valor 25. Hay que tener en cuenta que el valor que la
variable pudiera contener antes de la asignación es sustituido por el nuevo.
24 
Ilustración 1: Un ejemplo de diagrama de Tabourier
21
3.1.2
3
3.1 3.2
3.1.1 3.3.23.3.1
4
3.3
Nombre del programa
BLOCK
3. LA REPRESENTACIÓN GRÁFICA DE LOS ALGORITMOS Y SU TRADUCCIÓN A C
El operador de asignación tiene menor prioridad que cualquier otro. Esto hace que en primer
lugar se calcule el valor de la expresión al lado derecho del operador, y en segundo lugar este valor
se almacene en la variable cuyo nombre aparece a la izquierda del operador de asignación.
Es posible utilizar el mismo identificador en ambos lados del operador de asignación, dando
lugar a operaciones de conteo o de acumulación. Por ejemplo,
total ← total + 1
será una operación de conteo que incrementa en 1 el valor de la variable total, mientras que
total ← total + incremento
será una operación de acumulación que incrementa el valor de la variable total en una cantidad igual
al valor almacenado en la variable incremento.
Una instrucción de asignación en C utiliza como operador de asignación el carácter igual (=) y
finaliza en punto y coma (;). Por ejemplo, edad=25; correspondería a la operación de asignación
anterior. Adviértase la diferencia entre este operador y el operador relacional “igual que” (==)
estudiado en el capítulo anterior. El primero asigna un valor a una variable, mientras que el segundo
compara dos valores para determinar si son iguales. Es habitual entre los programadores noveles
confundir ambos operadores.
En C, el tipo del valor obtenido al evaluar el lado derecho de una instrucción de asignación se
convertirá al tipo de la variable que se encuentra en el lado izquierdo, lo que puede provocar una
alteración del valor realmente almacenado (por ejemplo, al asignar el valor real 5.45 a una variable
de tipo entero, se almacenará el valor 5). Por ello, para evitar errores, es recomendable en general
que el dato que se asigna pueda almacenarse sin pérdidas en la variable especificada (por ejemplo,
el valor entero 5 podrá almacenarse sin pérdidas en una variable de tipo entero o de tipo real).
3.2.2 OPERACIONES DE ENTRADA
Las operaciones de entrada permiten leer valores desde un dispositivo de entrada (por ejemplo,
el teclado) y asignarlos a variables. Esta operación también se denomina operación de lectura,
indicando que el programa (el ordenador) va a leer cierta información del exterior (usuario).
En un diagrama de Tabourier, una operación de entrada desde teclado se representa:
En C, las operaciones de entrada se realizan fundamentalmente a través de la función scanf que
utilizaremos para asignar a variables valores de tipo simple (carácter, entero o real) introducidos por
teclado. Su archivo de cabecera es stdio.h, que debe incluirse mediante la instrucción
#include estudiada en capítulo anterior. La función scanf emplea el siguiente diagrama
sintáctico:
25 
leer
(id1, id2, ..., idN)
);,scanf( cadena de 
control
& id. variable 
tipo simple
3. LA REPRESENTACIÓN GRÁFICA DE LOS ALGORITMOS Y SU TRADUCCIÓN A C
La cadena de control debe contener un número de especificaciones de conversión igual al
número de identificadores de variables que le sucedan. Cuando hay más de una variable, las
especificaciones de conversión deben aparecer separadas entre sí por espacios y quedan asociadas
por orden a las correspondientes variables (la primera especificación de conversión con la primera
variable, la segunda con la segunda, etc.). Cada especificación de conversión es un grupo de
caracteres que indica el tipo de la variable correspondiente según la siguiente tabla:
Especificación
de conversión Tipo
%d int
%f float
%lf double
%c char
Obsérvese que cada identificador de variable viene precedido por el operador de dirección (&), es
decir, tras la cadena de control se indican las direcciones de las variables donde se almacenarán los
valores introducidos desde teclado.
Cuando se utiliza una misma instrucción para leer más de un valor numérico, éstos deben
introducirse desde teclado separados por una pulsación de la tecla Intro o espacios. Para finalizar la
entrada se pulsará la tecla Intro.
EJEMPLO 3.1. Dadas las variables grupo, habitantes y masa, declaradas como char, int y double,
respectivamente, podrán recibir valores desde el teclado utilizando la siguiente instrucción de entrada:
scanf("%c %d %lf", &grupo, &habitantes, &masa);
Los valores deberán introducirse desde teclado separados entre sí mediante la tecla Intro o espacios y la introducción
deberá finalizar con la tecla Intro, por ejemplo:
B 146832 1.9891e30
o bien
B
146832
1.9891e30
Obsérvese que en la instrucción scanf las especificaciones de conversión van separadas entre sí por espacios y que
cada identificador va precedido del carácter ampersand (&). Por otro lado, los valores reales podrá introducirlos el
usuario indistintamente en notación clásica o en notación exponencial.
Para la introducción desde teclado de cadenas de caracteres, emplearemos una función específica
para este propósito: la función gets. Para utilizarla se incluirá entre paréntesis el identificador de la
variable de tipo cadena a la que se asignará la cadena de caracteres introducida desde teclado. Para
evitar ciertos problemas cuando se emplea en combinación con la función scanf, cada llamada a
gets la precederemos de una llamada a la función fflush(stdin);, que borra el buffer de
teclado.
EJEMPLO 3.2. Dada la variable pelicula declarada como char[60], podrá recibir una cadena desde teclado
utilizando la siguiente instrucción de entrada:
fflush(stdin); gets(pelicula);
26 
3. LA REPRESENTACIÓN GRÁFICA DE LOS ALGORITMOS Y SU TRADUCCIÓN A C
La cadena deberá introducirse seguida de la tecla Intro, por ejemplo:
La Guerra de las Galaxias
Obsérvese que en la función gets el identificador ahora no va precedido del carácter ampersand (&).
3.2.3 OPERACIONES DE SALIDA
Las operaciones de salida (también llamadas de escritura) permiten visualizar el valor de
variables o expresiones a través de un dispositivo de salida (por ejemplo, el monitor).
En un diagrama de Tabourier, las operaciones de escritura sobre pantalla se representan:
En C, utilizaremos la función printf para mostrar por pantalla valores de cualquier tipo
(enteros, reales, caracteres y cadenas), cuyo archivo de cabecera es también stdio.h. Su diagrama
sintáctico es el siguiente:
En la instrucción printf, la cadena de control deberá contener una especificación de
conversión por cada expresión y además podrá contener otros caracteres cualesquiera (incluidas las
secuencias de escape vistas en el capítulo anterior) que se mostrarán por pantalla. El valor de las
expresiones se insertará en la cadena de control allí donde aparezca su correspondiente
especificación de conversión.
Las especificaciones de conversión más habituales con la instrucción printf y sus formatos de
salida asociados se muestran en la siguiente tabla:
Especificación
de conversión Tipo
%d int
%f float, double
(notación clásica)
%e float, double
(notación exponencial)
%g float, double
(notación clasica/exponencial dependiendo de la
precisión)
%c char
%s char []
27 
escribir
(exp1, exp2, ..., expN)
);
,
printf( cadena de 
control
expresión
3. LA REPRESENTACIÓN GRÁFICA DE LOS ALGORITMOS Y SU TRADUCCIÓN A C
EJEMPLO 3.3. Dadas las variables grupo, habitantes y masa declaradas como char, int y double,
respectivamente, y con los valores del Ejemplo 3.1, la siguiente instrucción de salida:
printf("Grupo=%c\nBadajoz=%d hab.\nMasa Sol=%e kg.\n",grupo,habitantes,masa);
generará las siguientes tres líneas en pantalla:
Grupo=B
Badajoz=146832 hab.
Masa Sol=1.989100e+30 kg.
Obsérvese que el valor de las variables se ha insertado en el lugar de las correspondientes especificaciones de
conversión dentro de lacadena de control.
En estas instrucciones los datos se visualizan con un determinado formato por defecto que
depende del tipo del dato. Por ejemplo, en el caso de los reales, las instrucciones
a=15.2;
printf("%f",a);
producirían el resultado
15.200000
mostrando por tanto el valor de la variable a con 6 dígitos decimales, aunque 5 de ellos no sean
significativos.
Para que la información pueda mostrarse de forma más clara, es posible añadir ciertos
modificadores a las especificaciones de conversión.
Uno de estos modificadores permite indicar el número mínimo de caracteres que ocupará en
pantalla el valor correspondiente. Cuando el valor a mostrar tenga menos caracteres que el número
de caracteres reservado, el valor será precedido de espacios hasta completar dicho número. Cuando
el valor tenga más caracteres que los reservados, el valor no aparecerá truncado, sino que se tomarán
los caracteres necesarios por la derecha. Este modificador se indica mediante un número situado
inmediatamente después del carácter % en la especificación de conversión correspondiente.
EJEMPLO 3.4. Dadas las variables grupo, habitantes y masa del ejemplo anterior, la siguiente instrucción de
salida:
printf("Grupo=%4c\nBadajoz=%5d hab.\nMasa Sol=%13e kg.\n",grupo,habitantes,masa);
generará las siguientes tres líneas en pantalla:
Grupo= B
Badajoz=146832 hab.
Masa Sol= 1.989100e+30 kg.
Obsérvese que el valor de grupo y de masa aparece precedido de 3 y 1 espacios para completar los 4 y 13
caracteres reservados, respectivamente. Sin embargo, aunque para habitantes se han reservado 5 caracteres y el valor
ocupa 6, se visualiza el dato completo.
En el caso de los valores reales, es posible indicar un modificador adicional que especifique el
número de dígitos decimales que se mostrarán por pantalla. El valor a mostrar se redondeará, si es
preciso, al número de decimales indicado por el modificador. Este modificador se incluirá en la
especificación de conversión mediante un punto seguido de un número entero, tras el carácter % (es
decir, %.entero) o, si se especifica el número mínimo de caracteres reservados, tras dicho número
(es decir, %entero.entero).
28 
3. LA REPRESENTACIÓN GRÁFICA DE LOS ALGORITMOS Y SU TRADUCCIÓN A C
EJEMPLO 3.5. Dada la variable masa del ejemplo anterior y la variable numeroPi de tipo float y valor
3.14159265, la siguiente instrucción de salida:
printf("Masa Sol=%.2e kg.\nNúmero PI=%8.4f\n",masa,numeroPi);
mostrará en pantalla las siguientes líneas:
Masa Sol=1.99e+30 kg.
Número PI= 3.1416
3.3 ESTRUCTURA DE UN PROGRAMA EN C
El esqueleto de un programa en C simple tiene el siguiente aspecto:
En este esqueleto encontramos los siguiente elementos:
• En primer lugar se sitúan las instrucciones #include correspondientes a los archivos de
cabecera de las funciones internas que se vayan a utilizar en el programa, seguido de la
definición de las constantes simbólicas (si hubiera alguna), según se estudió en el Capítulo 2.
• La siguiente línea int main() es la cabecera de la función principal, por donde todo
programa comienza a ejecutarse, y el contenido de dicha función se encuentra a continuación
entre llaves. El significado de su sintaxis se explicará en el Capítulo 5.
• La declaración de variables deberá incluir todas las variables utilizadas en el programa,
según la sintaxis estudiada en el Capítulo 2.
• Finalmente, se incluirán las instrucciones ejecutables correspondientes a la traducción de los
pasos del algoritmo representados en el diagrama de Tabourier, seguidas por la instrucción
return 0 para finalizar la ejecución del programa.
EJEMPLO 3.6. El siguiente programa en C permite calcular y mostrar por pantalla la suma de dos números enteros
leídos desde teclado.
#include <stdio.h>
int main()
{
 int s1,s2,result;
 printf("Introduzca dos números enteros: ");
 scanf("%d %d",&s1,&s2);
 result=s1+s2;
 printf("La suma de %d más %d es %d.\n",s1,s2,result);
 return 0;
}
29 
inclusión de archivos de cabecera (#include)
definición de constantes (#define)
int main()
{
 declaración de variables
 instrucciones del programa
 return 0;
}
3. LA REPRESENTACIÓN GRÁFICA DE LOS ALGORITMOS Y SU TRADUCCIÓN A C
3.4 ESTRUCTURAS DE CONTROL
A continuación, se estudiará el significado y la representación de las estructuras básicas de la
programación estructurada (secuenciales, selectivas y repetitivas), así como las distintas variantes
que existen.
3.4.1 ESTRUCTURA SECUENCIAL
Es aquélla en la que todas las acciones que la componen se ejecutan exactamente una vez. La
figura siguiente representa una estructura secuencial:
EJEMPLO 3.7. Realizar un programa que calcule el perímetro y el área de un rectángulo a partir de la base y la
altura dadas por el usuario.
ANÁLISIS:
a) Datos de entrada:
 bas: base del rectángulo. Teclado. (bas > 0)3
 alt: altura del rectángulo. Teclado. (alt > 0)3
b) Datos de salida:
 per: perímetro del rectángulo. Monitor.
 area: área del rectángulo. Monitor.
DISEÑO:
a) Parte declarativa:
VARIABLES
bas,alt,per,area:real
b) Representación algorítmica:
3 Dado que aún no se han estudiado las estructuras que permitirán realizar el control de entrada correspondiente a
estas restricciones, dicho control se omitirá excepcionalmente en la representación algorítmica de este ejemplo.
30 
3 ... n21
BLOCK
rectangulo
BLOCK
escribir
("Base y altura:")
leer
(bas,alt)
per←2bas+2alt area←basalt escribir
(per,area)
3. LA REPRESENTACIÓN GRÁFICA DE LOS ALGORITMOS Y SU TRADUCCIÓN A C
CODIFICACIÓN:
/************************************************/
/* Muestra el perímetro y área de un rectángulo */
/************************************************/
#include <stdio.h>
int main()
{
 float bas,alt,per,area;
 printf("Introduzca la base y la altura del rectángulo: ");
 scanf("%f %f",&bas,&alt);
 per=2*bas+2*alt; /* Perímetro del rectángulo */
 area=bas*alt; /* Area del rectángulo */
 printf("Su perímetro es %.2f y su área %.2f\n",per,area);
 return 0;
}
3.4.2 ESTRUCTURAS SELECTIVAS
La estructura secuencial es típica de los algoritmos que pueden llevarse a cabo con una
calculadora básica, ya que todas las instrucciones introducidas se ejecutan exactamente una vez. El
empleo de ordenadores para la ejecución de algoritmos cobra mayor sentido cuando en ellos se
describe algo más que una mera secuencia de acciones. Este es el caso cuando el siguiente paso a
ejecutar depende del valor de una expresión.
En las estructuras selectivas se evalúa una expresión y en función de su resultado se determina
cuál será el siguiente paso. La acción asociada a cada una de las alternativas consideradas en la
estructura selectiva se denomina cuerpo de dicha alternativa.
ESTRUCTURA SELECTIVA SIMPLE (IF-THEN)
Esta estructura restringe la ejecución de una acción al cumplimiento de una condición. Su
representación en un diagrama de Tabourier es la siguiente:
En la ejecución de una estructura selectiva simple, en primer lugar se evalúa la condición. Si el
resultado de la expresión lógica es verdadero se ejecuta la acción indicada; en caso contrario, no se
ejecuta.
EJEMPLO 3.8. La siguiente porción de algoritmo expresa que la operación de asignación se ejecutará solo si la
variable x es mayor que 0.
31 
if then
positivo ← 1x > 0
if then
acciónexpresión
lógica
3. LA REPRESENTACIÓN GRÁFICA DE LOS ALGORITMOS Y SU TRADUCCIÓN A C
Es posible que la acción a realizar si se cumple la condición sea una acción compuesta, esto es,
que conste de varios pasos más simples. Una acción compuesta en un diagrama de Tabourier se
representará mediante una estructura secuencial:
Por tanto, una estructura selectiva simple cuando contiene una acción compuesta se representará
en un diagrama de Tabourier de la siguiente forma:
En C, cuando el cuerpo de una estructura selectiva simple consiste en una acción sencilla (es
decir, una sola instrucción), se utiliza el siguientediagrama sintáctico:
Las acciones compuestas en C emplean el diagrama sintáctico:
Por tanto, la estructura selectiva simple, cuando contiene una acción compuesta, utilizará el
diagrama sintáctico siguiente:
EJEMPLO 3.9. A partir de dos números reales introducidos por teclado, mostrar el resultado de la división si el
divisor es distinto de 0.
ANÁLISIS:
a) Datos de entrada:
 ddo: Dividendo. Teclado.
 dsor: Divisor. Teclado.
b) Datos de salida:
 coc (sólo si dsor ≠ 0): Cociente de la división. Monitor.
DISEÑO:
a) Parte declarativa:
VARIABLES
coc,ddo,dsor:real
32 
expresión 
lógica
if ( ) instrucción
if then
BLOCKexpresión
lógica
paso 1 paso 2 paso n...
instrucción{ }
expresión 
lógica
if ( ) instrucción{ }
BLOCK
paso 1 paso 2 paso n...
3. LA REPRESENTACIÓN GRÁFICA DE LOS ALGORITMOS Y SU TRADUCCIÓN A C
CODIFICACIÓN:
/***************************/
/* Cálculo de una división */
/***************************/
#include <stdio.h>
int main()
{
 float ddo,dsor,coc;
 printf("Introduzca el dividendo y el divisor: ");
 scanf("%f %f",&ddo,&dsor);
 if (dsor != 0) /* solo se calcula si el divisor no es cero */
 {
 coc=ddo/dsor;
 printf("El resultado de la división es %.2f\n",coc);
 }
 return 0;
}
ESTRUCTURA SELECTIVA DOBLE (IF-THEN-ELSE)
La estructura anterior es inadecuada para representar la selección de alternativas cuando se
requiere que el algoritmo seleccione entre dos posibles acciones en función del resultado de una
condición, de forma que si la condición se cumple se seleccione una alternativa y en caso contrario
se seleccione la otra. La estructura selectiva doble nos permite representar más adecuadamente esta
situación.
Por lo tanto, una estructura selectiva doble deberá emplearse cuando se presenten dos alternativas
de actuación mutuamente excluyentes que dependan del resultado de una misma condición.
En un diagrama de Tabourier, esto se representará:
33 
division
BLOCK
escribir
("Dividendo
y divisor:")
leer
(ddo,dsor)
escribir(coc)
if then
BLOCKdsor ≠ 0
coc ← ddo/dsor
if then else
acción 1expresión
lógica
acción 2
3. LA REPRESENTACIÓN GRÁFICA DE LOS ALGORITMOS Y SU TRADUCCIÓN A C
Si la expresión lógica toma valor verdadero, se ejecutará la acción 1; si toma valor falso, se
ejecutará la acción 2. Al igual que en las estructuras selectivas simples, las acciones de una
estructura selectiva doble pueden ser compuestas, en cuyo caso se representarán del modo descrito
anteriormente para la estructura selectiva simple.
En C, el diagrama sintáctico correspondiente a la estructura selectiva doble es el siguiente:
donde bloque de sentencias se refiere de forma genérica a una única acción simple o a una acción
compuesta, aplicándose en este último caso el diagrama sintáctico para acciones compuestas
estudiado anteriormente.
EJEMPLO 3.10. Indicar si, dado un número por teclado, este es par o impar.
ANÁLISIS:
a) Datos de entrada:
 n: Número entero. Teclado.
b) Datos de salida:
 paridad: Mensaje indicando la paridad del número n. Monitor
DISEÑO:
a) Parte declarativa:
VARIABLES
n: entero
CODIFICACIÓN:
/***************************************/
/* Muestra si un número es par o impar */
/***************************************/
#include <stdio.h>
int main()
{
 int n;
 printf("Introduzca un número entero: ");
 scanf("%d",&n);
 if (n % 2 == 0) /* un número es par si al dividir entre 2 da resto 0 */
 printf("El número es PAR\n");
 else
 printf("El número es IMPAR\n");
 return 0;
}
34 
expresión 
lógica
if ( ) bloque de 
sentencias
else
bloque de 
sentencias
paridad
BLOCK
escribir
("Un nº:")
leer (n) if then else
resto(n,2)=0 escribir
("Es par")
escribir
("Es impar")
3. LA REPRESENTACIÓN GRÁFICA DE LOS ALGORITMOS Y SU TRADUCCIÓN A C
ESTRUCTURA SELECTIVA MÚLTIPLE (SWITCH)
A menudo, en la resolución de un problema se presentan más de dos alternativas que dependen
de una misma circunstancia, por ejemplo, del día de la semana en el que nos encontramos. Esto
podría resolverse usando estructuras selectivas dobles encadenadas, pero generaría un código poco
legible y de difícil escritura si el número de alternativas es grande.
La estructura selectiva múltiple permite seleccionar una alternativa de entre varias posibles, en
función del resultado de una expresión de tipo entero o de tipo carácter. En un diagrama de
Tabourier, esta estructura se representa de la siguiente forma:
Las listas lista 1, lista 2, ..., lista n contendrán el o los valores asociados a la alternativa
correspondiente, separados por comas si son varios. La cláusula default es opcional y se usará
cuando una alternativa englobe a los valores de la expresión que no se han indicado explícitamente.
En C, el diagrama sintáctico de la estructura selectiva múltiple es:
Cada valor de una misma lista se representa mediante un par case-expresión acabado en dos
puntos (:). Tras la lista, se sitúa el bloque de sentencias correspondiente a la acción asociada.
Obsérvese que se utiliza una instrucción break; para separar cada par lista-acción de la siguiente
y, si está presente, del par default-acción.
EJEMPLO 3.11. Se desea diseñar un algoritmo que escriba por pantalla la duración en días correspondiente al mes
cuyo número de orden se indique por teclado o un mensaje de error si dicho valor no está en el intervalo [1,12].
ANÁLISIS:
a) Datos de entrada:
 mes: Número de orden del mes. Teclado.
b) Datos de salida:
 dias: Mensaje indicando el número de días que tiene mes o un mensaje de error. Monitor
DISEÑO:
a) Parte declarativa:
VARIABLES
mes:entero
35 
switch
acción 1expresión acción 2 acción n acción d...
lista 1 lista 2 lista n default
expresiónswitch ( ) bloque de 
sentencias
default
{ case expresión :
break;
bloque de 
sentencias
}
3. LA REPRESENTACIÓN GRÁFICA DE LOS ALGORITMOS Y SU TRADUCCIÓN A C
CODIFICACIÓN:
/****************************************************************************/
/* Muestra la duración en días correspondiente al número de orden de un mes */
/****************************************************************************/
#include <stdio.h>
int main()
{
 int mes;
 printf("Introduzca el número de orden del mes: ");
 scanf("%d",&mes);
 switch (mes)
 {
 case 1:
 case 3:
 case 5:
 case 7:
 case 8:
 case 10:
 case 12:
 printf("31 días\n");
 break;
 case 4:
 case 6:
 case 9:
 case 11:
 printf("30 días\n");
 break;
 case 2: /* depende de si el año es o no bisiesto */
 printf("28 o 29 días\n");
 break;
 default:
 printf("Error: el valor no corresponde a ningún mes.\n");
 }
 return 0;
}
3.4.3 ESTRUCTURAS REPETITIVAS
Otro tipo de estructura de control es aquélla que describe la repetición de una acción un número
de veces a priori determinado o indeterminado. Estas estructuras se denominan estructuras
repetitivas o bucles y se llama iteración a cada una de las ejecuciones de la acción en el bucle.
El conjunto de pasos que constituye la acción que se repite se denomina cuerpo del bucle. Aparte
del cuerpo del bucle, será necesario también establecer una condición de parada que determine el
número de veces que el cuerpo del bucle se ejecutará (el número de iteraciones). Esta condición se
localizará al comienzo o al final de bucle y podrá indicarse de distintos modos, dando lugar a tres
tipos distintos de estructuras repetitivas: while-do, do-while y for-do.
36 
duracionMes
BLOCK
escribir
("Mes:")
leer (mes) switch
mes
escribir
("31 días")
escribir
("30 días")
escribir
("28 o 29 días")
escribir
("Error")
default
1,3,5,7,8,10,12 4,6,9,11 2
3. LA REPRESENTACIÓN GRÁFICA DE LOS ALGORITMOS Y SU TRADUCCIÓN A C
ESTRUCTURA REPETITIVA WHILE-DO
En ella, el cuerpo del bucle se repite mientras se cumpla una determinada condición. Su
representación en un diagrama de

Continuar navegando