Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Fundamentos de
tiene dos partes diferenciadas.
En la primera parte se definen los conceptos fundamentales
que se aplican en cualquier programa de ordenador reali-
zado mediante lenguajes de programación estructurados
la programación.
Fundamentos de la programación
programas de ordenador y aplicar conceptos que son válidos
para cualquier lenguaje de programación estructurada.
Más en concreto, se espera que el lector pueda aprender David Lizcano Casas (coord.)
a definir algoritmos, implementar estructuras de datos y
determinar la eficiencia de los programas realizados. Fernando Alonso Amo
Loïc Antonio Martínez Normand
José Luis Fuertes Castro
902 02 00 03
www.udima.es
Ediciones
Ediciones
1/1
Fundamentos de
la programación.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
SUMARIO
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
PÁGINA
Prólogo........................................................................................................ 7
www.udima.es 5
FUNDAMENTOS DE LA PROGRAMACIÓN
6 www.udima.es
PRÓLOGO
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
www.udima.es 7
FUNDAMENTOS DE LA PROGRAMACIÓN
del algoritmo en un programa informático que pueda ser comprensible para la computa-
dora. A tal efecto, se utilizará un lenguaje de programación que transforme el algoritmo
en un programa informático. La ejecución del programa proporcionará unos resultados
que permitirán comprobar la bondad de los mismos o la existencia de errores, que será
preciso eliminar modificando el algoritmo y, consecuentemente, el programa informá-
tico desarrollado.
Cabe señalar que todos estos fundamentos de la programación que definen la resolu-
ción de un problema mediante técnicas informáticas son expuestos en este manual de un
modo muy didáctico y sin necesidad de conocimientos previos sobre la materia informática.
Antes de plantear los conceptos que definen un programa informático, los autores
describen previamente qué es una computadora y con ello dan una visión completa de
todo el proceso informático. Asimismo, han escogido como lenguaje de programación
el C++, lenguaje muy didáctico gracias al cual se pueden aprender otros lenguajes con
gran facilidad, como C#, Java, Visual Basic, JavaScript o PHP, entre otros. Por otra parte,
C++ es un lenguaje muy flexible que permite programar con múltiples estilos y es apre-
ciado por la eficiencia de su código; por ello, es uno de los lenguajes de programación
más populares para crear aplicaciones y software de sistemas.
En resumen, los autores han sabido plasmar en sus diez unidades didácticas de un
modo sencillo la descripción de cada fundamento de la programación, acompañados de
ejemplos que permiten al lector asimilarlos fácilmente.
8 www.udima.es
1
UNIDAD
DIDÁCTICA
CONCEPTO DE
PROGRAMA INFORMÁTICO
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Objetivos de la unidad
5. Estructuras de control
5.1. Secuencia
5.2. Condiciones
5.2.1. Estructura condicional simple
5.2.2. Estructura condicional doble
5.2.3. Estructura condicional múltiple
Conceptos básicos
www.udima.es 9
FUNDAMENTOS DE LA PROGRAMACIÓN
Actividades de autocomprobación
Actividades de repaso
Referencias bibliográficas
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
10 www.udima.es
OBJETIVOS DE LA UNIDAD
En esta primera unidad didáctica se abordan los conceptos básicos que son necesa-
rios conocer y comprender para trabajar con el resto de unidades didácticas. Para ello,
se comienza introduciendo el concepto de computadora como máquina capaz de realizar
operaciones aritméticas y lógicas sobre unos datos.
Para que una computadora pueda ejecutar un programa, este debe estar escrito en
su propio lenguaje, el lenguaje máquina, que es un lenguaje muy poco adecuado para
las personas. Por esta razón, en programación se utilizan lenguajes de alto nivel, que son
más cercanos a los seres humanos.
Sin embargo, antes de programar usando uno de estos lenguajes es necesario des-
cribir de forma abstracta y no ambigua lo que tiene que hacer el programa. Para eso se
utilizan los lenguajes de pseudocódigo. En esta unidad didáctica se recogen las reglas
generales de este tipo de lenguajes, así como los tipos de estructura de control que
permiten: secuencia, condiciones (simple, doble y múltiple) y repeticiones (Mientras,
Hasta, Para).
www.udima.es 11
FUNDAMENTOS DE LA PROGRAMACIÓN
A este respecto, hay que destacar el esfuerzo desarrollado en el campo del trata-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Sin embargo, las computadoras no son solo meras herramientas de cálculo, sino que
tienen además la función de efectuar operaciones razonables (lógicas y matemáticas) sobre
la información significativa. Es decir, realizan automáticamente operaciones lógicas y
matemáticas a partir de una información de entrada y según una secuencia predetermi-
nada de instrucciones y entregan unos resultados. Esa secuencia de instrucciones recibe
el nombre de programa (véase epígrafe 3).
Las instrucciones que puede ejecutar una computadora son muy simples: operaciones
matemáticas (sumas, restas, multiplicaciones, etc.), comparaciones (igualdad, mayor que,
menor que, etc.), movimientos de información de un lugar a otro, etc. La computadora
puede realizar esas instrucciones en el momento en que se le ordene y en la forma en que
se le indique.
Es decir, el secreto de las computadoras reside en su capacidad para ejecutar las ins-
trucciones incluidas en los programas. Ahora bien, para ello es necesario que una persona
escriba el programa destinado a resolver un problema. Esta persona recibe el nombre de
programador, quien será también el encargado de hacer un estudio del problema que se
quiere resolver para poder obtener dicho programa, es decir, el conjunto de instrucciones
adecuadas para resolver el problema.
12 www.udima.es
Con ella se pueden llevar a cabo trabajos como el proceso de datos, en el que la
máquina mecaniza y automatiza una serie de tareas rutinarias que realizadas manual-
mente consumirían una gran cantidad de tiempo, aunque no fuera necesario prestar toda
la atención al realizarlas.
CPU
Programa
Teniendo esto en cuenta, las instrucciones que procesa una computadora (es decir,
su CPU) se pueden clasificar en los siguientes tipos:
www.udima.es 13
FUNDAMENTOS DE LA PROGRAMACIÓN
2. LA PROGRAMACIÓN
14 www.udima.es
En este caso, una computadora puede ser de gran ayuda, ya que bastaría con escribir
un programa que se cargase en su interior y al ejecutarse fuera leyendo uno a uno los
números y fuera seleccionando el menor y el mayor, de forma que, al leer el último
número, el programa mostrara en la pantalla de la computadora los resultados deseados:
el número menor y el número mayor que ha leído.
Si, además, se pide listar aquellos números que son primos, es decir, que solo son
divisibles por sí mismos y por la unidad, su resolución manual sería inmensamente labo-
riosa. De nuevo, un programa informático podría realizar esta tarea de forma sencilla.
Se ve, pues, que las computadoras, por medio de los programas informáticos,
resuelven en cuestión de segundos o de minutos problemas que para el ser humano exi-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Programa
Problema Resultados
Datos de
entrada
Así, en el caso del ejemplo anterior, que consistía en obtener los números menor y
mayor leídos, así como los números primos, la representación gráfica de la resolución
del problema usando una computadora sería la recogida en la figura 3.
www.udima.es 15
FUNDAMENTOS DE LA PROGRAMACIÓN
Programa
Leer números,
calcular menor,
mayor y primos
Problema Resultados
Obtener el menor, Primos: 1,13
el mayor y los Menor: – 7
números primos Mayor: 148
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Datos
4, 1, – 7, 148,
25, 13, 16, ...
3. CONCEPTO DE PROGRAMA
El programa parte de unos datos iniciales o datos de entrada (en el caso de la lavadora,
el estado inicial es que la ropa está sucia). A medida que la computadora va ejecutando el
programa, se obtienen unos valores intermedios (la ropa pasa por estados diferentes: con
agua, con detergente, etc.). Finalmente, se alcanza el resultado final (la ropa queda limpia).
16 www.udima.es
Así, en el caso del ejemplo anterior que selecciona los números menor y mayor que se
han leído y que, además, obtiene aquellos que sean números primos positivos, el programa,
llamado MAXMIN-PRIMOS, podría consistir en la siguiente secuencia de instrucciones:
/* MAXMIN-PRIMOS */
Inicio
MENOR = el mayor número posible
MAYOR = el menor número posible
Leer un número (NUM)
Mientras se haya leído un número
/* Comprueba si NUM es el menor o el mayor de todos los números
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
leídos hasta ahora y actualiza MENOR y MAYOR según corresponda */
Si NUM < MENOR
Entonces
MENOR = NUM
Fin_si
Si NUM > MAYOR
Entonces
MAYOR = NUM
Fin_si
/* Comprobar si NUM es primo. Si lo es mostrarlo en pantalla */
Si NUM > 0
Entonces
I = 2
Mientras NUM no sea divisible por I y I < NUM
I = I + 1
Fin_mientras
Si I = NUM o NUM = 1
Entonces
Escribir NUM " es primo."
Fin_si
Si no
Escribir NUM " no es positivo."
Fin_si
/* Leer el siguiente número */
Leer otro número (NUM)
Fin_mientras
/* Ahora se muestran los resultados (MENOR y MAYOR) */
Escribir "El menor de todos es: " MENOR
Escribir "El mayor de todos es: " MAYOR
Fin
www.udima.es 17
FUNDAMENTOS DE LA PROGRAMACIÓN
El proceso anterior finaliza cuando no hay más números que leer. En este caso, el
programa escribe el menor y el mayor de todos los leídos y finaliza.
.../...
18 www.udima.es
.../...
NUM < MENOR → sí 4
NUM > MAYOR → sí 4
I = 2
…
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
NUM < MENOR → sí – 7
NUM > 0 → no –7 no es positivo.
NUM < MENOR → no
NUM > MAYOR → sí 13
NUM > 0 → sí
I = 2
I = 3, 4, …, 12
13 es primo.
NUM divisible por 3, 4, …, 12 → no
El menor de todos es: – 7
El mayor de todos es: 13
www.udima.es 19
FUNDAMENTOS DE LA PROGRAMACIÓN
> 4
> ‒ 7
‒ 7 no es positivo.
> 13
13 es primo.
> FIN
El menor de todos es: ‒ 7
El mayor de todos es: 13
computadoras solo entienden un lenguaje binario (es decir, formado por ceros y unos)
que es denominado «lenguaje máquina». Este lenguaje máquina es diferente para cada
modelo de computadora; cada computadora solo entiende y acepta su propio lenguaje
máquina.
4. EL PSEUDOCÓDIGO
20 www.udima.es
guaje muy útil para diseñar programas ya que permite expresar lo que se quiere hacer de
una forma clara, precisa, sin ambigüedad y usando un lenguaje natural. Es una forma
de describir la solución a un problema de manera que su posterior traducción a un len-
guaje de programación de alto nivel sea sencilla.
Debe señalarse que existen notaciones gráficas que pueden utilizarse con el mismo
fin que el pseudocódigo. Estas notaciones se presentarán en la unidad didáctica 2.
en gran medida del criterio del programador. No obstante, es aconsejable respetar lo más
rigurosamente posible las siguientes pautas de carácter general:
Cuando se diseña un programa, interesa describir lo que hace de una forma clara,
precisa y sin ambigüedades. Para tal fin, el pseudocódigo utiliza un lenguaje muy apro-
piado para describir las tres estructuras básicas de control que se utilizan en un programa,
como son la estructura secuencial, la condicional y la repetitiva. En los siguientes epí-
grafes se describirán dichas estructuras básicas de control.
www.udima.es 21
FUNDAMENTOS DE LA PROGRAMACIÓN
5. ESTRUCTURAS DE CONTROL
5.1. SECUENCIA
Por ejemplo, supóngase que se quiere calcular la suma y el producto de dos números.
El programa resultante es muy simple. Lo primero que tiene que hacer es leer dos nú-
meros, A y B. Después, tiene que sumarlos y luego multiplicarlos. Por último, el pro-
grama debe mostrar los resultados en la pantalla de la computadora.
Inicio
Leer A y B
SUMA = A + B
PRODUCTO = A * B
Mostrar SUMA, PRODUCTO
Fin
5.2. CONDICIONES
22 www.udima.es
...
Si condición
Entonces
Acción 1
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Acción 2
...
Acción n
Fin_si
...
Por ejemplo, si el problema que se quiere resolver consiste en leer por teclado un
número, que se denominará NUM, y visualizarlo en la pantalla solo si es mayor que 20, se
tendría el siguiente pseudocódigo:
Inicio
Leer un número (NUM)
Si NUM > 20
Entonces
Mostrar NUM
Fin_si
Fin
En el ejemplo se señala que si, y solo si, el valor NUM es mayor que 20, se debe mos-
trar este valor; pero si no se cumple la condición, no se hace nada.
Obsérvese que las instrucciones están tabuladas hacia la derecha respecto a las
palabras Si y Fin_si. Esto tiene por objeto realzar las instrucciones que pertenecen
a la estructura. Esta norma de «indentación» se aplica a todas las demás estructuras
de control del pseudocódigo, tal y como se ha comentado en las normas generales del
pseudocódigo.
www.udima.es 23
FUNDAMENTOS DE LA PROGRAMACIÓN
...
Si NUM > MAYOR
Entonces
MAYOR = NUM
Fin_si
...
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
...
Si I = NUM o NUM = 1
Entonces
Escribir NUM " es primo."
Fin_si
...
En este tipo de estructura condicional hay dos posibles bloques de instrucciones para
ejecutar. Se ejecutará uno u otro dependiendo de que la condición sea cierta o falsa. Si
la condición es cierta, se ejecutará el bloque de instrucciones de Entonces. Si la condi-
ción es falsa, se ejecutará el bloque de instrucciones de Si no. El pseudocódigo de esta
variante es:
...
Si condición
Entonces
Acción 1
Acción 2
...
Acción n
24 www.udima.es
Si no
Acción a
Acción b
...
Acción z
Fin_si
...
Por ejemplo, programa que lee dos números y selecciona y visualiza el mayor:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Inicio
Leer A y B
Si A > B
Entonces
Mostrar "El mayor es: " A
Si no
Mostrar "El mayor es: " B
Fin_si
Fin
El programa así diseñado es ilustrativo del uso de la estructura condicional doble, pero
no es totalmente correcto debido a que ambos números podrían ser iguales, y no se con-
templa esta posibilidad (si A y B fueran iguales, el programa indicaría que el mayor es B).
En la siguiente estructura de control se comentará una posible solución de este problema.
...
Si NUM < MENOR
Entonces
MENOR = NUM
www.udima.es 25
FUNDAMENTOS DE LA PROGRAMACIÓN
Si no
...
Fin_si
...
...
Si NUM > 0
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Entonces
I = 2
...
Si no
Escribir NUM " no es positivo."
Fin_si
...
En este caso, dependiendo del valor que tome la expresión que controla la estruc-
tura de control (que puede ser numérica o de otro tipo), se ejecutará uno de los posibles
grupos de acciones definidos en la estructura. La estructura condicional múltiple también
permite indicar qué acciones deben ejecutarse cuando el valor de la expresión no coin-
cida con ninguno de los recogidos de forma explícita. El pseudocódigo de esta variante
de la estructura condicional es el siguiente:
...
Según expresión
= 1 Secuencia de acciones 1
= 2 Secuencia de acciones 2
...
= n Secuencia de acciones n
En otro caso
Secuencia de acciones
Fin_según
...
26 www.udima.es
Por ejemplo: programa que lee desde el teclado un valor numérico, denominado
NUM_CARTA, asociado a una carta de una baraja española (del 1 al 12), y muestra en pan-
talla el nombre de la carta asociado a ese número. Si el número de la carta está fuera de
rango, se muestra un mensaje de error:
Inicio
Leer NUM_CARTA
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Según NUM_CARTA
= 1 Mostrar "As"
= 2 Mostrar "Dos"
= 3 Mostrar "Tres"
= 4 Mostrar "Cuatro"
= 5 Mostrar "Cinco"
= 6 Mostrar "Seis"
= 7 Mostrar "Siete"
= 8 Mostrar "Ocho"
= 9 Mostrar "Nueve"
= 10 Mostrar "Sota"
= 11 Mostrar "Caballo"
= 12 Mostrar "Rey"
En otro caso
Mostrar "Número de carta no válido: " NUM_CARTA
Fin_según
Fin
www.udima.es 27
FUNDAMENTOS DE LA PROGRAMACIÓN
Inicio
Leer A
Leer B
Si A > B
Entonces
Mostrar "El mayor es: " A
Si no
Si A < B
Entonces
Mostrar "El mayor es: " B
Si no
Mostrar "A y B son iguales"
Fin_si
Fin_si
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Fin
Inicio
Leer A
Leer B
Según Comparación(A, B)
= 1 Mostrar "El mayor es: " A
= - 1 Mostrar "El mayor es: " B
= 0 Mostrar "A y B son iguales"
Fin_según
Fin
28 www.udima.es
...
Mientras condición
Acción 1
Acción 2
...
Acción n
Fin_mientras
...
Por ejemplo: una empresa almacena los datos personales de sus empleados. Se desea
desarrollar un programa que muestre en pantalla el nombre de todos aquellos empleados
que sean mayores de 55 años.
Inicio
Leer Empleado
Mientras haya_empleado
Si edad de Empleado > 55
Entonces
Mostrar nombre de Empleado
Fin_si
Leer Empleado
Fin_mientras
Fin
www.udima.es 29
FUNDAMENTOS DE LA PROGRAMACIÓN
Mientras:
• La primera, que abarca casi todo el programa, lee un número mientras haya
números y ejecuta todo el proceso:
/* MAXMIN-PRIMOS */
Inicio
...
Leer un número (NUM)
Mientras se haya leído un número
...
Fin_mientras
/* Ahora se muestran los resultados (MENOR y MAYOR) */
...
Fin
...
Mientras NUM no sea divisible por I y I < NUM
I = I + 1
Fin_mientras
...
30 www.udima.es
...
Repetir
Acción 1
Acción 2
...
Acción n
Hasta condición
...
Inicio
CONT = 0
Repetir
CONT = CONT + 1
PROD = CONT * 4
Mostrar "4 * " CONT " = " PROD
Hasta CONT = 10
Fin
Para resolver este problema se necesitan dos variables: CONT, que es un contador
que almacena cuantos números se han visualizado (es la variable que contiene la condi-
ción de salida del bucle); y PROD, que almacena el valor del número que se debe mostrar
y que corresponde a los números de la tabla de multiplicar del 4.
www.udima.es 31
FUNDAMENTOS DE LA PROGRAMACIÓN
Para dicho control hay que definir dentro de la estructura el nombre de una variable
(normalmente denominada «contador»), su valor inicial, su valor final y un incremento
fijo. Ello quiere decir que, inicialmente, el bloque de acciones se ejecuta con el valor
inicial de la variable; este valor se incrementa en cada iteración con el valor del incre-
mento y las iteraciones finalizan cuando el valor de la variable sobrepasa su valor final.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
...
Para VAR desde VI hasta VF incremento INC
Acción 1
Acción 2
...
Acción n
Fin_para
...
Inicio
SUMA = 0
Para NUM desde 1 hasta 100
SUMA = SUMA + NUM
Fin_para
Mostrar SUMA
Fin
32 www.udima.es
En el ejemplo se utiliza la variable SUMA para almacenar la suma de los 100 primeros
números y la variable NUM para controlar el bucle. Este empieza en I y llega hasta 100 con
incremento 1, y cuando NUM sobrepasa el valor 100, indica que ya se han sumado todos los
números, con lo que el bucle de tipo Para termina y en SUMA se tendrá el valor buscado.
Así, el ejemplo anterior desarrollado con una estructura de tipo Mientras, daría
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Inicio
SUMA = 0
NUM = 1
Mientras NUM <= 100
SUMA = SUMA + NUM
NUM = NUM + 1
Fin_mientras
Mostrar SUMA
Fin
www.udima.es 33
FUNDAMENTOS DE LA PROGRAMACIÓN
CONCEPTOS BÁSICOS
• Programación. Proceso de planificar y desarrollar la resolución de un pro-
blema mediante una computadora. El resultado de la programación es un
programa que será ejecutado por una computadora para resolver el problema.
• Programa. Secuencia de instrucciones codificadas de una forma determi-
nada y registradas en un soporte informático. Al ejecutarlo, la computadora
realiza una serie de operaciones preestablecidas para resolver el problema.
• Lenguaje de pseudocódigo. Mezcla de castellano y expresiones matemá-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1
a) Construir un algoritmo.
b) Construir un programa.
c) Construir un lenguaje de programación.
d) Planificar y desarrollar la resolución del problema.
Enunciado 2
El pseudocódigo es:
a) Un lenguaje informático.
b) Un conjunto de expresiones.
34 www.udima.es
Enunciado 3
a) Secuencial.
b) Condicional.
c) Tipo Para.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
d) Tipo Según.
Enunciado 4
Enunciado 5
www.udima.es 35
FUNDAMENTOS DE LA PROGRAMACIÓN
Solución 1
b) Construir un programa.
Solución 2
Solución 3
d) Tipo Según.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Solución 4
Solución 5
ACTIVIDADES DE REPASO
Enunciado 1
36 www.udima.es
Enunciado 2
Enunciado 3
Inicio
Leer N
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Si N < 0 o N no es entero
Entonces
Mostrar "No se puede realizar el cálculo"
Si no
I = 0
R = 1
Mientras I < N
I = I + 1
R = R * I
Fin_mientras
Mostrar "El resultado es: " R
Fin_si
Fin
www.udima.es 37
FUNDAMENTOS DE LA PROGRAMACIÓN
Solución 1
Inicio
Leer A
Leer B
Si A < B
Entonces
/* Intercambiar A y B */
NUM = A
A = B
B = NUM
Fin_si
R = resto(A/B)
Mientras R <> 0
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
A = B
B = R
R = resto(A/B)
Fin_mientras
Mostrar "MDC es " B
Fin
Solución 2
Inicio
Leer N
R = resto(N/2)
Si R = 0
Entonces
A = raíz_cuadrada(N)
Si no
A = N * N
Fin_si
Mostrar A
Fin
Solución 3
38 www.udima.es
REFERENCIAS BIBLIOGRÁFICAS
Básica
Avanzada
«Fundamentos de programación para el diseño» [Open Course Ware]. Universidad ICESI. Disponible en
<http://www.icesi.edu.co/ocw/course/view.php?id=14>.
González Harbour, M. y Montaña Arnáiz, J. L. «Programación I» [Open Course Ware]. Universidad de
Cantabria. Disponible en <https://ocw.unican.es/course/view.php?id=217>.
Jaén, J. A. et al. «Fundamentos de programación» [Open Course Ware]. Universidad Politécnica de Madrid.
Disponible en <http://ocw.upm.es/ciencia-de-la-computacion-e-inteligencia-artificial/fundamentos-pro
gramacion>.
Peña, R. Diseño de programas: formalismo y abstracción. Prentice Hall, 1993.
www.udima.es 39
2
UNIDAD
DIDÁCTICA
ALGORITMOS Y SISTEMAS
DE REPRESENTACIÓN
DE UN PROGRAMA
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Objetivos de la unidad
1. Algoritmo
1.1. Características básicas
1.2. Algoritmo de Euclides
1.3. Algoritmos computables y no computables
3. La programación estructurada
3.1. Diagramas y programa propio
3.2. Diagramas estructurados o diagramas privilegiados
3.2.1. El bloque secuencial, secuencia o encadenamiento
www.udima.es 41
FUNDAMENTOS DE LA PROGRAMACIÓN
Conceptos básicos
Actividades de autocomprobación
Actividades de repaso
Referencias bibliográficas
42 www.udima.es
OBJETIVOS DE LA UNIDAD
Se presenta en esta unidad didáctica, en primer lugar, el concepto de algoritmo
como «conjunto finito de reglas que crean una serie de operaciones para resolver un
problema». Seguidamente, el concepto de ordinograma como herramienta gráfica para
la implementación de un algoritmo informático que es utilizado en la programación
clásica. Y, posteriormente, el concepto de programación estructurada con los diferentes
sistemas de representación de un programa estructurado, tales como los diagramas es-
tructurados arborescentes y los diagramas de N-S o de Chapin.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
www.udima.es 43
FUNDAMENTOS DE LA PROGRAMACIÓN
1. ALGORITMO
En la Edad Media, los abaquistas calculaban con ábaco y los algoritmistas, con
algorismos. Paulatinamente, la forma y significado de «algorismo» fue deteriorándose y
cambió a «algoritmo» con el significado de «noción de los cuatro tipos de cálculos aritmé-
ticos: suma, resta, multiplicación y división» (diccionario matemático alemán de 1747).
Algoritmo. Conjunto finito de reglas que crean una serie de operaciones para
resolver un tipo específico de problema.
44 www.udima.es
Para que un algoritmo pueda ser considerado como tal, debe ser determinista, tener
un número finito de instrucciones y debe acabar. Por determinista se entiende que, si se
sigue el mismo proceso más de una vez, se llega siempre al mismo resultado.
Donald Knuth, insigne algoritmista, ofreció una lista de cinco propiedades, que son
ampliamente aceptadas como requisitos para un algoritmo:
www.udima.es 45
FUNDAMENTOS DE LA PROGRAMACIÓN
A partir del carácter finito y de producir una salida, se deduce que, ante una misma
situación inicial (o valores de entrada), un algoritmo debe proporcionar siempre el mismo
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
resultado (o salida), con excepción de los algoritmos que utilizan valores aleatorios o son
de tipo probabilístico, los cuales no son objeto de esta unidad didáctica.
Dados dos números enteros positivos, se trata de hallar el MCD de ambos números
mediante divisiones sucesivas entre dichos números y entre el menor y el resto. Es decir,
consiste en hallar el número más alto que divide a los dos.
46 www.udima.es
Para resolver este problema, se puede diseñar un algoritmo con los siguientes pasos:
a B, e ir al paso 4.
Y el MCD (11, 3) = 1:
Vemos que los seis pasos anteriores que resuelven el MCD de dos números es un
algoritmo porque cumple con los cinco requisitos señalados en el epígrafe anterior:
www.udima.es 47
FUNDAMENTOS DE LA PROGRAMACIÓN
Pongamos, por ejemplo, que el problema que hay que resolver es: «Hallar un nú-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
mero P mayor que otro N tal que P sea primo». Es decir, ¿existe P > N tal que P es pri-
mo? El algoritmo que lo resuelve sería el siguiente:
Como hay infinitos primos, sabemos que el problema es finito y el algoritmo ante-
rior es un verdadero algoritmo porque encontrará el número primo buscado y se detendrá
respondiendo afirmativamente a la pregunta.
Ahora, si el problema que se debe resolver es: «Hallar un número P mayor que
N tal que P y P + 2 sean ambos primos». Es decir, ¿existe P > N tal que P y P + 2 son
ambos primos?
48 www.udima.es
Tal vez el algoritmo no se detenga nunca o tal vez se detenga rápidamente. Este hecho
nos hace pensar que el problema no es computable (es indecidible) porque no existe un
algoritmo efectivo que lo resuelva, mientras que los problemas del MCD y de hallar
un número primo mayor que otro admiten un algoritmo que los resuelve; es decir, para
todo posible valor de las variables de entrada, el algoritmo se detiene dando como
salida la solución correcta al problema. Por tanto, estos problemas son computables
(son decidibles).
www.udima.es 49
FUNDAMENTOS DE LA PROGRAMACIÓN
2.1.1. Características
Por otra parte, los diagramas de flujo presentan las siguientes ventajas:
50 www.udima.es
2.1.2. Tipos
2.2. EL ORDINOGRAMA
www.udima.es 51
FUNDAMENTOS DE LA PROGRAMACIÓN
Entrada/salida de información.
52 www.udima.es
www.udima.es 53
FUNDAMENTOS DE LA PROGRAMACIÓN
Inicio
Leer A y B
no
AyB A o B no
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
˃0 son positivos
sí
B>A A↔B
R ← A mod B
no
A←B
R=0
B←R
El MCD es B
Fin
54 www.udima.es
Inicio
Leer N
sí
N <= 0 N no positivo
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
P←N
P←P+1
I←2
J ← P/2
sí
I←I+1 P es el 1.er primo
I>J Fin
mayor que N
no
no
P mod I = 0
sí
3. LA PROGRAMACIÓN ESTRUCTURADA
www.udima.es 55
FUNDAMENTOS DE LA PROGRAMACIÓN
56 www.udima.es
Diagrama propio. Aquel que posee un solo punto de entrada y uno de salida.
Programa propio. Aquel que cumple las siguientes condiciones:
www.udima.es 57
FUNDAMENTOS DE LA PROGRAMACIÓN
58 www.udima.es
En cambio, la figura 5 nos describe el diagrama del MCD como un programa propio,
utilizando exclusivamente los tres símbolos de ordinograma de la programación estruc-
turada. Hay que señalar que el hecho de que un programa sea propio no quiere decir que
sea un programa estructurado; para ello, es necesario que utilice los diagramas estructu-
rados que se verán a continuación.
AyB
Leer
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
AoB
B>A
<= 0
sí
no
A↔B
no > 0"
"A o B
R ← A mod
B
B←R
A←B
R=0
MCD es B
www.udima.es 59
FUNDAMENTOS DE LA PROGRAMACIÓN
fi f2 fn
60 www.udima.es
a) IFTHENELSE b) IFTHEN
cierto cierto
f f
p p
g
falso falso
c) CASE OF
=a
fa
=b
p fb
...
fn
=n
Este bloque condicional, con sus diferentes variantes, corresponde, en los lenguajes
de programación, a sentencias de la siguiente estructura:
• IFTHENELSE (p, f, g) → IF <condición> THEN <inst1> ELSE <inst2>;
Donde: <instl> e <inst2> pueden ser una única sentencia o un bloque de
varias sentencias.
Ejemplo: if (p) f else g; (en C/C++)
www.udima.es 61
FUNDAMENTOS DE LA PROGRAMACIÓN
• IFTHEN (p, f) → IF <condición> THEN <inst1>;
Ejemplo: if (p) f; (en C/C++)
• CASE OF (p, fa, fb, ... , fn) → CASE <condición> OF a: fa; b: fb;
...; n: fn END;
• Variante DOUNTIL. Esta variante se define con los mismos diagramas que
el DOWHILE, aunque su estructura es diferente.
Se representa por la figura 8 b) (ejecutar f hasta que p sea cierto) y corres-
ponde literalmente a un DOUNTIL (p, f).
DOWHILE (p, f) → WHILE <condición> DO <inst>; DOUNTIL (p, f) → → REPEAT
<inst> UNTIL <condición>;
Ejemplo (en C/C++):
while (p) f;
do f while (p);
for (Vc; k; Vf) f;
62 www.udima.es
a) DOWHILE b) DOUNTIL
falso
cierto
f
f p
p
c) CASE OF
sí
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Vc ← Vi Vc > Vf f Vc ← Vc + k
no
Vc = variable de control.
Vi = valor inicial.
Vf = valor final.
k = incremento de la variable de control.
f = tratamiento.
DOFOR (p, f) → DO <eti> Vc = Vi, Vf, k
(Instrucciones) } (en Fortran)
<eti> CONTINUE
www.udima.es 63
FUNDAMENTOS DE LA PROGRAMACIÓN
MCD = [BLOCK ((Leer A y B), IFTHENELSE ((A o B <= 0), (Escribir
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
A o B no son > 0), BLOCK (IFTHEN (B > A, A ↔ B), (R ← A mod B), DOWHILE
(R ≠ 0, BLOCK ( A ← B, B ← R, R ← A mod B)), (Escribir el MCD es B))].
sí Escribir
AoB
no > 0
R←A no Escribir
R≠0
mod B MCD es B
sí
IFTHEN B>A A←B DOWHILE
64 www.udima.es
Este teorema significa que todo lo que se puede programar se puede poner bajo la
forma estructurada.
www.udima.es 65
FUNDAMENTOS DE LA PROGRAMACIÓN
Donde:
• Descomposición de k = BLOCK (f, g):
• Descomposición de k = IFTHENELSE (p, f, g):
• Descomposición de k = DOWHILE (p, f):
– Para todos los estados de entrada de f, que producen los mismos resul-
tados, k debe consistir en no hacer nada (función idéntica).
66 www.udima.es
Este teorema es el útil que nos sirve para guiar la descomposición funcional; es
decir, la programación.
Los diagramas estructurados se han representado de múltiples formas; una de las más
utilizadas es la representación arborescente basada en el método de Tabourier. Tabourier
define un programa mediante una estructura arborescente. La raíz del árbol, que configura
todo el programa, es un diagrama estructurado y cada rama del árbol es, a su vez, otro dia-
grama estructurado que puede estar compuesto por uno o varios diagramas estructurados.
www.udima.es 67
FUNDAMENTOS DE LA PROGRAMACIÓN
BLOCK
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
f1 f2 ... fn
=n
=a
p f g p f p fa ... fn
p f f p
Vc = Vi, k, Vf f
68 www.udima.es
MCD
DOWHILE
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Leer A y B
IFTHENELSE
Escribir "Error
AoB
datos de
<=0 BLOCK
entrada A, B"
Escribir
IFTHEN DOWHILE
R ← A mod B "MCD: " B
www.udima.es 69
FUNDAMENTOS DE LA PROGRAMACIÓN
Seguidamente, se vuelve a repetir otro bucle del bloque DOWHILE, raíz del árbol,
hasta que se tratan todas las parejas de números A y B existentes en el fichero de entrada.
5. D
IAGRAMAS ESTRUCTURADOS DE LA METODOLOGÍA NASSI-
SHNEIDERMAN O DE CHAPIN
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Consideramos que esta forma de hacer organigramas es una cosa muy trivial, pero es
muy concreta, y, como se irá viendo, favorece (e incluso obliga) la modularidad de los pro-
gramas, su tamaño reducido, su programación estructurada; en fin, una serie de objetivos dis-
persos que se consiguen también actualmente de otras formas, pero con un esfuerzo mayor.
70 www.udima.es
p
laterales contienen una T y una F, T F
Parte Parte
respectivamente, para representar los Then Else
dos bloques del proceso alternativo
(parte then y parte else). La variante b)
IFTHEN se representa como se indica
p
en la figura 15 b). Y la variante CASE T F
www.udima.es 71
FUNDAMENTOS DE LA PROGRAMACIÓN
a) b) c)
p Vc = Vi, k, Vf
f
f f
p
72 www.udima.es
5.2. V
ENTAJAS DE LOS DIAGRAMAS ESTRUCTURADOS CON RES-
PECTO A LOS ORDINOGRAMAS CLÁSICOS
y aislado.
Con respecto a los diagramas arborescentes, interesa señalar que son muy fáciles
de seguir y de actualizar. Insertar o eliminar un bloque en el árbol suele ser una acción
muy simple que no obliga a rehacer todo el diagrama; hecho que no se produce en
los diagramas N-S/Chapin ni en los ordinogramas. Con respecto a los diagramas N-S/
Chapin, Chapin hace notar que sus diagramas son más compactos que los clásicos (en
los clásicos, una gran parte del espacio lo consumen las flechas y líneas de conexión) y
ocupan aproximadamente la mitad, debido a que no necesitan dejar tantos espacios para
su claridad y facilidad de lectura. Además, su trazado no tiene que guardar proporciones
entre sus componentes. Se puede usar una convención para destacar la mayor o menor
importancia de una función o procedimiento: las funciones importantes se colocan más
elevadas y hacia la izquierda; las menos importantes (por ejemplo, un tratamiento de
errores) se pueden poner hacia la derecha y abajo. También se pueden aplicar las elipses
con el mismo fin. Este método favorece el diseño y desarrollo top-down (o descendente);
un programa empieza como un rectángulo vacío que se va llenando desde arriba, que, como
se ha indicado, no puede ser muy grande. Se diferencian perfectamente los tres bloques
básicos de la metodología estructurada (Chapin incluye unas barras oblicuas en la parte
vertical de una sentencia de bucle y en el bloque IFTHEN para destacar mejor su presencia
y amplitud). La recursividad es muy fácil de representar con estos bloques, puesto que
basta emplear una elipse con el mismo nombre.
Algo que no representan bien los diagramas estructurados en relación con los clá-
sicos son los diferentes medios con los que se realizan las entradas/salidas (impresora,
disquete, cinta, disco); en esto, los ordinogramas clásicos son más claros. Con todo, en los
sistemas operativos actuales y con «independencia de dispositivos», cada vez va siendo
menos seguro que los registros se lean o escriban en el medio indicado originalmente.
www.udima.es 73
FUNDAMENTOS DE LA PROGRAMACIÓN
CONCEPTOS BÁSICOS
• Algoritmo. El conjunto de instrucciones que define un programa informá-
tico implementa un algoritmo. Este se define como «conjunto finito de reglas
que crean una serie de operaciones para resolver un tipo específico de pro-
blema». Un algoritmo ha de ser finito, definible, con datos de entrada, con
resultados de salida y efectivo.
• Ordinograma. Representación gráfica de un algoritmo informático que
utiliza en su representación diagramas de flujo.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1
Dado el problema «Hallar un número P mayor que otro N tal que P sea primo», se
pide diseñarlo estructuradamente utilizando los diagramas estructurados arborescentes.
74 www.udima.es
Enunciado 2
Ax2 + Bx + C = 0
Enunciado 3
Enunciado 4
Enunciado 5
• Suma de divisores de
• Suma de divisores de
www.udima.es 75
FUNDAMENTOS DE LA PROGRAMACIÓN
Solución 1
Un número primo P mayor que N
IFTHENELSE
Leer N
N>0 BLOCK
"N no positivo"
P←N+1 DOUNTIL
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
I←2
K←0 K=1
BLOCK
IFTHENELSE
DOWHILE
(P mod I ≠ 0)
I > P/2 P es 1.er primo P←P+1
^(I <= P/2)
mayor que N I←2
I←I+1 K←1
Solución 2
1. Leer A, B, C.
2. Si A, B y C son = 0, entonces escribir: «Resultado indeterminado». Fin del
algoritmo.
3. Si A y B = 0 y C ≠ 0, entonces escribir: «Resultado imposible». Fin del
algoritmo.
4. Si A = 0 y B ≠ 0, entonces escribir: «Ecuación de primer grado con resul-
tado: x1 = – (C/B)». Fin del algoritmo.
5. Si A ≠ 0, entonces D = B2 – 4 * A * C; A1 = 2 * A.
6. Si D > 0, entonces escribir: «Raíces reales: x1 = (– B + sqrt (D))/A1;
x2 = (– B – sqrt (D))/A1». Fin del algoritmo.
7. Si D = 0, entonces escribir: «Raíz doble: x1 = x2 = – (B/A1)». Fin del
algoritmo.
8. Si D < 0, entonces escribir: «Raíces complejas: parte real x1 = – B/A 1;
parte imaginaria x2 = sqrt (– D) j/A1». Fin del algoritmo.
76 www.udima.es
Solución 3
Se lee la palabra y se almacena en un vector Pal. Si la palabra tiene más de ocho carac-
teres, se emite un mensaje de error. Para comprobar que la palabra es palíndroma, se va com-
parando la primera y sucesivas letras de Pal con la última y anteriores. El análisis finaliza si la
palabra no es palíndroma (lo detecta una variable S al tomar el valor 1), o si la palabra lo es.
Palabra palíndroma
Palíndroma
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
S = 0; I = 1; Leer(C); Pal[I] = C;
I=I+1
I>9
T F
T S=0
F
J = 1; K = I – 1
J < K and S = 0
T Pal[J] ≠ Pal[K] F
"Palabra no palíndroma"; S = 1 J = J + 1; K = K – 1
T F
Escribir "Palabra palíndroma"
Solución 4
www.udima.es 77
FUNDAMENTOS DE LA PROGRAMACIÓN
Si se cae sobre una casilla ocupada (esto se produce cuando se acaba de escribir un
múltiplo de N), colocar el número debajo de la última casilla rellena.
El cuadro mágico utiliza la matriz Cuadrado [N, N] para almacenar el cuadro má-
gico, y la matriz booleana Ocupado [N, N] para saber si un cuadro ha sido ya ocupado
(en una optimización del diagrama esta matriz es innecesaria).
Cuadro mágico
MÁGICO
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
BLOCK
Escribir
"Cuadro mágico"
Cuadrado[1 ... n, 1 ... n]
DOFOR i←1
DOFOR IFTHEN
j ← (n + 1)/2
BLOCK
i= DOFOR k=
1, 1, n 1,1, sqr (n) Ocupado
BLOCK
[i, j]
j <= 0 j←n
Solución 5
78 www.udima.es
Números amigos
Números
amigos
D1 = 1; D2 = 1; Leer N1 y N2
No fin de fichero
Vc = 2, 1 N1/2
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
N1 mod Vc = 0
T F
D1 = D1 + Vc
T N2 = D1 F
Vc = 2, 1 N2/2
N2 mod Vc = 0
T F
D2 = D2 + Vc
N1 = D2
T F
"N1 y N2 no
"N1 y N2 son amigos"
son amigos"
Leer N1 y N2
ACTIVIDADES DE REPASO
1. Diseñar estructuradamente, utilizando la representación literal de los tres
diagramas privilegiados, el problema de los números amigos expuesto
anteriormente.
www.udima.es 79
FUNDAMENTOS DE LA PROGRAMACIÓN
3. Juego del Mastermind. Esta variante del juego Mastermind consiste en adi-
vinar una combinación de dígitos. El jugador que forma la clave oculta (la
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
que hay que adivinar) debe indicar los aciertos obtenidos por el otro en cada
jugada, ya sean exactos (dígito igual y en la misma posición) o aproximados
(dígito igual pero en distinta posición). Por ejemplo:
Mastermind
Clave: 1 2 3 4 5 1 1 3 7 9
Jugada: 2 3 2 4 7 1 3 1 5 7
80 www.udima.es
Caminos hamiltonianos a) y b)
a) b)
1 2 2
1
3 3
a) Caminos:
Caminos: 1, 2, 1,2,3; 1,3,2
3 ; 1, 3, 2 b) Caminos:
Caminos: no tiene
no tiene
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
REFERENCIAS BIBLIOGRÁFICAS
Básica
www.udima.es 81
FUNDAMENTOS DE LA PROGRAMACIÓN
Avanzada
82 www.udima.es
3
UNIDAD
DIDÁCTICA
TRATAMIENTO
INFORMÁTICO DE
UN PROBLEMA
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Objetivos de la unidad
1. Introducción
2. Definición de los requisitos del problema
3. Análisis
4. Diseño
4.1. Diseño general
4.2. Diseño detallado
5. Codificación
6. Pruebas
7. Mantenimiento
Conceptos básicos
Actividades de autocomprobación
Actividades de repaso
Caso práctico
Referencias bibliográficas
www.udima.es 83
FUNDAMENTOS DE LA PROGRAMACIÓN
OBJETIVOS DE LA UNIDAD
En esta unidad se presenta el ciclo de vida de desarrollo de software, que refleja las
etapas por las que atraviesa el desarrollo de un programa informático desde que se decide
resolver un problema hasta que el programa resultante deja de utilizarse.
Para ello, se definirá el concepto de ciclo de vida y se describirán sus etapas típicas:
• Análisis.
• Diseño.
• Codificación.
• Pruebas.
• Mantenimiento.
84 www.udima.es
1. INTRODUCCIÓN
Con esto se quiere indicar que, aunque el objetivo final es producir un programa
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Ciclo de vida de un programa. Describe qué ocurre desde que se decide desarrollar
un programa hasta que ese programa deja de utilizarse. Incluye las siguientes etapas:
definición de los requisitos del problema, análisis, diseño, codificación, pruebas y
mantenimiento.
www.udima.es 85
FUNDAMENTOS DE LA PROGRAMACIÓN
Definición de
los requisitos
del problema
Análisis
Diseño
Codificación
Pruebas
Mantenimiento
86 www.udima.es
Posteriormente, se han definido otros muchos modelos de ciclo de vida como el prototipado,
el modelo en espiral, los modelos iterativos e incrementales, etc.
En los epígrafes siguientes se van a describir estas etapas. Esta descripción de las
etapas se apoyará en un ejemplo consistente en la «gestión académica de un centro
docente universitario». La gestión académica de un centro docente incluye normalmente
las siguientes tareas:
Consiste en describir el problema que hay que resolver e identificar las necesidades
que se plantean, es decir, describir los objetivos que pretende alcanzar la universidad. En
esta etapa se analiza también si el problema se puede resolver informáticamente o no, es
decir, si es viable con una computadora.
www.udima.es 87
FUNDAMENTOS DE LA PROGRAMACIÓN
La dirección del centro desea que la gestión académica se realice de forma centralizada
desde la secretaría del centro, ya que esta es la responsable de su gestión.
La siguiente pregunta que el informático se plantea al definir los requisitos del problema
es: ¿se puede resolver este problema en una computadora? Para ello se realiza un análisis
88 www.udima.es
técnico y económico del sistema, se establecen las restricciones de tiempo y coste que tiene
el desarrollo del programa y se culmina con una evaluación de la viabilidad del sistema.
El análisis técnico evalúa la viabilidad técnica del sistema propuesto y recoge infor-
mación sobre rendimiento, fiabilidad, facilidad de mantenimiento y posibilidad de pro-
ducción. El análisis económico es un análisis de coste-beneficio que evalúa los costes
estimados para el desarrollo del sistema y los contrasta con los beneficios previstos.
Nota. Estas estimaciones dependen en gran medida del alcance que se establezca en los requisitos y del riesgo que
se pueda asumir. Normalmente, se suele iterar esta etapa con la siguiente hasta tomar una decisión final.
www.udima.es 89
FUNDAMENTOS DE LA PROGRAMACIÓN
• Secretaría del centro. Tendría un administrativo, que actuaría como operador y que rea-
lizaría todas las peticiones que llegasen firmadas por el secretario. Habría que diseñar un
documento de petición del servicio y otro de entrega de resultados. A principios de curso
obtendría los siguientes listados: uno de profesores con las asignaturas que imparten, otro
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
de alumnos con las asignaturas en las que estén matriculados y un tercero de asigna-
turas, todos ellos para la dirección del centro. Y una relación de alumnos por asignatura
para entregarla a cada profesor. Habría que diseñar una propuesta de modelo de los listados
solicitados o, en su defecto, describir el contenido de cada listado. En los meses de junio y
julio se produciría un listado de alumnos por asignatura para que cada profesor consignase
la nota del examen. Este listado se grabaría en el ordenador y seguidamente se obtendría
un listado definitivo de alumnos por asignatura con sus calificaciones (actas) para que lo
firmara cada profesor. Una copia del mismo se expondría en el tablón de anuncios para el
conocimiento del alumno. Habría que diseñar una propuesta de modelo de estos listados
o, en su defecto, describir el contenido de los mismos. Habría que diseñar también una
propuesta de modelo del documento para dar de alta, de baja o modificar los datos de un pro-
fesor, y lo mismo se haría para el caso de un alumno o una asignatura.
• Profesorado. Podría solicitar un listado de alumnos por asignatura (con o sin notas) de
las que es profesor, cumplimentando una petición dirigida al secretario.
• Alumnos. Podrían solicitar una certificación académica del curso actual o un certificado
de estudios de todo su expediente académico mediante una petición dirigida al secretario.
• Software. El software que se debe desarrollar estaría instalado en un PC y sus funciones
serían las de procesar las peticiones realizadas por la secretaría del centro, a través del
operador, y producir como resultado los listados, las actas, etc., descritos anteriormente.
Habría que señalar el tipo de sistema operativo y las herramientas informáticas que se
utilizarían y definir la ubicación del PC y el equipamiento necesario.
• Base de datos. Almacenaría la información del alumnado y profesorado del centro. La
información actual estaría ubicada en el disco duro del ordenador, ya que 1.000 alumnos
y 80 profesores se podrían mantener sin problemas en el PC. Los alumnos que han finali-
zado y los profesores dados de baja se mantendrían en un disco aparte. Existirían copias
de seguridad de ambos discos.
El último paso de esta etapa es la definición del sistema, de forma que sea la base
para todo el trabajo posterior. Consiste fundamentalmente en crear un modelo de la
90 www.udima.es
arquitectura del sistema que describa las interrelaciones existentes entre los distintos ele-
mentos del sistema (interfaz de usuario, entradas, función y control del sistema, salidas,
mantenimiento y autocomprobación). El modelo puede incorporar un «diagrama de con-
texto de la arquitectura», que establece los límites de información entre el sistema y el
entorno en el que va a funcionar, y define los productores y los consumidores externos,
así como las entidades que se comunican a través de la interfaz o realizan mantenimiento
o autocomprobaciones. A partir de aquí se define un «diagrama de flujo de la arquitec-
tura» que muestra los subsistemas principales y las líneas de flujo de información (con-
trol y datos) más importantes del sistema. Cada uno de los subsistemas puede contener
uno o más elementos del sistema según el diseño realizado por el ingeniero del sistema.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Petición S
Producto S
Dirección
Producto A
Petición AV
Petición PV
Secretario
Petición P Producto PV Petición A Producto AV
Profesor Alumno
.../...
www.udima.es 91
FUNDAMENTOS DE LA PROGRAMACIÓN
.../...
documento describe toda la información que se ha obtenido en esta fase sobre el sistema
que se quiere implementar. Este documento tiene los siguientes elementos principales:
Si, como resultado de los análisis técnico y económico y del estudio de viabilidad
del sistema, el problema se considera viable, se emite el documento «Plan software»,
que es un extracto de la especificación del sistema centrada en el software. En líneas
generales, el «Plan software» incorpora los siguientes elementos del documento «Espe-
cificación del sistema»:
92 www.udima.es
3. ANÁLISIS
Como resultado de este, se definen los flujos de información, las estructuras primarias
de datos, las características funcionales del sistema, los requerimientos de rendimiento
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
y las restricciones impuestas por el cliente. Asimismo, se incorporarán los criterios glo-
bales de validación que se utilizarán para probar que los requisitos señalados han sido
implementados.
Dado que esta unidad didáctica está centrada en los fundamentos de la programación,
se va a insistir únicamente en el modelo funcional (características funcionales del sistema),
que consiste en describir el tratamiento informático que va a tener el problema, es decir,
en saber qué procesos (denominados normalmente «unidades de tratamiento» –UT–) se
van a desarrollar y en qué consisten. Para lo cual, hay que describir para cada uno de ellos:
Gráficamente, los procesos se representan con un círculo dentro del cual viene el
nombre del proceso. Los archivos que se almacenan en el disco de la computadora se
representan con un cilindro y los listados, con un símbolo de listado, especificando su
contenido.
En la figura se muestra un diagrama con todos los procesos del sistema de gestión de un
centro docente. Se puede observar que hay tres grandes grupos de procesos: los dedicados
a profesorado, los dedicados al alumnado y, finalmente, los dedicados a las asignaturas.
.../...
www.udima.es 93
FUNDAMENTOS DE LA PROGRAMACIÓN
.../...
2.1.
Alta
2.2.
Alteración 3.1.
2.
Información Alta
2.3.
profesorado Baja
3.2.
2.4. Alteración
Profesorado Profesorado/
Asignaturas
1. 3.3.
Solicitud Alumnado 3.
Información Baja
Información
solicitada alumnado
3.4.
Certificado
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
4.1. académico
Asignaturas
Alta 3.5.
4. Certificado de
Información estudios
asignaturas 4.2.
Alteración 3.6.
Alumnos con
4.6. 4.4. asignaturas
Listado 4.5. 4.3.
Alumnos por
asignaturas Actas asignatura Baja
.../...
94 www.udima.es
.../...
4.5. Actas
Listado
Nombre asignatura Asignaturas Alumnos Profesores de actas
• Introducción. Describe los fines y objetivos del software que hay que
desarrollar.
• Descripción de la información. Descripción detallada del problema que
el software debe resolver. Estarán documentados el flujo y las estruc-
www.udima.es 95
FUNDAMENTOS DE LA PROGRAMACIÓN
4. DISEÑO
Esta etapa tiene por objetivo final producir el pseudocódigo del programa y definir las
estructuras de los datos (entradas y salidas) que intervienen en los procesos. Realmente,
el diseño se suele dividir en dos etapas: diseño general (o preliminar) y diseño detallado.
96 www.udima.es
un centro docente, donde se han incluido los procesos recogidos en la figura del ejemplo 6,
incorporando un módulo que representa el programa principal, así como módulos que
realizan comprobaciones sobre la existencia de datos en los ficheros de alumnos, profe-
sores y asignaturas.
El módulo principal controla todo el sistema y se encarga de llamar, según la selección rea-
lizada, al módulo de profesorado, alumnado o asignaturas, que, a su vez, llaman al módulo
apropiado según la solicitud realizada por el usuario.
Módulo principal
Alta Alteración Baja Prof./Asig. Alta Alteración Baja Cert. Cert. Alum./Asig. Alta Alteración Baja List./Asig. Alum./Asig. Actas
acad. est.
www.udima.es 97
FUNDAMENTOS DE LA PROGRAMACIÓN
El segundo paso del diseño general es el diseño de datos. Consiste en definir las estruc-
turas de los datos de entrada y de los resultados de salida de cada proceso. ¿Qué quiere decir
«definir las estructuras de los datos»?, pues simplemente indicar si los datos que se van a
leer son números enteros, reales, caracteres, etc. Y lo mismo, con los resultados de salida.
En el cuadro se muestra la estructura que tendría cada uno de los registros del fichero de
alumnos. Para ello se utiliza la siguiente terminología:
AP1 AP2 Nombre Calle, N.º, Piso, Letra CAS NJ NJL CAS NJ NJL
98 www.udima.es
Inicio Módulo_Principal
Presentar menú_principal
Leer solicitud /* del usuario */
Mientras solicitud <> salir
Según solicitud
= prof Ejecutar Proceso: 'Profesorado'
= alum Ejecutar Proceso: 'Alumnado'
= asig Ejecutar Proceso: 'Asignaturas'
En otro caso
Mostrar "Opción desconocida"
Fin_según
Presentar menú_principal
Leer solicitud /* del usuario */
Fin_mientras
Fin Módulo_Principal
Seguidamente, se muestra el pseudocódigo del módulo que muestra el listado de todos los
profesores con sus asignaturas. Primero se comprueba si existen profesores. Si los hay, se
.../...
www.udima.es 99
FUNDAMENTOS DE LA PROGRAMACIÓN
.../...
muestra la cabecera del listado y después se recorre el fichero de profesores y, para cada
uno, se comprueba si tiene asignaturas. En ese caso, se obtienen las asignaturas de dicho
profesor (a partir de los códigos de asignatura) y se muestran sus datos. Si el profesor no
tenía asignaturas, se muestra un mensaje en el listado. Finalmente, si no hay profesores,
se muestra un mensaje explicativo.
Inicio ProfesoradoAsignaturas
Si existen profesores
Entonces
Mostrar cabecera del listado
Repetir
Leer registro de profesor
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Mostrar nombre de profesor
Si profesor tiene asignaturas
Entonces
Repetir
Leer código de asignatura de profesor
Leer registro de asignatura con ese código
Mostrar nombre de asignatura
Hasta profesor no tiene más asignaturas
Si no
Mostrar "Profesor sin asignaturas"
Fin_si
Hasta fin de fichero de profesores
Si no
Mostrar "No existen profesores para listado de
profesorado con asignaturas"
Fin_si
Fin ProfesoradoAsignaturas
100 www.udima.es
5. CODIFICACIÓN
Esta etapa tiene por fin traducir en un formato legible para la computadora el pseu-
docódigo producido en la etapa anterior.
Aunque los detalles sobre una codificación correcta en el lenguaje C++ se irán
viendo en el resto de unidades didácticas, sí puede decirse que, independientemente del
lenguaje de programación elegido, es muy importante codificar con un estilo que pro-
duzca un código comprensible, tanto para el autor original del mismo como para otras
personas. Ello quiere decir que:
www.udima.es 101
FUNDAMENTOS DE LA PROGRAMACIÓN
En este punto de esta unidad didáctica se debería mostrar cómo se pueden codi-
ficar en lenguaje C++ los módulos que se han descrito a lo largo del proceso de análisis
y diseño. Sin embargo, no es hasta la siguiente unidad didáctica cuando se empiezan a
ver los elementos esenciales de este lenguaje de programación, por lo que se ha prefe-
rido no mostrar ejemplos de codificación en esta unidad didáctica.
6. PRUEBAS
Por eso, antes de dar por finalizada cualquier labor de programación, es indispen-
sable preparar un conjunto de datos de entrada, lo más amplio posible, que, aplicado al
programa, permita la verificación de los resultados. Este proceso se conoce como «de
pruebas» o «validación» del programa.
102 www.udima.es
Las pruebas del software son un elemento crítico para la garantía de calidad del
software y representan una revisión final de las especificaciones, del diseño y de la codi-
ficación. No es raro que el coste de las pruebas del software suponga un 40 % del coste
total de desarrollo del proyecto.
Interesa señalar que en cada fase del ciclo de vida de desarrollo del software se
plantea un conjunto de pruebas que permiten constatar que el software desarrollado satis-
face las especificaciones de esa fase. Así, durante la fase de «definición de los requisitos
del problema» se especifican las pruebas de sistema, que tienen por finalidad comprobar
que todo el sistema (parte manual, software desarrollado, bases de datos existentes, etc.)
funcione correctamente. Estas pruebas, que quedan fuera de los límites de la ingeniería
del software, verifican que cada elemento encaja de forma adecuada y que se alcanza la
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Durante la fase de «análisis de los requisitos del software» se especifican las pruebas
de validación, que consisten en comprobar que el software desarrollado satisface todas
las expectativas razonables del cliente, es decir, satisface todos los requisitos funcionales,
de comportamiento y de rendimiento especificados durante el análisis.
www.udima.es 103
FUNDAMENTOS DE LA PROGRAMACIÓN
• Pruebas de caja negra. Se llevan a cabo sobre la interfaz del software y pre-
tenden demostrar que el software funciona adecuadamente; es decir, que las
entradas se aceptan de forma adecuada y que se produce una salida correcta.
Estas pruebas no tienen en cuenta la estructura lógica interna del software.
• Pruebas de caja blanca. Se basan en un minucioso examen de los detalles
procedimentales. Se comprueban los caminos lógicos del software para
examinar trozos específicos del programa (bucles, sentencias de bifurca-
ción, etc.).
Normalmente, se suelen combinar las pruebas de caja negra con las de caja blanca
de forma que validen la interfaz del software y aseguren a la vez que el funcionamiento
interno del software es correcto.
Para terminar este epígrafe dedicado a las pruebas debe señalarse que se ha consi-
derado un enfoque tradicional, en el que las pruebas se crean siempre después de codi-
ficar los módulos.
104 www.udima.es
Hoy en día existen formas de trabajar (como el desarrollo dirigido por las pruebas,
TDD, del inglés Test-Driven Development) según las cuales se realizan primero las
pruebas y luego se construyen los módulos. Estos métodos de desarrollo permiten per-
feccionar las abstracciones que se van a implementar. Y con ello se evita, al principio
del desarrollo del proyecto, la codificación de métodos innecesarios.
7. MANTENIMIENTO
Los programas producidos deben ser mantenidos mientras dure el ciclo de vida del
programa. Así, en nuestro ejemplo, el centro educativo deseará que la empresa que ha
diseñado el programa se lo mantenga mientras que el centro lo utilice.
www.udima.es 105
FUNDAMENTOS DE LA PROGRAMACIÓN
Esta fase comporta diferentes actividades. Por un lado, comprobar que toda la docu-
mentación está disponible y es adecuada para las tareas de mantenimiento. Y, por otro,
establecer un esquema de acciones para el caso de error o modificación del software y
comunicar al usuario estas acciones.
entrega al cliente (y a los usuarios) para que lo utilice, hay que estar pendiente del pro-
grama construido porque es normal que surjan cuestiones que exijan la realización de
acciones de mantenimiento.
106 www.udima.es
CONCEPTOS BÁSICOS
• Ciclo de vida de un programa. Describe qué ocurre desde que se decide
desarrollar un programa hasta que ese programa deja de utilizarse. Incluye
las siguientes etapas: definición de los requisitos del problema, análisis,
diseño, codificación, pruebas y mantenimiento.
• Definición de los requisitos del problema. Tiene los siguientes pasos: iden-
tificar las necesidades del cliente, realizar un estudio técnico y económico del
sistema, establecer restricciones de tiempo y coste, evaluar la viabilidad
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
www.udima.es 107
FUNDAMENTOS DE LA PROGRAMACIÓN
ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1
a) Análisis.
b) Diseño.
c) Requisitos del problema.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
d) Pruebas.
Enunciado 2
Enunciado 3
El diseño produce:
a) El pseudocódigo.
b) El pseudocódigo y las estructuras de los datos.
c) Un programa informático.
d) Unidades de tratamiento.
Enunciado 4
108 www.udima.es
Enunciado 5
a) Deductivo.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
b) Interactivo y permanente.
c) Correctivo y adaptativo.
d) Correctivo, perfectivo y adaptativo.
www.udima.es 109
FUNDAMENTOS DE LA PROGRAMACIÓN
Solución 1
Solución 2
Solución 3
Solución 4
Solución 5
ACTIVIDADES DE REPASO
1. Completar las etapas de análisis y diseño del ejemplo de sistema de ges-
tión docente de un centro educativo universitario que se ha expuesto en la
unidad didáctica.
2. Documentarse sobre las pruebas de software, profundizando más allá de la
breve introducción vista en esta unidad didáctica. Temas de especial interés
son: creación de conjuntos de pruebas relevantes (tanto de caja negra como
de caja blanca) y herramientas para la automatización de pruebas en len-
guaje C++.
110 www.udima.es
CASO PRÁCTICO
• Un cliente puede tener varias líneas, mientras que cada línea solo pertenece
a un cliente.
• Una llamada está asociada a la línea desde la que se realiza. Una línea puede
haber realizado varias llamadas.
• Un mensaje está asociado a la línea desde la que se envía. Una línea puede
haber enviado varios mensajes.
• Una conexión de datos está asociada a la línea desde la que se realiza. Una
línea puede realizar varias conexiones de datos.
www.udima.es 111
FUNDAMENTOS DE LA PROGRAMACIÓN
Las tareas que puede realizar un usuario del sistema son las siguientes:
• Agregar un cliente, dados todos sus datos. No podrán existir dos clientes
con el mismo DNI.
• Eliminar un cliente, dado su DNI. Al eliminar un cliente se eliminan todos
sus datos de líneas, llamadas, mensajes y conexiones de datos.
• Agregar una línea, dados todos sus datos y el DNI del cliente al que per-
tenece. No podrán existir dos líneas con el mismo número de teléfono. El
número de teléfono de la línea debe empezar en 6 (por ser un móvil).
• Eliminar una línea, dado su número de teléfono. No se podrá eliminar una
línea si ha realizado llamadas, envío de mensajes o conexiones de datos.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
• Agregar una tarifa, dados todos sus datos. No se pueden agregar dos tarifas
del mismo tipo.
Nota. Por simplicidad, no se pueden eliminar ni modificar tarifas una vez
agregadas al sistema.
• Agregar una llamada, dados todos sus datos y el número de teléfono de la
línea de origen de la llamada. No pueden solaparse en el tiempo llamadas
realizadas desde la misma línea. Si el número de teléfono de destino empieza
por 6, se considerará que se trata de un teléfono móvil. En cualquier otro
caso, se considerará que es un teléfono fijo.
• Agregar un mensaje, dados todos sus datos y el número de teléfono de la
línea de origen. No pueden coincidir en el tiempo mensajes enviados desde
la misma línea. El teléfono de destino deberá ser un móvil.
• Agregar una conexión de datos, dados todos sus datos y el número de telé-
fono de la línea de origen. No pueden solaparse en el tiempo conexiones de
datos realizadas desde la misma línea.
Nota. Por razones de simplicidad, no deben comprobarse los solapamientos
entre llamadas, mensajes y conexiones de datos. Solo debe comprobarse
que no hay solapamientos entre elementos del mismo tipo. Por otro lado,
no podrán agregarse llamadas, mensajes o conexiones de datos si las tarifas
correspondientes no han sido creadas en el sistema. Finalmente, debe tenerse
en cuenta que los números de teléfono de destino de llamadas y mensajes
no tienen que pertenecer necesariamente a líneas dadas de alta en Gestel.
• Mostrar la información resumida de una línea en un periodo de tiempo, dados
el número de teléfono de la línea y las fechas inicial y final del periodo. Se
mostrará el DNI del cliente, el número de teléfono de la línea, el número
112 www.udima.es
REFERENCIAS BIBLIOGRÁFICAS
Básica
Alonso, F.; Segovia, F. J. y Martínez, L. Introducción a la ingeniería del software: modelos de desarrollo
de programas. Delta Publicaciones, 2005.
www.udima.es 113
FUNDAMENTOS DE LA PROGRAMACIÓN
Avanzada
«Fundamentos de programación para el diseño» [Open Course Ware]. Universidad ICESI. Disponible en
<http://www.icesi.edu.co/ocw/course/view.php?id=14>.
González Harbour, M. y Montaña Arnáiz, J. L. «Programación I» [Open Course Ware]. Universidad de
Cantabria. Disponible en <https://ocw.unican.es/course/view.php?id=217>.
Jaén, J. A. et al. «Fundamentos de programación» [Open Course Ware]. Universidad Politécnica de Madrid.
Disponible en <http://ocw.upm.es/ciencia-de-la-computacion-e-inteligencia-artificial/fundamentos-pro
gramacion>.
Pressman, R. S. e Ince, D. C. Ingeniería del software. Un enfoque práctico. 6.ª ed. McGraw-Hill, 2005.
Sommerville, I. Software Engineering. 8.ª ed. Addison-Wesley, 2006.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
114 www.udima.es
4
UNIDAD
DIDÁCTICA
LA PROGRAMACIÓN
Y LOS LENGUAJES
INFORMÁTICOS
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Objetivos de la unidad
1. La programación
2. Paradigmas de programación
2.1. Tipos de paradigmas de programación
2.1.1. Paradigmas procedimentales u operacionales
2.1.2. Paradigmas declarativos
2.1.3. Paradigmas demostrativos
2.1.4. Secuencias de control en paradigmas
3. Paradigma imperativo
3.1. Lenguajes imperativos orientados a expresiones y a sentencias
4. Lenguajes de programación
4.1. Lenguajes máquina
4.2. Lenguajes de bajo nivel
4.2.1. El traductor de ensamblador
4.3. Lenguajes de alto nivel
4.3.1. El traductor de los lenguajes de alto nivel
4.3.1.1. Compilación
4.3.1.2. Interpretación
4.4. Historia de los lenguajes de programación
www.udima.es 115
FUNDAMENTOS DE LA PROGRAMACIÓN
Conceptos básicos
Actividades de autocomprobación
Actividades de repaso
Referencias bibliográficas
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
116 www.udima.es
OBJETIVOS DE LA UNIDAD
La unidad didáctica 4 presenta los siguientes conceptos:
www.udima.es 117
FUNDAMENTOS DE LA PROGRAMACIÓN
118 www.udima.es
1. LA PROGRAMACIÓN
www.udima.es 119
FUNDAMENTOS DE LA PROGRAMACIÓN
Interesa señalar que, aunque las etapas para construir un programa informático son
siempre las mismas: planteamiento del problema, especificación de requisitos, análisis de
los requisitos del programa, diseño del programa, codificación, pruebas y mantenimiento, su
120 www.udima.es
estructura interna no es siempre la misma, pues depende del tipo de problema que se quiere
resolver. Por ejemplo, las etapas arquitectónicas para construir una casa y una fábrica son
básicamente las mismas, pero su estructura interna es totalmente diferente porque resuelve
problemas diferentes. Por ello, a la hora de construir un programa se pueden seguir dife-
rentes filosofías de programación, lo que se denomina «paradigmas de programación».
2. PARADIGMAS DE PROGRAMACIÓN
ejemplar» y como «Teoría o conjunto de teorías cuyo núcleo central se acepta sin cues-
tionar y que suministra la base y modelo para resolver problemas y avanzar en el cono-
cimiento». Realmente, existen muchas acepciones del concepto paradigma tales como:
• Ejemplo.
• Visión específica del mundo, esquema mental, creencia.
• Modelo o marco de referencia filosófico/conceptual/cultural/social/moral.
• Filtro cognitivo de percepciones para interpretar la realidad.
www.udima.es 121
FUNDAMENTOS DE LA PROGRAMACIÓN
Los paradigmas de programación nos indican las diversas formas que, a lo largo
de la evolución de las ciencias de la computación, han sido aceptadas como estilos
para construir programas y para resolver los problemas por medio de una computa-
dora. Un paradigma de programación representa un enfoque particular o filosofía para
la construcción de un programa. No es mejor uno que otro, sino que cada uno tiene ven-
tajas y desventajas. También hay situaciones en las que un paradigma resulta más apro-
piado que otro.
122 www.udima.es
Una vez que visualizamos una solución vía modelos conceptuales de un paradigma,
debemos expresarla con un lenguaje de programación. Para que este proceso sea efectivo,
las características del lenguaje deben reflejar adecuadamente los modelos conceptuales
de este paradigma. Por ejemplo, en OO, el lenguaje debe permitir definir clases, crear
objetos y que estos objetos se manden mensajes entre ellos, mientras que, en el para-
digma lógico, el lenguaje debe permitir crear asertos y reglas y poder aplicar métodos
de encadenamiento de las reglas.
www.udima.es 123
FUNDAMENTOS DE LA PROGRAMACIÓN
Por otro lado, la «metodología de desarrollo de programas» señala los pasos que
hay que seguir desde que se plantea un problema hasta que se resuelve con la construc-
ción del programa informático y las actividades que se deben realizar durante la fase de
mantenimiento del programa hasta que este deja de utilizarse. Este proceso completo es
lo que se denomina «ciclo de vida de un programa» o, en términos más generales, «ciclo
de vida del software».
Evidentemente sí, pues parece lógico que la metodología que se utilice para desa-
rrollar un programa ha de derivar en un modelo de construcción específico. Por ejemplo,
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
• Los que soportan técnicas de programación de bajo nivel (por ejemplo, uti-
lizar ficheros versus estructuras de datos compartidos tales como bases de datos).
• Los que soportan métodos de diseño de algoritmos (por ejemplo, divide
y vencerás, programación dinámica, etc.).
• Los que soportan soluciones de programación de alto nivel, como los
basados en procedimientos y datos, basados en objetos, en funciones, en
hechos y reglas, etc.
Floyd también señala lo diferentes que resultan los lenguajes de programación que
soportan cada una de estas categorías de paradigmas.
Aquí nos centraremos en el nivel más relevante, es decir, en los paradigmas que
soportan soluciones de programación de alto nivel. Estos se agrupan en tres categorías,
de acuerdo con la solución que aportan para resolver el problema:
124 www.udima.es
π
� 3 seno(4x) dx
0
Área de 1 seno(2x) = 2
Área de – 2 seno(3x) = – 2
Etc.
Seguidamente, se describen los paradigmas que incorporan cada una de estas tres
soluciones.
www.udima.es 125
FUNDAMENTOS DE LA PROGRAMACIÓN
Los paradigmas procedimentales son de dos tipos básicos: los que actúan modifi-
cando repetidamente la representación de sus datos (efecto de lado o efecto colateral) y
los que actúan creando continuamente nuevos datos (sin efecto de lado).
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Los paradigmas con efecto de lado utilizan un modelo en el que las variables están
estrechamente relacionadas con direcciones de la memoria de la computadora. Cuando
se realiza una ejecución del programa, el contenido de estas direcciones se actualiza
repetidamente (las variables reciben múltiples asignaciones), y cuando la computación
finaliza, los valores finales de las variables representan el resultado.
• El imperativo.
• El orientado a objetos.
Los paradigmas sin efecto de lado incluyen los que tradicionalmente son denomi-
nados como paradigmas funcionales. No obstante, es importante distinguir la solución
funcional procedimental de la solución funcional declarativa.
126 www.udima.es
Dado que estos paradigmas especifican la solución sin indicar cómo construirla, en
principio eliminan la necesidad de probar que el valor computado es el valor solución.
En la práctica, mientras que muchos de los paradigmas no tienen secuencia de control
y efecto de lado que requiera la noción de estado, las soluciones son producidas como
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
construcciones más bien que como especificaciones. Por lo que los paradigmas resul-
tantes y los lenguajes que los soportan no son verdaderamente declarativos, son pseudo-
declarativos. Se encuentran en este grupo: el funcional, el lógico y el de transformación.
Los sistemas que infieren intentan generalizar una solución usando razonamiento
basado en el conocimiento. Una solución basada en la inferencia intenta determinar en
qué son similares un grupo de datos u objetos y, a partir de ello, generalizar estas simi-
laridades. Lo normal es emplear una serie de juegos de ensayo de aprendizaje para que
www.udima.es 127
FUNDAMENTOS DE LA PROGRAMACIÓN
Los resultados más satisfactorios de los sistemas de inferencia han sido en áreas espe-
cíficas, donde el sistema tenía un conocimiento semántico importante de la aplicación.
El mayor problema que se presenta con los programas demostrativos es conocer cuándo
un programa es correcto. En el caso de los programas procedimentales, esto se consigue
estudiando el algoritmo y el resultado de juegos de ensayo apropiados. En el caso de los
programas demostrativos, el algoritmo queda en una representación interna, y su estudio
se sale del ámbito de estos sistemas. Por lo que la veracidad de la decisión se debe hacer
exclusivamente con base en la eficiencia del algoritmo sobre los casos específicos de prueba.
Por otra parte, se pueden catalogar los paradigmas de programación con base en el
grado en el que la secuencia de control tiene mayor o menor relevancia en los mismos.
En el histograma de la figura 1 se presentan en las filas los diferentes paradigmas de
programación y en las columnas se especifica la mayor o menor dependencia de cada
128 www.udima.es
paradigma con la secuencia de control. En el lado izquierdo parten los paradigmas pro-
cedimentales, que controlan explícitamente el orden de evaluación y disponen de sen-
tencias con efecto de lado. Y en el lado derecho están los paradigmas declarativos con
especificaciones abstractas de la solución y que usan restricciones arbitrarias. En este tipo
de paradigmas no es necesario especificar un orden de ejecución del programa.
Imperativo
Orientado a objetos
Funcional
Lógico
De transformación
Basado en formularios
Flujo de datos
Basado en restricciones
Demostrativo
3. PARADIGMA IMPERATIVO
Este paradigma se caracteriza por que presenta como idea central un modelo abs-
tracto de una computadora que consiste en un gran almacenamiento o memoria, en la
que se incorporan unos datos que posteriormente son transformados en unos resultados.
www.udima.es 129
FUNDAMENTOS DE LA PROGRAMACIÓN
int nombre = 25;
int &nombre1 = nombre;
130 www.udima.es
nombre = nombre + nombre1;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
int vector[10] = {5, 10, 2, 4, 6, 8, 12, 20, 45, -5};
int i= 0, sum= 0;
while (i < 10)
{
sum += vector[i];
i++;
}
printf ("%d", sum); /* imprime 107 */
www.udima.es 131
FUNDAMENTOS DE LA PROGRAMACIÓN
Lo que quiere decir que el programa está constituido por un conjunto de instruc-
ciones que definen el algoritmo y un conjunto de estructuras de datos, de tipo básico:
enteros, reales, caracteres, etc., o de tipo estructurado: vectores, registros, árboles, etc.,
sobre las que opera el algoritmo.
3.1. L
ENGUAJES IMPERATIVOS ORIENTADOS A EXPRESIONES Y A
SENTENCIAS
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
a) Sentencia condicional:
if x > y then v := true else v := false;
b) Expresión condicional:
v := x > y
132 www.udima.es
No obstante, las expresiones en este tipo de programación pierden también sus pro-
piedades matemáticas al permitir la existencia del efecto de lado.
x= ++y – b * c;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
4. LENGUAJES DE PROGRAMACIÓN
www.udima.es 133
FUNDAMENTOS DE LA PROGRAMACIÓN
134 www.udima.es
Estos lenguajes están clasificados como lenguajes de segunda generación. Son len-
guajes simbólicos porque las instrucciones se construyen usando códigos de tipo mnemo-
técnico, lo cual facilita la escritura y depuración de los programas aunque no los acorta,
puesto que cada instrucción, si no es una macroinstrucción, se convierte en una instrucción
en lenguaje máquina. Son lenguajes de programación que se acercan al funcionamiento
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
de la computadora.
Los lenguajes de bajo nivel por excelencia son los ensambladores. El ensamblador
fue el primer lenguaje de programación de bajo nivel utilizado. Es muy similar al lenguaje
máquina, por lo que depende estrictamente del tipo de procesador utilizado (cada tipo de
procesador puede tener su propio lenguaje máquina). Así, un programa desarrollado en
ensamblador para un equipo no puede ser portado a otro equipo diferente. El término
«portabilidad» describe la capacidad de usar un programa en diferentes tipos de compu-
tadoras. Para poder utilizar un programa escrito en código ensamblador en otro equipo
es necesario, si el procesador no es el mismo, volver a escribir todo el programa.
En general, y comparado con otros lenguajes que veremos más adelante, tiene la
desventaja de tener un repertorio reducido de instrucciones, un rígido formato para las
instrucciones (una instrucción está formada por un código de operación, que es un mne-
motécnico, y unos operandos, que son identificadores), baja portabilidad y fuerte depen-
dencia del hardware. Pero tiene la ventaja del uso óptimo de los recursos hardware;
www.udima.es 135
FUNDAMENTOS DE LA PROGRAMACIÓN
MOV eax,1; mueve al registro eax el valor 1
XOR ebx, ebx; pone en 0 el registro ebx
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
int 80h; llama a la interrupción 80h (80h = 128 sistema decimal)
Programa escrito
Programa escrito
en
en lenguaje
lenguaje
ensamblador
ensamblador
COMPUTADORA
COMPUTADORA
Traductor
Traductor
ENSAMBLADOR
ENSAMBLADOR
Programa escrito
Programa escrito
en código de
en código máquina
máquina
COMPUTADORA
COMPUTADORA Resultados
Resultados
Datos
DATOS
136 www.udima.es
Los lenguajes de alto nivel están clasificados como lenguajes de tercera generación.
Estos lenguajes de programación están más próximos al lenguaje humano porque uti-
lizan palabras y frases más fáciles de entender, aunque todavía presentan una gran dis-
tancia con el lenguaje natural.
www.udima.es 137
FUNDAMENTOS DE LA PROGRAMACIÓN
que la escritura de cada instrucción se ajuste a una forma rígida y sistemática de escribir,
sin que haya cabida, por ejemplo, para ambigüedades o dobles sentidos.
program MCD (input, output);
var a, b, r, a1, b1: integer; {declaración de las variables}
begin {comienzo del programa principal}
writeln ('Escriba 2 números enteros positivos'); {imprime el texto}
readln (a, b); {lee 2 números y los coloca en las variables a y b}
if (a <= 0) or (b <= 0) then writeln ('datos de entrada incorrectos')
else
begin
a1 := a; b1 := b;
r := a mod b; {obtiene el resto de dividir a entre b}
while r <> 0 do
begin
a := b;
b := r;
r := a mod b;
end;
writeln ('El MCD de ', a1 : 5,'y', b1 : 5, 'es :', b);
{escribe el resultado}
end
end. {termina el programa principal}
138 www.udima.es
#include <stdio.h>
int main()
{
int a, b, r, a1, b1; /* declaramos variables */
printf ("Escriba 2 números enteros positivos"); /* imprime el texto */
scanf("%d %d", &a, &b);
if ((a <= 0) || (b <= 0)) printf ("\nValores de entrada erróneos");
else
{
a1= a;
b1= b;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
r= a % b; /* obtiene el resto de dividir a entre b */
while (r != 0)
{
a= b;
b= r;
r= a % b;
}
printf ("\nEl MCD de %d y %d es %d", a1, b1, b); /* imprime el resultado */
}
4.3.1.1. Compilación
www.udima.es 139
FUNDAMENTOS DE LA PROGRAMACIÓN
A) Análisis léxico
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Esta fase se encarga de verificar si toda la secuencia de caracteres del programa fuente
pertenece o no al lenguaje léxico. Es decir, realiza un análisis, carácter a carácter, de cada
cadena de caracteres indicando el token al que corresponde cada uno de los elementos
reconocidos o el error en caso de no reconocerlo. Por ejemplo, el análisis léxico de la ins-
trucción suma = valor * 5 señalará que existen dos identificadores (suma y valor), un
operador de asignación (=), otro de multiplicación (*) y una constante entera sin signo (5).
B) Análisis sintáctico
El análisis sintáctico (en inglés, parser) convierte el texto de entrada en otras estruc-
turas (comúnmente árboles) que son más útiles para el posterior análisis de la entrada. El
analizador léxico crea tokens a partir de la secuencia de caracteres de entrada y son estos
tokens los que son procesados por el analizador sintáctico para construir la estructura de
datos; por ejemplo, un árbol de análisis o árboles abstractos de sintaxis.
C) Análisis semántico
140 www.udima.es
Tiene por objeto traducir el código resultante del análisis de las fases anteriores en
un código objeto (normalmente, en código máquina).
www.udima.es 141
FUNDAMENTOS DE LA PROGRAMACIÓN
Enlazador
Enlazador
Programa escrito
Programa escrito
(linkeditor)
(linkeditor)
enen
lenguaje
lenguajede
alto
de altonivel
nivel
COMPUTADORA
COMPUTADORA
COMPUTADORA
COMPUTADORA
Compilador
Compilador
Programa escrito
Programa escrito
Programa escrito Programa escrito
en código
en
encódigo objeto
código objeto en código máquina
máquina
COMPUTADORA
COMPUTADORA Resultados
Resultados
Datos
Datos
Los dos pasos de compilación y enlazado se pueden hacer por separado, almace-
nando el resultado de la fase de compilación en ficheros objeto (el típico programa .obj
para Microsoft Windows o el .o para UNIX) y enlazarlos en una fase posterior, o se
puede crear directamente el programa ejecutable, con lo que la fase de compilación se
almacena solo temporalmente. Debido al proceso de enlazado, un programa podría tener
142 www.udima.es
partes escritas en varios lenguajes (por ejemplo, en C y Pascal) que se podrían compilar
con sus compiladores respectivos de forma independiente y luego enlazarlos juntos para
formar un único módulo ejecutable.
4.3.1.2. Interpretación
lación para utilizarlo en una ejecución posterior, el sistema solo carga el programa fuente
en la computadora junto con los datos que se van a procesar. A continuación, un pro-
grama denominado intérprete, almacenado en el sistema operativo del disco, o incluido
de manera permanente dentro de la computadora, convierte cada instrucción del programa
fuente en lenguaje máquina, conforme vaya siendo necesario durante el procesamiento
de los datos. El código máquina generado no se graba para utilizarlo posteriormente.
La siguiente vez que se ejecute una instrucción se deberá interpretar otra vez y tra-
ducir a lenguaje máquina. Por ejemplo, durante el procesamiento repetitivo de los pasos
de un ciclo o bucle, cada instrucción del bucle tendrá que volver a ser interpretada en
cada ejecución repetida del ciclo, lo cual hace que el programa sea más lento en tiempo
de ejecución (porque se va revisando el código en tiempo de ejecución). El intérprete
elimina la necesidad de realizar una compilación después de cada modificación del pro-
grama cuando se quiere agregar funciones o corregir errores, pero es obvio que un
programa objeto compilado se ejecutará con mucha mayor rapidez que uno que debe
interpretar a cada paso el código fuente durante su ejecución.
Por otra parte, un programa compilado tiene la ventaja de garantizar en mayor medida
la privacidad del código fuente. En efecto, el lenguaje interpretado, al ser directamente
un lenguaje legible, hace que cualquier persona pueda conocer el código fuente del pro-
grama y, de ese modo, copiar su código o incluso modificarlo.
www.udima.es 143
FUNDAMENTOS DE LA PROGRAMACIÓN
144 www.udima.es
El primer lenguaje de programación (como tal) de alto nivel que se propuso fue
Plankalkül, que fue diseñado por Konrad Zuse en los años cuarenta, aunque no fue cono-
cido públicamente hasta 1972 (y no fue implementado hasta el 2000, cinco años después
de la muerte de Zuse).
En 1960, aparece el lenguaje COBOL. Este lenguaje tenía como objetivo ser utili-
zado en el tratamiento de la información y procesamiento de datos a gran escala. Inmedia-
tamente fue adoptado en bancos, compañías y dependencias oficiales. También en 1960
aparece el lenguaje Lisp, un lenguaje muy distinto a los anteriores. Lisp es un lenguaje
que únicamente ejecuta funciones compuestas por otras más simples. Estas funciones son
recursivas, es decir, pueden llamarse a sí mismas cuantas veces sean necesarias. Lisp fue
creado por John McCarthy para su utilización en el campo de la inteligencia artificial.
www.udima.es 145
FUNDAMENTOS DE LA PROGRAMACIÓN
Por la misma época, también aparecen los lenguajes Forth y APL, aunque pasaron
algunos años para que realmente entraran en uso. A estos les siguió el lenguaje PL/I, que
intentó reunir en un solo programa las características de Fortran y COBOL; sin embargo,
el resultado fue un lenguaje sumamente complicado y se dejó de utilizar.
En 1965, John Kemeny y Thomas Kurtz crean el lenguaje BASIC con la intención
de que se convirtiera en un lenguaje de enseñanza. Este lenguaje tuvo mucha aceptación,
aunque hoy en día está en desuso.
En 1970, el profesor Niklaus Wirth crea el lenguaje Pascal a partir del ALGOL
58, también con fines didácticos. En la misma época nace el lenguaje C, que conjuga
estructuración, formalismo y sencillez. Con él se desarrolló el sistema operativo UNIX.
El manejo de las bases de datos llevó al desarrollo del lenguaje proposicional SQL,
para su aplicación a las bases de datos relacionales. La implementación del lenguaje
fue desarrollada por IBM. Del SQL nace dBase, del cual surgieron copias como, por
ejemplo, Fox, Clipper, R:BASE, Oracle, Informix, etc. Al conjunto de estos programas
se les denominó 4GL (lenguajes de cuarta generación).
146 www.udima.es
www.udima.es 147
FUNDAMENTOS DE LA PROGRAMACIÓN
148 www.udima.es
CONCEPTOS BÁSICOS
• Programación. Proceso de desarrollo de un programa informático que exige:
conocer el problema que va a resolver el programa, estudiarlo detenidamente,
construir el programa utilizando un lenguaje de programación y ejecutarlo en
una computadora de forma que funcione adecuadamente.
• Programa de calidad. Aquel que hace lo que debe hacer, que es claro de
leer e interpretar, que es eficiente y que se puede ejecutar en una plataforma
diferente a aquella en la que se elaboró.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1
www.udima.es 149
FUNDAMENTOS DE LA PROGRAMACIÓN
Enunciado 2
Si tuviera que diseñar un programa que resolviera el cálculo de una nómina de per-
sonal, ¿qué paradigma utilizaría en su resolución? ¿Sería adecuado utilizar el lenguaje Lisp?
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Enunciado 3
Enunciado 4
Enunciado 5
150 www.udima.es
Solución 1
Solución 2
Solución 3
Solución 4
Solución 5
www.udima.es 151
FUNDAMENTOS DE LA PROGRAMACIÓN
ACTIVIDADES DE REPASO
1. Lo más importante de un programa informático es que sea de calidad. Las
empresas exigen a sus proveedores que sus productos informáticos cumplan
con la normativa ISO 9000. Analizar, en general, esta norma y resumir los
puntos más importantes en una página.
2. Investigar sobre los paradigmas de programación que soportan técnicas de
programación de bajo nivel y los que soportan métodos de diseño de algo-
ritmos. Resumirlos en una página.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
REFERENCIAS BIBLIOGRÁFICAS
Básica
152 www.udima.es
Floyd, R. W. «The Paradigms of Programming». Communications of the ACM, 1979, vol. 22, núm. 8.
«Paradigma de programación». Wikipedia. Disponible en <http://es.wikipedia.org/wiki/Paradigma_de_
programaci%C3%B3n>.
Pierce, B. C. Types and Programming Languages. MIT Press, 2002.
«Programación». Wikipedia. Disponible en <http://es.wikipedia.org/wiki/Programaci%C3%B3n>.
«Teoría de lenguajes de programación». Wikipedia. Disponible en <http://es.wikipedia.org/wiki/Teor%C3%
ADa_ de_lenguajes_de_programaci%C3%B3n>.
Watt, D. A. Programming Language, Concepts and Paradigms. London: Prentice Hall Int., 1990.
Avanzada
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Friedman, D. P.; Wand, M. y Haynes, C. T. Essentials of Programming Languages. MIT Press, 2001.
López Ostenero, F. y García Serrano, A. M. Teoría de los lenguajes de programación. Madrid: Ramón
Areces, 2014.
Mitchell, J. C. Foundations for Programming Languages. MIT Press, 1996.
Scott, M. L. Programming Language Pragmatics. 2.ª ed. Morgan-Kaufmann, 2006.
www.udima.es 153
5
UNIDAD
DIDÁCTICA
EL LENGUAJE
IMPERATIVO C++
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Objetivos de la unidad
1. Introducción
2. Historia de C++
3. Características generales de C++
4. Elementos básicos de C++
5. Estructura de un programa C++
6. Palabras reservadas de C++
7. Comentarios en C++
Conceptos básicos
Actividades de autocomprobación
Actividades de repaso
Referencias bibliográficas
www.udima.es 155
FUNDAMENTOS DE LA PROGRAMACIÓN
OBJETIVOS DE LA UNIDAD
Para utilizar las técnicas de programación es necesario conocer y dominar un len-
guaje de programación. Por ello, en esta unidad didáctica se comienza la presentación
del lenguaje de programación C++. Dado que este lenguaje es amplio y tiene caracte-
rísticas propias del paradigma orientado a objetos, que quedan fuera del alcance de esta
materia, aquí se presentan únicamente las características de C++ que permiten utilizarlo
como un lenguaje imperativo. Tras realizar una breve presentación histórica del lenguaje,
se comentarán las características generales de C++, para después explicar cuál es la
estructura general de un programa escrito en C++. Asimismo, también se explicarán las
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
156 www.udima.es
1. INTRODUCCIÓN
en el lenguaje C sobre el que han sido incorporadas: clases, funciones inline, sobrecarga
de operadores y funciones, tipos constantes, referencias, operadores de gestión dinámica de
memoria, etc. El C++ es, por tanto, una extensión compatible, aunque no al 100 %,
del lenguaje C, que proporciona:
Por ello, los programadores que estén familiarizados con el lenguaje C encontrarán
muy sencillo el paso al lenguaje C++, pues podrán enseguida empezar a programar, rea-
lizando mínimos cambios en el código y adaptándose rápidamente a las nuevas posibi-
lidades y características que ofrece el nuevo lenguaje C++.
2. HISTORIA DE C++
En este epígrafe se van a comentar los hitos más interesantes de la historia de C++
con el fin de tener un poco de perspectiva sobre el lenguaje.
www.udima.es 157
FUNDAMENTOS DE LA PROGRAMACIÓN
Con el paso del tiempo, se fue popularizando el lenguaje C, hasta el punto de que
fue estandarizado por ANSI. La versión estándar del lenguaje añadía algunas mejoras
importantes que favorecieron un mayor uso del lenguaje y que formaron parte del C++.
En 1986, se licencia a otros vendedores el AT&T C++ Translator 1.1, que incorpora
punteros a miembros y la palabra protected.
En 1988, aparecen otros compiladores de C++ (GNU, Oregon Software, Zortech, etc.).
En la 1988 USENIX C++ Conference se describen nuevas características del lenguaje.
En junio de 1989 se presenta el AT&T C++ Release 2.0, que añade la posibilidad
de la herencia múltiple, la sobrecarga de un mayor número de operadores, además de
solucionar ciertos problemas que presentaban las versiones anteriores del lenguaje.
En 1991, se desarrolla el AT&T C++ Release 2.1, que proporciona una definición
más rigurosa del lenguaje y repara algunos defectos del C++. En mayo de ese mismo
año se publica The Annotated C++ Reference Manual, por Margaret A. Ellis y Bjarne
Stroustrup, que constituye el manual de referencia obligado de todo programador en C++.
En 1992, se realiza el AT&T C++ Release 3.0, que incorpora las plantillas, la deri-
vación protegida y el manejo de excepciones.
158 www.udima.es
En 1997, se publica la tercera edición del libro The C++ Programming Language,
de Bjarne Stroustrup.
La importancia del lenguaje C++ se ha visto además apoyada por el hecho de que
ha servido de base para desarrollar otros lenguajes de programación de gran impacto en
el mundo de la programación, como son el lenguaje Java y el lenguaje C#.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
www.udima.es 159
FUNDAMENTOS DE LA PROGRAMACIÓN
160 www.udima.es
Sentencia. Cualquier orden o instrucción válida del lenguaje. Todas las sentencias
van seguidas de un punto y coma.
Ejemplo de sentencias son las asignaciones y las llamadas a funciones. Puede defi-
nirse también la sentencia vacía como un punto y coma.
• Sentencia: sentencia;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
• Sentencia vacía: ;
Una sentencia puede estar formada por expresiones (que se verán en la unidad didáctica 6),
como sumas, productos, operaciones lógicas, llamadas a funciones, accesos a elementos
de un vector, etc. Estas expresiones pueden combinarse entre sí para formar expresiones
más complejas mediante el uso de distintos operadores proporcionados por el lenguaje.
Otro de los elementos básicos del lenguaje son las declaraciones. En C++ pueden
declararse variables (se verán en la unidad didáctica 6), tipos de datos (se verán en las
unidades didácticas 6 y 9) y funciones (se verán en la unidad didáctica 8). Para ello, habrá
que indicar un tipo de dato junto al objeto que se desea declarar, finalizando la declara-
ción con punto y coma. Es importante indicar que en C++ es obligatorio declarar siempre
cualquier elemento antes de poder usarlo. Así, por ejemplo, las siguientes declaraciones
permiten indicar que la variable a será entera y la variable b será real:
www.udima.es 161
FUNDAMENTOS DE LA PROGRAMACIÓN
int a;
float b;
Por tanto, se usan las llaves como delimitadores de los bloques. Un ejemplo funda-
mental de bloque lo constituye el cuerpo de una función. En resumen, un bloque tiene
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
la siguiente estructura:
{
[declaraciones;]
[sentencias;]
}
Este resultado puede ser un valor de uno de los tipos del lenguaje o definido por el
programador. El programador puede definir tantas funciones como necesite para resolver
un determinado problema. Además, en C++ se pueden utilizar funciones ya definidas (que
se suelen llamar funciones de librería, como las explicadas en la unidad didáctica 10). Un
ejemplo de función que devuelve el cuadrado de un número entero recibido como pará-
metro sería el siguiente:
int Cuadrado(int n)
{
return n * n;
}
162 www.udima.es
Todo programa deberá contener la definición de una función con el nombre obli-
gatorio de main. Esta función será la que se ejecute al poner en marcha el programa. El
siguiente ejemplo muestra un programa que declara una variable (i), calcula la suma
de dos números guardándola en dicha variable y escribe el resultado en pantalla con la
operación cout (para más información sobre la operación de escritura cout puede con-
sultarse la unidad didáctica 7):
void main (void)
{
int i;
i= 876 + 123;
cout << i;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
www.udima.es 163
FUNDAMENTOS DE LA PROGRAMACIÓN
Esta estructura es por convención, dado que C++ es un lenguaje de formato libre,
pero es recomendable que siempre se pueda identificar cada una de estas partes.
Ejemplo de un programa:
#include <iostream.h> // Directiva de preprocesador
const float PI= 3.14159; // Constante
float PorPI (float x); // Declaración de función
void main (void) // Programa principal
{
float y= 5.6;
cout << "Y: " << y << " por PI = " << PorPI(y) << endl;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
}
float PorPI (float x) // Definición de función
{
return x * PI;
}
Las funciones, las declaraciones, etc., pueden agruparse en diversos ficheros fuente.
Por tanto, un programa C++ podrá estar formado por uno o varios ficheros fuente, que
se pueden compilar por separado, para después enlazarlos (link) junto con las librerías
que proporcione el compilador para obtener el programa final.
En el caso de un programa con varios ficheros, suelen existir dos ficheros por cada
módulo:
164 www.udima.es
// Función que devuelve el cuadrado de un número
float Cuadrado(float); // prototipo de la función
#include "cuad.h"
// Implementación de Cuadrado
float Cuadrado(float n)
{
return n * n;
}
#include <iostream.h>
#include "cuad.h"
// Programa principal: leer y calcular cuadrado
void main(void)
{
float num, cuad;
cout << "Introduce un número: ";
cin >> num;
cuad= Cuadrado(num);
cout << "El cuadrado de " << num << " es " << cuad << endl;
}
• Preprocesado. Se tratan las directivas del preprocesador (que empiezan por #).
Entre ellas destaca la inclusión de ficheros de cabecera, que consiste en
copiar el contenido del fichero de cabecera dentro del fichero que contiene
la directiva #include.
www.udima.es 165
FUNDAMENTOS DE LA PROGRAMACIÓN
Inc1.h Inc2.h
PREPROCESADO
�
� Inc2.h Inc3.h
GESTIÓN DE LIBRERÍAS
Librería.lib
File5.o
File1.cpp File2.cpp File3.cpp File4.mod
File6.o
COMPILACIÓN
�
Ejecutable
En C++ existe una serie de palabras clave que tienen un significado especial y que
se utilizan para escribir instrucciones, definir tipos, construir funciones, clases, métodos,
etc. Estas palabras son reservadas en C++ y, por tanto, no se pueden utilizar para otros
fines más que para los que fueron previstos.
166 www.udima.es
www.udima.es 167
FUNDAMENTOS DE LA PROGRAMACIÓN
7. COMENTARIOS EN C++
teres /* y su final con los caracteres */. Este tipo de comentario de bloque
puede ocupar varias líneas si es necesario.
/* esto es un comentario de bloque
que puede ocupar varias líneas */
// esto es un comentario de línea
int i; // otro comentario de línea
Los comentarios no pueden anidarse entre sí, es decir, no se puede colocar un comen-
tario dentro de otro. El siguiente ejemplo muestra un uso incorrecto de los comentarios,
puesto que hay una parte que puede parecer un comentario que realmente no lo es:
float Cuadrado(float n) /* Esto es un comentario
{ /* Aquí no comienza otro comentario; continúa el anterior
168 www.udima.es
return n * n;
} y esto sigue siendo el mismo comentario */
Pero esto ya no es un comentario, sino un error */
Los comentarios deben escribirse para aclarar el objetivo del código y no simple-
mente para dar indicaciones obvias. Así, en el siguiente fragmento de código, el comen-
tario de la primera línea no aporta nada que un programador no sepa ya; en cambio, la
segunda línea proporciona información útil acerca del significado de la variable.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
int cont1; // declaración de una variable entera
int cont2; // almacena el contador de unidades vendidas
Resulta útil también aportar información acerca de cada función que se declare, para
facilitar su uso por parte del propio programador o por otros programadores. Así, sería
conveniente describir el objetivo de la función, si tiene efectos colaterales (como modi-
ficar una variable global o interactuar con el usuario), qué parámetros recibe la función
indicando su tipo y su significado, el tipo de retorno, etc.
www.udima.es 169
FUNDAMENTOS DE LA PROGRAMACIÓN
CONCEPTOS BÁSICOS
• C++ es un lenguaje importante en el mundo de la programación y tiene un
núcleo común compartido con otros famosos lenguajes de programación
como C, C# y Java, aunque muchos otros no tan conocidos también se ali-
mentan de características comunes (C--, D, Objective-C, R++, Felix, etc.).
• Es un lenguaje de formato libre y se diferencian minúsculas y mayúsculas.
• Los elementos básicos de un programa en C++ son las sentencias, que fina-
lizan en punto y coma, y las declaraciones, que permiten declarar variables,
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1
a) Kernighan y Ritchie.
b) Bjarne Stroustrup.
170 www.udima.es
c) Ken Thompson.
d) ANSI.
Enunciado 2
a) Pascal.
b) C.
c) COBOL.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
d) BPL.
e) C#.
f) Java.
g) D.
Enunciado 3
Uno de los elementos básicos de C++ es la sentencia. ¿Cuál de las siguientes afir-
maciones es falsa?
Enunciado 4
www.udima.es 171
FUNDAMENTOS DE LA PROGRAMACIÓN
Enunciado 5
¿Cuál de las siguientes frases en relación con las palabras reservadas es falsa?
172 www.udima.es
Solución 1
b) Bjarne Stroustrup.
Solución 2
b) C.
d) BPL.
e) C#.
f) Java.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Solución 3
Solución 4
Solución 5
c) Las palabras reservadas son cualquier palabra que pueda utilizar el progra-
mador para construir un programa como, por ejemplo, los nombres de las
variables.
ACTIVIDADES DE REPASO
1. Buscar el conjunto de lenguajes que se considera que pertenecen a la «familia
de C++» y los que pertenecen a la «familia de C».
2. El programa que empieza al final de la página 168 es erróneo. Corríjalo.
www.udima.es 173
FUNDAMENTOS DE LA PROGRAMACIÓN
REFERENCIAS BIBLIOGRÁFICAS
Básica
Avanzada
Deitel, H. y Deitel, P. J. C++ How to Program. 7.ª ed. Prentice Hall, 2009.
Fuertes, J. L. y González, Á. L. El lenguaje de programación C. Koobeth International, 2004.
Kernighan, B. W. y Ritchie, D. M. The C Programming Language. 2.ª ed. Prentice Hall, 2004.
Liberty, J.; Rao, S. y Jones, B. L. Sams Teach Yourself C++ in One Hour a Day. Sams, 2008.
174 www.udima.es
6
UNIDAD
DIDÁCTICA
EXPRESIONES
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Objetivos de la unidad
1. Introducción
2. Constantes
2.1. Constantes enteras
2.2. Constantes reales
2.3. Constantes lógicas
2.4. Constantes carácter
2.5. Constantes cadenas de caracteres
3. Variables
3.1. Nombres de variables
3.2. Declaraciones
3.3. Inicializaciones
3.4. Identificadores constantes
www.udima.es 175
FUNDAMENTOS DE LA PROGRAMACIÓN
4.7. Punteros
4.8. Referencias
4.9. Declaraciones en bloques
4.10. Conversiones de tipos
5. Operadores
5.1. Operadores y expresiones
5.1.1. Operador, operando y expresión
5.1.2. Operadores unarios, binarios y ternarios
5.2. Precedencia y asociatividad de operadores
5.3. Operadores y expresiones aritméticas
5.4. Operadores y expresiones relacionales y lógicas
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Conceptos básicos
Actividades de autocomprobación
Actividades de repaso
Referencias bibliográficas
176 www.udima.es
OBJETIVOS DE LA UNIDAD
Para utilizar las técnicas de programación es necesario conocer y dominar todas
las características de un lenguaje de programación. Por ello, en esta unidad didáctica se
comienza la presentación del primero de los grandes componentes que forman el lenguaje
de programación C++: las expresiones. Se comienza la explicación con la descripción de
las constantes de distintos tipos, cómo declarar y nombrar una variable y cuáles son los
tipos básicos de datos del lenguaje, y finaliza la unidad didáctica con una descripción de
todo el conjunto de operadores que presenta C++.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
www.udima.es 177
FUNDAMENTOS DE LA PROGRAMACIÓN
1. INTRODUCCIÓN
Esta unidad didáctica va a presentar los elementos básicos del lenguaje C++ nece-
sarios para construir uno de los componentes fundamentales de cualquier programa: las
expresiones. Una expresión está formada generalmente a partir de elementos básicos,
como constantes o variables, y de operadores, que permiten relacionar las constantes o
variables entre sí. Asimismo, varias expresiones pueden agruparse con la ayuda de los
operadores para dar lugar a otra expresión más compleja.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Expresión. Está formada por los operandos (constantes, variables, etc.) y los ope-
radores (aritméticos, lógicos, relacionales, etc.).
2. CONSTANTES
En todo lenguaje de programación, uno de los elementos básicos son las cons-
tantes, que posibilitan representar valores de distintos tipos de datos elementales como,
por ejemplo, números.
Cada lenguaje concreto especifica en sus normas cómo se escribe cada tipo de cons-
tante y su significado exacto. En el lenguaje C++ existen distintos tipos de constantes.
178 www.udima.es
Seguidamente se van a estudiar todos ellos, conjuntamente con las distintas nota-
ciones existentes en las que se puede representar cada tipo de constante.
www.udima.es 179
FUNDAMENTOS DE LA PROGRAMACIÓN
Fácilmente puede verse que como el dígito 6 está en la tercera posición (es decir,
posición 2 si se empieza a contar desde 0), hay que multiplicar su valor por la potencia
segunda de 10, es decir, por 100.
Otro aspecto que hay que destacar es el rango posible de valores que se puede repre-
sentar con esta notación de constante entera. El rango de una constante se refiere a cuántos
valores distintos pueden representarse o, dicho de otra forma, cuál es el máximo valor que
se admite. Cada tipo de ordenador, cada arquitectura, cada sistema operativo, cada com-
pilador puede determinar el rango de los valores enteros que puede representar. De esta
manera, por ejemplo, en un entorno determinado, podría estar prefijado que los números
enteros se deben poder almacenar en dos bytes (16 bits), dejando un bit para el signo. En
este caso, entonces, se podría representar un total de 215 valores distintos; teniendo en
cuenta que el primero de ellos sería el 0, el mayor número representable sería 215 – 1, es
decir, 32.767. Este dato es fundamental para todo programador que se enfrenta a la tarea
de diseñar un programa, por lo que antes de comenzar deberá estudiar la documentación
del compilador para el ordenador que esté usando con el fin de averiguar dichos límites.
También hay que tener en cuenta el rango de los números cuando se escriben valores
negativos. Siguiendo con el ejemplo anterior de enteros con 16 bits, los valores posibles
180 www.udima.es
que se podrían representar van desde el – 32.768 hasta el + 32.767 (es decir, un total de
65.536 valores distintos o, lo que es lo mismo, 216 valores).
Además de las constantes enteras en notación decimal, C++ ofrece otras notaciones
para representar números enteros. Estas notaciones se fundamentan en utilizar una base
distinta a la decimal. C++ dispone de dos notaciones adicionales: la notación octal (o en
base 8) y la notación hexadecimal (en base 16).
La forma para obtener el valor de una constante entera octal es análoga a la vista para
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
la notación decimal, excepto en que se usa la base 8 en vez de la base 10. De esta manera,
cada dígito se multiplica por la base (8) elevada a la potencia indicada por la posición que
ocupa dicho dígito dentro del número empezando por cero desde la derecha. Por ejemplo,
el valor decimal del número octal 20.702 se podría calcular de la siguiente manera:
2 * 80 + 0 * 81 + 7 * 82 + 0 * 83 + 2 * 84 =
2 * 1 + 0 * 8 + 7 * 64 + 0 * 512 + 2 * 4.096 =
2 + 0 + 448 + 0 + 8.192 = 8.642
Fácilmente puede verse que como el dígito 7 está en la tercera posición (es decir,
posición 2 si se empieza a contar desde 0), hay que multiplicar su valor por la potencia
segunda de 8, es decir, por 64.
En C++, si se desea representar un número en notación octal, hay que utilizar obli-
gatoriamente como prefijo el dígito cero (0). Es decir, todas las constantes enteras que
comiencen por un cero serán números en notación octal y, por tanto, solamente podrán
emplearse los dígitos entre el 0 y el 7. De igual forma, también los números octales
pueden ir precedidos de un signo.
Podría pensarse que existe cierta ambigüedad con la constante de valor cero, dado
que empieza por cero y podría suponerse que es un número octal, pero no vienen detrás
www.udima.es 181
FUNDAMENTOS DE LA PROGRAMACIÓN
más dígitos. En realidad, no existe dicha ambigüedad dado que el valor cero en decimal
se representa exactamente igual que el valor cero en octal, por lo que no hay problema
con interpretarlo en una o en otra base.
A B C D E F
10 11 12 13 14 15
Fácilmente puede verse que como el dígito 1 está en la tercera posición (es decir,
posición 2 si se empieza a contar desde 0), hay que multiplicar su valor por la potencia
segunda de 16, es decir, por 256. Obsérvese también como el valor del dígito hexade-
cimal C ha sido sustituido por su valor equivalente (12).
182 www.udima.es
0x5D4 -0x1 0x0 +0x30 -0x29a 0x3039 -0xA +0x7D9 0x2710 0x400
Las constantes enteras sin signo se utilizan para representar valores en los que el
signo no se quiere tener en cuenta o que no pueden representarse con los enteros normales.
Como es también un entero, se utiliza la misma cantidad de memoria que para representar
un entero con signo. En el caso expuesto anteriormente, los enteros ocupaban 16 bits y se
comentó que uno de los bits se reservaba para el signo. Pues bien, si lo que se pretende
representar es un entero sin signo, no es necesario guardar dicho bit extra para el signo, sino
que se puede utilizar para almacenar más valores numéricos. De esta manera, con 16
bits, los valores que se pueden representar van desde el valor 0 hasta el 65.535 (216 – 1).
Para representar los enteros sin signo en C++ se utiliza como sufijo la letra U (viene
del inglés unsigned), tanto mayúscula como minúscula. Evidentemente, si se tiene una
constante entera con el sufijo U no puede ir precedida de ningún signo.
0x5D4U 1u 0U 060U 0x29au 12345u 10u 2009U 10000U 0x400U
Las constantes enteras de alta (o gran) precisión se utilizan para representar valores
más grandes de lo normal, es decir, mayores números positivos o menores números nega-
tivos. Para representar estos nuevos números, los compiladores utilizan mayor cantidad
de memoria que para representar un entero. En el caso expuesto anteriormente, si los
enteros ocupaban 2 bytes, el compilador podría decidir utilizar 4 bytes para los enteros
de alta precisión. En este caso, los valores representables irían desde el – 2.147.483.648
hasta el + 2.147.483.647, que ya constituyen números enteros lo suficientemente grandes
como para representar casi cualquier valor de los habituales.
www.udima.es 183
FUNDAMENTOS DE LA PROGRAMACIÓN
Para representar los enteros de alta precisión, en C++ se utiliza como sufijo la letra
L (viene del inglés long), tanto mayúscula como minúscula. Evidentemente, una cons-
tante entera con el sufijo L puede ir precedida de un signo.
Hay que tener en cuenta que, aunque el valor de la constante escrita no sea grande
y, por tanto, no sería necesario usar el sufijo L, puede ser recomendable usarlo cuando
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
dicho valor va a ser operado con otros datos de alta precisión. Así, este sufijo constituye
una indicación al compilador para que almacene internamente dicho valor utilizando un
mayor número de bytes que el estrictamente necesario.
Un segundo tipo de constantes numéricas lo forman las constantes de tipo real, que
permiten representar números con una parte entera y una parte decimal. Algunos ejem-
plos habituales de constantes reales que pueden encontrarse en la vida real son:
184 www.udima.es
En C++ existen dos notaciones para representar los números reales. La notación
normal para los números reales consta de la parte entera y la parte decimal, separadas
por un punto decimal (es decir, se utiliza el punto como indicador de la parte decimal en
lugar de la coma como resulta habitual en el lenguaje habitual de los hispanoparlantes).
No obstante, para representar un número real, el lenguaje permite que se omita una de las
dos partes (la entera o la decimal), pero manteniendo siempre el punto decimal. Cuando
una de estas partes se omite, se entiende que debe sustituirse por un valor de 0. Así, 5.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
equivale a 5.0 y .5 equivale a 0.5. Al igual que ocurría con los números enteros, un
número real puede ir precedido de un signo, tanto positivo como negativo.
www.udima.es 185
FUNDAMENTOS DE LA PROGRAMACIÓN
El primer modificador consiste en utilizar la letra F (del inglés float) como sufijo
(tanto mayúscula como minúscula). Este modificador indica al compilador que se desea
utilizar un menor rango de números (con el objetivo de ahorrar memoria para su repre-
sentación y de acelerar los cálculos, pues estos podrán realizarse de manera más rápida
por el procesador al utilizarse menor cantidad de bytes para su representación).
Téngase en cuenta en los ejemplos dados que los rangos de valores permitidos en
cada caso dependerán del compilador, por lo que siempre resulta imprescindible con-
sultar su documentación si no se quiere obtener resultados no deseados.
186 www.udima.es
(verdadero) y false (falso). De esta manera, cuando se quiera denotar que una expresión
es siempre cierta, puede utilizarse la constante true. Análogamente, cuando se quiera
indicar que una expresión es siempre falsa, se podrá utilizar la constante false.
Hay que tener en cuenta, además, que en C++ cualquier valor o expresión que se
evalúe como cero, se considera que es falsa, y cualquier valor o expresión que se evalúe
como distinta de cero, se considera que es verdadera.
De esta manera, sería equivalente decir: false, 0, 0.0, 0L, 0u, 0x0, etc. Asimismo,
sería equivalente (en cuanto al valor lógico) decir: true, 7, 9.1, 0.1, 0xA, 9L, .1e-99, etc.
El lenguaje C++ también dispone de otro tipo de constantes que permiten repre-
sentar un carácter perteneciente al conjunto de caracteres que utiliza un ordenador (por
ejemplo, ASCII, ANSI, EBCDIC, etc.). Un carácter se representa encerrándolo entre co-
millas simples. Por ejemplo, el carácter que representa la letra c minúscula será 'c'; el
carácter que representa la letra D mayúscula será 'D', el carácter que representa el sím-
bolo de la suma será '+' y el carácter que representa el dígito 8 será '8'. Cada carácter
tiene su representación, e internamente lo que realmente se almacena es el valor del
código del carácter dentro del juego de caracteres del ordenador. Por tanto, el valor
de una constante de tipo carácter es el valor numérico del carácter correspondiente en el
juego de caracteres de la máquina. Si, por ejemplo, se está utilizando el juego de carac-
teres ASCII (American Standard Code for Information Interchange), internamente, para
el carácter 'c' se almacenará el valor entero 99; para el carácter 'D' se almacenará el
valor 68; para el '+' se almacenará 43, y para el '8' se almacenará un 56.
De esta forma, puede representarse la mayoría de los caracteres, pero existen algunos
caracteres que no disponen de una representación visual o son especiales (como, por
ejemplo, el carácter que representa al salto de línea o el carácter tabulador). Además,
hay ciertos caracteres que pueden tener un significado distinto en el lenguaje (como, por
ejemplo, el propio carácter de la comilla o el porcentaje).
www.udima.es 187
FUNDAMENTOS DE LA PROGRAMACIÓN
ciales. La barra inversa irá seguida de uno o varios símbolos de tal manera que, depen-
diendo de dichos símbolos, se interpretarán como un carácter u otro. Hay que tener en
cuenta que, aunque una secuencia de escape se escribe utilizando varios caracteres, repre-
senta un único carácter.
Nótese que las dos últimas secuencias de escape permiten representar cualquier
carácter. De esta manera, el carácter cambio de línea se podría representar con la secuencia
de escape '\n'. Pero teniendo en cuenta que este carácter tiene el código ASCII 13, se podría
obtener su valor hexadecimal y escribir la secuencia de escape '\x0D', o bien, se
podría obtener su valor octal y usar la secuencia de escape '\015'. Si además se tiene en
cuenta la característica comentada anteriormente relativa a que un carácter se almacena
guardando su código ASCII (en este caso), una última forma de representar el carácter
cambio de línea sería usando directamente la constante entera 13. Como se ve, existen
diversas formas de representar un mismo carácter en C++.
Finalmente, un carácter que debe recibir un especial interés y que será útil en lo que
se va a estudiar a continuación lo constituye el carácter nulo, es decir, el carácter cuyo
188 www.udima.es
código es cero. Los programadores en C++ suelen llamar a este carácter habitualmente
mediante el nombre simbólico NULL, que puede utilizarse en los programas en C++ y
suele estar definido como 0 con una directiva del preprocesador.
El último tipo de constantes de los que dispone el lenguaje C++ son las denomi-
nadas cadenas de caracteres. Una constante cadena de caracteres permite representar
una secuencia de caracteres. De esta manera, una cadena de caracteres (denominada
de forma habitual simplemente como cadena) está compuesta por varios caracteres. En
C++ se representan las cadenas encerrando dichos caracteres entre el símbolo de comi-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
llas dobles.
En C++ está garantizado por el lenguaje que todas las constantes de cadena ter-
minen obligatoriamente con el carácter nulo ('\0'), que introduce automáticamente el
compilador, considerándose dicho carácter como el fin de cadena. Por tanto, el tamaño
de una cadena es el número de caracteres que tiene más el carácter nulo. Así, la cadena
siguiente tiene 24 caracteres «normales» (19 letras, 2 dígitos y 3 espacios), más el ca-
rácter nulo implícito de cierre de la cadena.
"Cadena con 25 caracteres"
C a d e n a c o n 2 5 c a r a c t e r e s /0
www.udima.es 189
FUNDAMENTOS DE LA PROGRAMACIÓN
No se deben confundir las constantes carácter con las constantes cadena. Una constan-
te carácter representa un único carácter mientras que una cadena puede representar varios.
Así, el carácter 'p' es distinto a la cadena "p" (que, además, consta de dos caracteres).
Una cadena de especial interés la constituye la cadena vacía, que se representa úni-
camente con las comillas: "". Debe recordarse que esta cadena tiene un único carácter:
el carácter nulo.
Hora "Día"
11:45 11/2/66
"Esta cadena es una cadena muy larga que no cabe en una línea,"\
"así que prefiero escribirla"\
"utilizando varias líneas para"\
"que quede más claro el código."
3. VARIABLES
190 www.udima.es
El nombre de una variable (o cualquier otro identificador) debe comenzar por una
letra o el carácter de subrayar (_) y puede continuar por letras (no se admiten letras con
acentos o eñes), dígitos o el carácter de subrayar. Los nombres de variables pueden tener
cualquier longitud, pero el número de caracteres significativos (los que usará el compila-
dor para diferenciar dos identificadores) depende del compilador (por ejemplo, un com-
pilador de C++ podría decidir utilizar solamente los primeros 32 caracteres del nombre
de una variable; aunque el programador use más, el compilador no los empleará). De esta
forma, serían nombres de variables válidos los siguientes:
www.udima.es 191
FUNDAMENTOS DE LA PROGRAMACIÓN
3.2. DECLARACIONES
tipo nombre_variable;
nidos por el usuario (que se verán también en la unidad didáctica 9). El nombre_variable
se refiere a un nombre de identificador válido en C++, tal como se ha comentado en el
epígrafe anterior. Obsérvese que cada declaración debe terminar en un punto y coma.
También se permite declarar diversas variables de un mismo tipo en una misma instruc-
ción de declaración separando las variables mediante comas, es decir:
En este caso, las tres variables serán del mismo tipo, esto es, pueden almacenar el
mismo tipo de información.
3.3. INICIALIZACIONES
Como posibilidad opcional, se permite dar o asignar un valor inicial a una variable
en el momento de la declaración. A esta acción se le denomina «inicializar la variable» y,
entonces, la instrucción de declaración pasa a denominarse también instrucción de defini-
ción (porque se define el valor de la variable). Existen dos posibles sintaxis para declarar
e inicializar una variable (para definirla). Estas notaciones, que son equivalentes, se mues-
tran a continuación:
192 www.udima.es
variable no se inicialice, el valor que puede contener es impredecible (se dice que contiene
«basura»). Por ello, es importante siempre dar un valor inicial a cada una de las variables
(preferiblemente en la declaración). Hay que destacar que el valor que se pretenda asignar
a una variable debe ser compatible con su tipo (el concepto de compatible se explica más
adelante). Por ejemplo, no se podrá asignar un número real a una variable de tipo cadena.
De esta forma, se define el nombre_constante del tipo indicado por tipo y con el
valor indicado, de tal manera que dicho nombre conservará su valor hasta la finaliza-
ción del programa, sin poder ser alterado.
Cada lenguaje dispone de un conjunto de tipos de datos que el usuario puede uti-
lizar para crear sus variables. Dentro del lenguaje C++, estos tipos de datos se pueden
www.udima.es 193
FUNDAMENTOS DE LA PROGRAMACIÓN
dividir en tres clases: tipos básicos (que representan un valor sencillo), tipos avanzados,
elaborados o complejos (que permiten representar varios datos simultáneamente o es-
tructuras de datos) y tipos definibles por el programador (el programador puede definir
nuevos tipos de datos). En este epígrafe se van a estudiar únicamente los primeros tipos
(básicos); el resto se dejan para la unidad didáctica 9.
int horas, minutos, segundos;
/* se declaran tres variables enteras */
int num_meses = 6 + 6;
/* la variable num_meses es de tipo entero */
int year (365); /* se define la variable year de tipo entero */
int dia = 15, hora; /*
se define una variable entera y se declara
una variable entera */
const int dias_semana = 7; /* esta constante valdrá siempre 7 */
Al igual que ocurría con las constantes, se puede tener distintos tipos de variables
enteras, dependiendo de la precisión requerida, empleando los siguientes modificadores:
194 www.udima.es
Estos modificadores se anteponen al tipo int para formar el nuevo tipo, aunque tam-
bién constituyen tipos de datos por sí mismos. El modificador signed, en realidad, es
redundante, pues cualquier tipo tiene signo a menos que se use el modificador unsigned.
Los dos grupos de declaraciones siguientes son equivalentes:
short edad; short int edad;
long precio; long int precio;
unsigned dia; unsigned int dia;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
signed diferencia; int diferencia;
También pueden mezclarse estos modificadores para obtener otros tipos de datos:
• Entero de poca precisión sin signo: unsigned short o unsigned short int.
• Entero de gran precisión sin signo: unsigned long o unsigned long int.
En lo referente a los tamaños que ocupan los diferentes tipos enteros, el lenguaje no
especifica los rangos de valores de cada tipo de datos. Lo único que obliga el lenguaje
es que se cumpla la siguiente relación:
Las normas del lenguaje indican que solamente una de las igualdades puede cum-
plirse. Sin embargo, se deja libertad al compilador en lo relativo a los tamaños de ocu-
pación de cada uno de los tipos y a si se cumple una de las igualdades o no.
unsigned short hora, minutos, segundos;
// son números pequeños sin signo
long distancia = 100000L;
unsigned long int peso;
long deuda = -50000L;
short descuento (25);
www.udima.es 195
FUNDAMENTOS DE LA PROGRAMACIÓN
El tipo de datos real se representa mediante la palabra float. Este tipo representa
los valores reales. De esta forma, se pueden declarar variables reales e inicializarlas, si
se desea, de la siguiente forma:
float ancho, alto= 1.84; /* las variables son de tipo real */
También existe un tipo real de gran precisión. Para representar el tipo real de gran
precisión se puede usar la palabra double o bien, long float. Las dos siguientes defini-
ciones son equivalentes entre sí:
double ml= 8,467866e+47;
long float ml= 8,467866e+47;
/* milímetros cúbicos en un año luz cúbico */
Si todavía se requiere una precisión mayor en los números reales, se puede utilizar
el tipo real de muy alta precisión, que se representa mediante el tipo long double. Un
ejemplo de uso sería el siguiente:
long double gigante= +1.5e2222L;
196 www.udima.es
char digito= '1', car= 0;
/* car se inicializa con el valor del código ASCII de '\0' */
char a= 'a', salto= '\n', tab= '\007', letra, D= 68, digito;
bool final, terminado= true, seguir= 5, pagado= false;
// seguir es una variable lógica inicializada a verdadero
const bool verdadero= true, falso= false;
Para terminar con los tipos de datos básicos, hay que mencionar un tipo de datos
especial denominado «tipo nulo» o «tipo vacío». Se representa mediante la palabra
www.udima.es 197
FUNDAMENTOS DE LA PROGRAMACIÓN
reservada void y, como su propio nombre indica, no almacena ningún valor. Se utiliza
fundamentalmente en las funciones para indicar que no reciben parámetros o que no
devuelven ningún valor. Una función típica sin parámetros y sin valor de retorno sería
la declaración de la función principal:
void main (void);
4.7. PUNTEROS
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Aunque pueden considerarse los punteros como un tipo avanzado de datos, que se
estudiará más profundamente en la unidad didáctica 9, se van a dar aquí unas breves
nociones sobre su significado, declaración y uso para poder comprender mejor algunos
de los operadores que se verán en el epígrafe 5.
tipo * var;
int *p;
Para utilizar un puntero hay que emplear el operador de acceso a puntero u operador
de indirección, que se representa con un asterisco (*). Por ejemplo, si p apunta a un 8,
podrá consultarse su valor usando *p.
4.8. REFERENCIAS
Las referencias son una facilidad avanzada que permite referirse a una dirección
de almacenamiento por otro nombre. Se usa el símbolo &. Dicho de otra forma, las refe-
198 www.udima.es
rencias permiten crear alias para los objetos, de tal forma que se pueda referenciar a un
mismo dato con dos nombres distintos:
int i= 0;
int &iref=i; // iref es una referencia a la variable i
iref= 2; // es equivalente a i= 2;
Al definir una función con argumentos por referencia, se permite que dicha función los
modifique (tal como se verá en la unidad didáctica 8).
#include <iostream>
int main (void)
{
int j; // declaración de j
j= func (); // sentencia de asignación con llamada a una función
char car= get_car (); // declaración con incialización de car
for (int i= 0; i < j; ++i) // declaración de i
{
cout << "Iteración número " << i << '\n';
float f= prob (i); // definición de f
if (f > .8)
cout << "\tÉxito\n";
} // desaparecen f, i
if (7 != j)
error ();
} // desaparecen car, j
www.udima.es 199
FUNDAMENTOS DE LA PROGRAMACIÓN
El alcance de una variable se extiende hasta el final del bloque en el que se ha decla-
rado. Como caso particular, el alcance de la variable i se limita al bloque del for, ya que
su intención es utilizarla dentro de él.
Por ejemplo, en la operación de suma 4 + 1.3, el operando con valor entero se con-
vierte a real doble para realizar la operación (según la regla 5), por lo que el resultado es
también un valor real doble (5.3L). En la operación de suma 53UL + 20U, según la regla 7,
el valor entero sin signo deberá convertirse a entero de gran precisión sin signo y dará
el resultado 73UL. En la operación de suma 'A' + 40L, en primer lugar se convierte el
carácter a entero según la regla 1 (se obtiene el código correspondiente al carácter, que,
en este caso es 65) y, a continuación, se aplica la regla 8 para convertirlos a gran preci-
sión, lo que ofrece como resultado 105L.
200 www.udima.es
En general, puede decirse que, siempre que pueda aplicarse una de estas reglas, los
tipos son compatibles y, por tanto, pueden operarse entre sí. No obstante, hay que tener
en cuenta que si los dos operandos son del mismo tipo, el resultado también lo será. Por
ejemplo, en la expresión de división 8/5, el resultado, al ser ambos operandos enteros y
no ser necesaria ninguna conversión, será también entero (1) truncándose el valor, como
ocurre con este ejemplo.
5. OPERADORES
En los epígrafes anteriores se han estudiado cuáles son las clases de datos que se
pueden manejar cuando se realiza un programa en C++ y cómo se representan dichos
datos gracias a las constantes y las variables. Pero ahora surge la pregunta: ¿qué se
puede hacer con las variables y las constantes? Para responder, el lenguaje C++ tiene
unas estructuras especiales llamadas expresiones que permiten manejar estos datos
y realizar operaciones con ellos. A continuación se estudiará en qué consisten estas
expresiones, qué tipos hay y cómo se usan para programar con el lenguaje C++.
Operador. Elemento del lenguaje que permite indicar qué operación se va a realizar
con unos determinados datos.
Por ejemplo, supóngase que se está escribiendo un programa para calcular el dinero
que hay en una cuenta bancaria y en un determinado momento se necesita realizar una
operación de suma entre dos números. Para expresar esta operación en el programa
www.udima.es 201
FUNDAMENTOS DE LA PROGRAMACIÓN
se necesitaría, junto con los números, usar un operador que indique que la operación
que se realiza en el programa es la suma (+), con lo que el programa quedaría con la
siguiente forma:
número1 operador_de_suma número2
Retomando los ejemplos anteriores, se puede observar claramente que los operandos,
en el primer caso, son los números, mientras que en el segundo serían las variables cuyo
contenido se desea igualar.
Expresión. Sirve para representar y manejar los datos de una manera simple y
eficaz. Puede consistir simplemente en una constante, en una variable o ser una
combinación de constantes y variables interconectadas por uno o más operadores.
202 www.udima.es
-743
x ++
sizeof (x)
a/b
3 <= X
h && u
7 - 9
t > 2
a ? f : g
C++ tiene un amplio conjunto de operadores que hay que conocer para poder obtener
toda la potencia del lenguaje. Asimismo, es necesario conocer su prioridad y asociati-
vidad para poder utilizarlos apropiadamente.
Que un operador tenga mayor prioridad que otro debe interpretarse como que se rea-
lizará su operación en primer lugar. De esta manera, en la expresión a + b * c se calcu-
lará en primer lugar el producto y, a su resultado, se le sumará el valor de a. Esto es así
porque el * tiene mayor prioridad que la suma.
www.udima.es 203
FUNDAMENTOS DE LA PROGRAMACIÓN
En el siguiente cuadro se listan todos los operadores en grupos que están separados
por líneas horizontales. Cada grupo contiene operadores con la misma prioridad; esta va
disminuyendo a medida que se baja por el cuadro. Si no se indica lo contrario, se asocian
de izquierda a derecha. Se realiza una somera explicación del significado del operador,
pero en los siguientes epígrafes se estudiarán más detenidamente.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
* Referencia a un puntero
& Dirección
- Menos unario (número negativo)
+ Más unario (número positivo)
! No, negación lógica (NOT)
~ Complemento a 1
++ Autoincremento
-- Autodecremento
(tipo) Conversión forzada de tipos (casting)
sizeof exp Tamaño en memoria de la expresión exp
sizeof (tipo) Tamaño en memoria del tipo indicado
new Solicitud de memoria dinámica
delete Liberación de memoria dinámica
* Producto
/ División
% Módulo o resto de la división
.../...
204 www.udima.es
.../...
+ Suma
- Resta
| O (OR) de bits
|| O (OR) lógico
= Asignación
+= Suma los dos operandos y asigna el resultado al primero
-= Resta el primer operando menos el segundo y asigna el resultado al primero
*= Multiplica los operandos y asigna el resultado al primero
www.udima.es 205
FUNDAMENTOS DE LA PROGRAMACIÓN
.../...
<<= Desplaza el primer operando a la izquierda tantos bits como indique el segun-
do operando, asignando el resultado al primer operando
&= Realiza un AND bit a bit entre los dos operandos y asigna el resultado al primero
^= Realiza un XOR bit a bit entre ambos operandos y asigna el resultado al primero
|= Realiza un OR bit a bit entre los dos operandos y asigna el resultado al primero
Los operadores aritméticos, como su nombre indica, son los que permiten la reali-
zación de operaciones matemáticas simples dentro de un programa de C++. Las expre-
siones formadas con estos operadores reciben el nombre de expresiones aritméticas y
son de gran utilidad en la mayoría de los programas en C++. A lo largo de este epígrafe
se verán numerosos ejemplos de este tipo de expresiones. En el lenguaje existen cinco
operadores aritméticos:
Operador Significado
+ suma
- resta
* producto
/ división
% módulo
206 www.udima.es
Los operandos sobre los que actúan los operadores aritméticos deben representar
valores numéricos. Por tanto, los operandos deben ser cantidades enteras, reales o carac-
teres (debe recordarse que las constantes de carácter se representan con valores enteros,
que están determinados por el conjunto de caracteres del ordenador). El operador módulo
necesita, además, que los dos operandos sean enteros y que el segundo tenga un valor
distinto de cero. Por su parte, la división también necesita que el segundo operando no
tenga valor nulo, aunque en este caso los operandos no tienen por qué ser enteros. Otra
característica que hay que destacar de la división es que su resultado dependerá siempre
del tipo de operandos al que se aplica, tal como se ha explicado en el epígrafe anterior.
Si se usan dos operandos enteros, el cociente será otro número entero, con lo que se pro-
ducirá un truncamiento (eliminación) de la parte decimal del mismo en caso de que la
división no sea exacta. Sin embargo, si se usa al menos un número real, este truncamiento
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Por ejemplo, supóngase que las variables enteras a y b tienen valores 10 y 3, res-
pectivamente. Si se quiere aplicar a estas variables los operadores aritméticos, se consi-
guen los siguientes resultados:
Expresión Resultado
a + b 13
a - b 7
a * b 30
a / b 3
a % b 1
Dentro de los resultados obtenidos hay que destacar el truncamiento del cociente (es
decir, la eliminación de la parte decimal del mismo) que se produce al efectuar la división
de dos cantidades enteras, ya que su resultado solo puede ser otro número entero. Tam-
bién se puede ver claramente que el resultado de la operación con el operador módulo
coincide con el resto de la división de a y b.
Supóngase ahora que a y b son variables reales cuyos valores son 12.5 y 2.0, respec-
tivamente. Si se quiere calcular operaciones aritméticas con estas variables, se obtienen
los siguientes resultados:
www.udima.es 207
FUNDAMENTOS DE LA PROGRAMACIÓN
Expresión Resultado
a + b 14.5
a - b 10.5
a * b 25.0
a / b 6.25
radores aritméticos, se obtendrán los siguientes resultados (se supone que el ordenador
utiliza el juego de caracteres ASCII):
Expresión Resultado
a + b 164
a - b -4
a * b 6720
a / b 0
a + b + 5 169
a + b + '5' 217
En estos resultados se puede observar que 'P' está codificada como 80 en el juego
de caracteres ASCII, mientras que 'T' tiene como código 84. En los resultados también
se observa que el número 5 es muy distinto del carácter '5' en las operaciones aritmé-
ticas, ya que tienen un valor totalmente diferente (el número 5 tiene lógicamente un valor
de 5 mientras que el carácter '5' tiene un valor en el juego de caracteres ASCII de 53).
Finalmente, obsérvese que estos operadores tienen asociatividad de izquierda a derecha
y que el producto, división y módulo tienen mayor prioridad que la suma y la resta. De
esta manera, una expresión como:
a + b * c / d - e * f
208 www.udima.es
será equivalente a:
(a + ((b * c) / d)) - (e * f)
b * c
(b * c) / d
(a + ((b * c) / d))
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
e * f
(a + ((b * c) / d)) - (e * f )
Los operadores relacionales son aquellos que sirven para comparar valores entre
sí dando lugar a expresiones lógicas que se utilizan para representar condiciones dentro
de un programa, es decir, se usan para formar expresiones que, al ser evaluadas, toman
como valor final verdadero o falso.
Operador Significado
== igual que
!= distinto que
www.udima.es 209
FUNDAMENTOS DE LA PROGRAMACIÓN
a > b 0 falso
a < b 1 verdadero
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
a >= b 0 falso
a <= b 1 verdadero
a == b 0 falso
a != b 1 verdadero
a < b == c > d
se agrupará como:
(a < b) == (c > d)
210 www.udima.es
Operador Significado
&& y lógica
|| o lógica
! negación lógica
Los operadores lógicos permiten actuar sobre operandos que son a su vez expresiones
lógicas, es decir, expresiones que tienen como resultado al ser evaluadas 1 (verdadero) o 0
(falso). También permiten combinar condiciones individuales y formar otras expresiones
lógicas más complicadas cuyo resultado puede ser verdadero o falso. El resultado de la ope-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
ración «y lógica» (&&) será verdadero (es decir, devolverá un valor de 1) solo si los dos
operandos son verdaderos, mientras que el resultado de una operación «o lógica» (||) será
verdadero si al menos uno de los dos operandos es verdadero. En otras palabras, el resultado
de una operación «o lógica» será falso solo si los dos operandos son falsos. La operación de
negación lógica (que es un operador unario) invierte el valor de verdad del operando.
Por ejemplo, supóngase que las variables h, f y c toman valores 7, 5.5 y 'w', res-
pectivamente. Si se usan estas variables con los operadores relacionales para formar
expresiones lógicas y después se combinan usando los operadores lógicos, se obtienen
los siguientes resultados:
(h >= 6) && (c == 'w') 1 verdadero
(h >= 6) || (c == 'p') 1 verdadero
(f < 11) && (h > 100) 0 falso
!((c != 'o') || ((h + f) >= 10)) 0 falso
www.udima.es 211
FUNDAMENTOS DE LA PROGRAMACIÓN
Un aspecto importante que hay que tener en cuenta cuando se escribe una expresión
lógica estriba en que C++ realiza una evaluación en «cortocircuito» o «perezosa». Esto
significa que, si al evaluar una parte de la expresión se puede asegurar el valor completo
de la expresión, no se continuará evaluando el resto de la expresión. De esta manera,
supóngase que se tiene la siguiente expresión:
(a || c) && ((b < d) || (e > f) && !(k = j))
Si al ejecutar se determina que a y c son ambos falsos y, por tanto, el primer parén-
tesis se evalúa como falso, ya no es necesario seguir evaluando la expresión puesto que
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
falso AND cualquier otra cosa siempre valdrá falso; por lo tanto, el valor de toda la expre-
sión será falso. En cambio, si una de las dos variables fuera verdadera, entonces se tendría
que seguir evaluando el segundo paréntesis para obtener el valor final de la expresión.
Saber esto puede resultar de especial importancia si en alguna parte de la expresión existe
algún operador que modifica un valor o una llamada a una función; en este caso, puede
ocurrir que no se ejecute esa parte de la expresión y provoque funcionamientos no espe-
rados por el programador. Por ejemplo, supóngase la siguiente expresión:
a && (f(5) < d)
212 www.udima.es
a= 3
x= z
delta= 0.001
area= longitud + anchura
Si los dos operandos de una sentencia de asignación son de diferentes tipos de datos,
el valor de la expresión a la derecha del operador se convertirá automáticamente al tipo
de la expresión de la izquierda, si son compatibles (en otro caso, se producirá un error
de compilación). De esta forma se consigue que toda la expresión de asignación sea del
mismo tipo de datos. En determinados casos, la conversión de tipo automática puede
llevar una modificación del dato que se está asignando. Por ejemplo:
• Un valor real puede ser truncado (es decir, eliminados sus decimales) si se
asigna a un identificador de tipo entero.
• Una cantidad entera puede ser alterada si se asigna a un identificador de tipo
carácter (se podrían perder algunos de los bits más significativos).
Por ejemplo, en las siguientes expresiones, supóngase que h es una variable de tipo
entero y que se usa el conjunto de caracteres ASCII. A continuación se verán qué alteraciones
de los datos se producen por la conversión automática en las expresiones de asignación:
Expresión Resultado
h= 3.3 3
h= 3.9 3
h= -3.9 -3
.../...
www.udima.es 213
FUNDAMENTOS DE LA PROGRAMACIÓN
Expresión Resultado
.../...
h= 'x' 120
h= '0' 48
h= ('x' - '0')/3 24
h= ('y' - '0')/3 24
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Llegado este punto, y con el fin de evitar errores, es conveniente señalar y recordar
que el operador de asignación (=) es totalmente distinto al operador de igualdad (==). El
primero, como se acaba de comentar, se emplea para asignar valor a un identificador,
mientras que el segundo se usa para comparar si dos expresiones tienen el mismo valor.
Otra cuestión que interesa conocer es que en el lenguaje C++ las operaciones de
asignación devuelven como resultado el valor que se asigna. Esto permite usar una asig-
nación como expresión actuando a modo de operando de otra expresión. Asimismo, están
permitidas las asignaciones múltiples de la forma:
id1= id2= id3= expresión
id1= (id2= (id3= expresión))
214 www.udima.es
Y, a su vez, es equivalente a:
id3= expresión
id2= id3
id1= id2
Por ejemplo, supóngase que h y j son dos variables de tipo entero. Supóngase tam-
bién la expresión de asignación múltiple: h= j= 5. En esta expresión se puede ver que,
primero, hay una asignación de 5 a la variable entera j y, después, se produce una asig-
nación del valor de j a h.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Al igual que cualquier operador, se puede combinar con otros operadores para formar
expresiones más complejas. Por ejemplo, la siguiente expresión es válida en C++ (como
la asignación tiene una de las prioridades más bajas son necesarios los paréntesis):
a= b + (c= 5 * 2) + d
c= 5 * 2
a= b + c + d
C++ dispone además de otros operadores de asignación, que son una combinación
del operador = con otros operadores. Dentro de los operadores aritméticos de asignación
se tienen los siguientes:
Operador Significado
www.udima.es 215
FUNDAMENTOS DE LA PROGRAMACIÓN
Por ejemplo, considérese que x, z, f y g son variables con valores 5, 7, 5.5 y -3.25,
respectivamente. Si se utilizan estas variables para ver cómo se usan los operadores de
asignación que se acaban de ver, se obtienen los siguientes resultados:
x += 5 10 x=x+5
z *= x - 3 14 z = z * (x – 3)
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
x %= z - 2 0 x = x % (z – 2)
216 www.udima.es
En el lenguaje C++ hay tres operadores lógicos de bits: «y de bits» (&), «o exclu-
siva de bits» (^) y «o de bits» (|). Cada uno de estos operadores requiere dos operandos
enteros. Las operaciones con estos operadores se realizarán de forma independiente en
cada par de bits que corresponde a cada operando, es decir, se comparan los bits menos
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
significativos (los bits más a la derecha) de los dos operandos; después, los siguientes
bits menos significativos, y así sucesivamente, hasta que se comparen todos los bits. Los
resultados de estas comparaciones serán:
• Una operación y de bits retornará un uno si ambos bits tienen el valor uno.
En otro caso, retornará un valor de cero.
• Una operación o exclusiva de bits retornará un uno si uno de los bits tiene
un valor de uno y el otro tiene un valor de cero. En otro caso retornará un
valor de cero.
• Una operación o de bits retornará un uno si alguno de los bits tienen el valor
de uno. Si ambos valen cero, devolverá un valor cero.
Por ejemplo, supóngase que a y b son variables enteras sin signo cuyos valores en
hexadecimal son 0x6db7 y 0xa726, respectivamente. Si se emplean los operadores lógicos
de bits con estas variables, se obtienen los siguientes resultados:
Expresión Resultado
a & b 0x2526
a ^ b 0xCA91
a | b 0xEFB7
www.udima.es 217
FUNDAMENTOS DE LA PROGRAMACIÓN
Cada uno de los operadores lógicos de bits tiene su propia precedencia. El operador
y de bits tiene la mayor precedencia, seguido por la o exclusiva de bits y después por la
o de bits. La asociatividad para cada operador de bits es de izquierda a derecha.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Por ejemplo, supóngase que a es una variable entera sin signo cuyo valor es 0x6db7.
La expresión b= a << 6 desplazará todos los bits seis posiciones a la izquierda y asignará
el valor resultante a la variable b (0x6dc0). A continuación se muestran los bits, subra-
yando los bits eliminados de a y los bits añadidos en a << 6:
218 www.udima.es
sea negativo, el lenguaje no especifica cómo completar los nuevos bits, y se deja como
una decisión del diseño del compilador. Las opciones son rellenar con ceros o rellenar
con unos (en este caso, que es el más habitual, lo que se está haciendo es duplicar el bit
más significativo, que es el bit que indica el signo).
Por ejemplo, supóngase que a es una variable cuyo valor es 0x6db7. La expresión
b= a >> 6 desplazará todos los bits seis posiciones a la derecha y asignará el valor resul-
tante a la variable b (0x01b6). A continuación se muestran los bits, subrayando los bits
eliminados de a y los bits añadidos en a >> 6:
El operador >> se emplea para realizar la entrada y el operador << para la salida:
canal_de_entrada >> variable;
canal_de_salida << expresión;
cout << x << y << z; // imprime en pantalla las tres variables
www.udima.es 219
FUNDAMENTOS DE LA PROGRAMACIÓN
Operador Significado
Por ejemplo, supóngase una variable v que representa un determinado dato. Con-
sidérese también p una variable de tipo puntero. Si se desea almacenar la posición de
220 www.udima.es
Su principal uso es para consultar el valor que tiene la posición de memoria contenida
en una variable de tipo puntero.
Aparte de los operadores que se han examinado hasta ahora, el lenguaje C++ tiene otra
serie de ellos que permiten la realización de ciertas operaciones especiales y que no pueden
agruparse dentro de los epígrafes anteriores. A continuación se revisarán estos operadores.
Los operadores paréntesis permiten realizar llamadas a funciones (un aspecto que se
estudiará más adelante). No deben confundirse los operadores paréntesis de llamada a fun-
ción con los paréntesis que se pueden colocar en cualquier expresión para alterar la pre-
cedencia o asociatividad. Los paréntesis, como operador, únicamente sirven para llamar
a funciones.
Este es un operador n-ario, es decir, que puede llevar varios operandos en número
variable. No obstante, al menos debe existir el primer operando, que consiste en el nombre
www.udima.es 221
FUNDAMENTOS DE LA PROGRAMACIÓN
de la función que va a ser llamada. Este operando se coloca antes de los paréntesis. Los
siguientes operandos, si existen, se colocan entre los paréntesis, separados por comas si
hubiera más de uno.
Funcion () // llamada a una función sin parámetros
suma (a, b) // llamada a una función con dos parámetros
Imprime (a/b, suma (5, c), fin && z)
// llamada a función con múltiples expresiones como parámetros
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
expresión1 ? expresión2 : expresión3
x= (a > b) ? a : b
222 www.udima.es
Estos operadores se emplean para indicar el signo de una constante numérica, una
variable o una expresión. Los operadores son el más (+) y el menos (-). Hay que darse
cuenta de que la operación definida por estos operadores (necesitan un solo operando)
es diferente de la definida por los operadores aritméticos que representan la suma y la
resta (requiere dos operandos). Evidentemente, el operador + no modifica el resultado,
de tal manera que resulta redundante ponerlo. He aquí algunos ejemplos en los que se
emplean estos operadores:
-123
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
+1
a += -1 - -c * -(a/b)
z= (x < 0) ? -x : +x
Por ejemplo, supóngase que x es una variable que tiene asignado el valor 5. La
expresión ++x, que es equivalente a escribir x= x + 1, hace que el valor de x sea 6, es
decir, se incremente en una unidad. Análogamente, la expresión --x, que es equivalente
a x= x - 1, hace que el valor (partiendo del valor original) pase a ser 4.
www.udima.es 223
FUNDAMENTOS DE LA PROGRAMACIÓN
Por ejemplo, considérese la variable x, que toma el valor 55, y la variable de tipo
entero z. Las siguientes expresiones pondrán de manifiesto la diferencia de un operador
de incremento o decremento según se use como prefijo o sufijo:
Expresiones
Expresión Resultado
equivalentes
z= x z= 55
z= x++
x= x + 1 x= 56
x= x + 1 z= 56
z= ++x
z= x x= 56
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
z= x z= 55
z= x--
x= x - 1 x= 54
x= x - 1 z= 54
z= --x
z= x x= 54
Este operador (sizeof) se emplea para calcular el tamaño en bytes (l byte = 8 bits)
del operando al que se aplica, según la implementación del compilador. Este operador
precede siempre a su operando, que suele ser una expresión o un tipo de datos (en este
caso, es obligatorio poner paréntesis). En programas sencillos no es recomendable utilizar
este tipo de operador. Sin embargo, es muy útil cuando se transfiere un programa de un
compilador a otro o a una nueva versión del lenguaje C++. A continuación se presentan
varios ejemplos del funcionamiento del operador sizeof, aplicado a una variable entera
(a), una expresión real (f es float) y al tipo carácter (para un determinado compilador):
sizeof a == 2
sizeof (f * 2) == 4
sizeof (char) == 1
224 www.udima.es
((int) (x + f)) % 4
(int (x + f)) % 4
Nótese que este operador no modifica el tipo del operando, sino que devuelve como
resultado un dato del tipo indicado. Es decir, si f fuera entera con un valor de 8, en la
expresión (float) f, la variable f seguirá siendo entera, pero el resultado de la expre-
sión será el valor real 8.0.
El operador coma (,) permite que aparezcan dos expresiones en situaciones donde
solo se utilizaría una expresión ordinariamente. La sintaxis consiste en poner dos expre-
siones separadas por comas. El lenguaje garantiza que las expresiones se ejecutarán en
el orden en el que están escritas, es decir, primero la de la izquierda y luego la de la
derecha. La expresión devolverá el resultado de la ejecución de esta última expresión.
Este operador se emplea principalmente en la sentencia for, cuyo estudio se realizará
con posterioridad.
Por ejemplo, supónganse dos variables, x y z, a las que se desea asignar el valor 5
y 8, respectivamente, y la variable a, a la que se le quiere asignar el valor de y. Normal-
mente esto se podría conseguir con las sentencias:
www.udima.es 225
FUNDAMENTOS DE LA PROGRAMACIÓN
x= 5;
a= y= 8;
Sin embargo, se puede utilizar el operador coma para reducir código, sustituyendo
las dos sentencias por una sola:
a= (x= 5, y= 8);
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Como se estudiará más adelante, en el lenguaje C++ existen unos tipos de datos que
se denominan estructuras, uniones y clases (propias estas de la orientación a objetos).
Estos tipos de datos consisten en un conjunto de variables o campos (también denomi-
nados miembros) de diferente tipo que se encuentran agrupados en un registro común.
Para acceder a cada una de estas variables existentes se emplea el operador punto (.).
registro.miembro
Por ejemplo, supóngase que se tiene el registro fecha, que se compone de las varia-
bles año, mes y día. Para poder consultar el valor de estos miembros del registro se
empleará el operador punto de la siguiente forma:
fecha.dia
fecha.mes
226 www.udima.es
Si en lugar de tener una variable del tipo registro, se tiene un puntero a un registro,
entonces se utilizará el operador flecha (->) de manera análoga:
punterofecha->dia
punterofecha->mes
Por otra parte, los operadores binarios .* y ->* son los operadores de acceso a pun-
teros a miembros de un registro.
al registro T (para ->*) y el segundo operando debe ser un puntero a un miembro del
registro T. En ambos casos, el resultado es un elemento o una función del tipo indicado
por el segundo operando. Estos operadores, de poco uso, tienen su mayor utilidad en la
orientación a objetos.
int i= 5;
int f (int i)
www.udima.es 227
FUNDAMENTOS DE LA PROGRAMACIÓN
{
return i ? i : ::i;
// si i (local) no es 0 devuelve i,
// si no, devuelve la i global (5)
}
struct X
{
static int n;
};
int X::n= 9; // Se asigna 9 al campo n del registro X
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Un puntero, hasta que se inicialice, hace referencia a una posición de memoria in-
determinada. Por esta circunstancia, no se puede utilizar su valor hasta que el puntero
se haya inicializado correctamente. El operador new se encarga de reservar la memoria
necesaria para albergar el tipo de dato especificado. Tras realizar la reserva, retorna la
dirección de memoria en la que empieza el bloque solicitado. El operador unario new
recibe como operando el tipo para el que tiene que buscar memoria.
La sintaxis es la siguiente:
puntero_a_tipo= new tipo;
En caso de que no se pueda encontrar suficiente memoria, new devuelve NULL y lanza
una excepción. En caso contrario, devuelve un puntero a la zona de memoria asignada.
int *p= new int (0);
/* p apunta a una zona de memoria reservada que contiene un 0 */
228 www.udima.es
Para solicitar memoria para un vector, hay que indicar su tamaño entre corchetes:
char *c= new char [80];
// c apunta a un vector de 80 caracteres
float *p[25]= new float [9][25];
// vector de 25 punteros a 9 float
Siempre que se reserve memoria con new es preciso retornarla al sistema cuando
esta deja de ser necesaria. Para ello se utiliza el operador delete. Este operador lo único
que hace es introducir el bloque en una tabla de bloques de memoria vacíos. No «anula»
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
las referencias que puedan existir. El operador unario delete recibe como operando
un puntero obtenido con new y libera la memoria asignada. La sintaxis es la siguiente:
delete puntero;
delete [] vector;
Aplicar el operador delete sobre un puntero nulo es totalmente inofensivo. Los ope-
radores new y delete aplicados sobre un puntero a un registro invocarán, respectivamente,
al constructor y al destructor del objeto, si existen (conceptos de orientación a objetos).
www.udima.es 229
FUNDAMENTOS DE LA PROGRAMACIÓN
CONCEPTOS BÁSICOS
• El lenguaje C++ dispone de varios tipos de constantes: enteras, reales,
carácter, lógicas y cadenas.
• Hay distintos tipos de constantes enteras con distinta precisión y se
pueden escribir con tres notaciones.
• Hay distintos tipos de constantes reales con distinta precisión y se pueden
escribir con dos notaciones.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1
230 www.udima.es
Enunciado 2
a) Float a, b;
b) char c= "hola";
c) const float pi= 3.1415926;
d) unsigned long double int a;
e) boolean d;
f) int estimación;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
g) void k
Enunciado 3
a) a= false, b= !a
b) a && !a
c) ((a == b) && (b != 0)) ? a : 8
d) a |= 0xFF
Enunciado 4
a) i += sizeof (int)
b) x= y= (a == b) ? 10 : b
c) v= (a += 1, a & 2)
d) a + b= 5
Enunciado 5
www.udima.es 231
FUNDAMENTOS DE LA PROGRAMACIÓN
a) Los nombres de variables solo pueden estar formados por letras y dígitos.
b) Cuando se declara una variable, hay que inicializarla siempre con un valor.
c) Las palabras int, char, void, real, double y long representan tipos básicos
en C++.
d) Si el programador quiere cambiar el orden de evaluación de una expresión,
puede usar paréntesis para alterar la prioridad de los operadores.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
232 www.udima.es
Solución 1
Solución 2
c) const float pi= 3.1415926;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Solución 3
b) a && !a
Solución 4
d) a + b= 5
Solución 5
ACTIVIDADES DE REPASO
1. Escribir una expresión que sirva para determinar si dos números reales son
iguales o no; en caso de que lo sean, deberá devolverse verdadero y en caso
contrario, falso.
www.udima.es 233
FUNDAMENTOS DE LA PROGRAMACIÓN
REFERENCIAS BIBLIOGRÁFICAS
Básica
Avanzada
Deitel, H. y Deitel, P. J. C++ How to Program. 7.ª ed. Prentice Hall, 2009.
Fuertes, J. L. y González, Á. L. El lenguaje de programación C. Koobeth International, 2004.
Kernighan, B. W. y Ritchie, D. M. The C Programming Language. 2.ª ed. Prentice Hall, 2004.
Liberty, J.; Rao, S. y Jones, B. L. Sams Teach Yourself C++ in One Hour a Day. Sams, 2008.
234 www.udima.es
7
UNIDAD
DIDÁCTICA
SENTENCIAS Y
ENTRADA/SALIDA BÁSICA
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Objetivos de la unidad
1. Introducción
2. Sentencias básicas
2.1. Asignación
2.2. Llamada a funciones
2.3. Sentencia «return»
2.4. Sentencia vacía
www.udima.es 235
FUNDAMENTOS DE LA PROGRAMACIÓN
4. Entrada/salida básica
4.1. Salida
4.2. Entrada
Conceptos básicos
Actividades de autocomprobación
Actividades de repaso
Referencias bibliográficas
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
236 www.udima.es
OBJETIVOS DE LA UNIDAD
Para que un ordenador realice una tarea tiene que estar descompuesta en una serie
de instrucciones o acciones más simples. En los lenguajes de programación, la unidad
más básica de programación es la sentencia.
una tortilla española. Este es el tipo de descomposición de una tarea compleja (preparar
la tortilla) en sentencias simples (cortar la patata).
Las sentencias son uno de los elementos básicos del lenguaje C++. Se ejecutan
secuencialmente, es decir, una detrás de otra. También existen sentencias que permiten
alterar el orden de ejecución, como las sentencias condicionales (que ejecutarán unas
sentencias u otras), las sentencias repetitivas (que permiten repetir la ejecución de ciertas
sentencias) y las sentencias de salto (que permiten saltar a una parte del código).
www.udima.es 237
FUNDAMENTOS DE LA PROGRAMACIÓN
1. INTRODUCCIÓN
El lenguaje C++ dispone de distintos tipos de sentencias que se usan para construir
programas. De esta manera, el resultado de un programa es la ejecución de sus senten-
cias. Cada sentencia finaliza por un punto y coma. Aunque es posible escribir en una
línea varias sentencias distintas, es más elegante y legible escribir una por línea. Tam-
bién se pueden agrupar las sentencias en un bloque, encerrándolas entre llaves {}. Este
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
En esta unidad didáctica van a estudiarse las sentencias del lenguaje C++. En primer
lugar, se explicará brevemente la sentencia de asignación. Aunque ya se ha estudiado el
operador de asignación, por su importancia y frecuencia de uso resulta interesante men-
cionarlo como sentencia, aunque cualquier expresión puede constituir por sí misma una
sentencia. También se mencionará la llamada a funciones como sentencias, que consti-
tuyen otro de los tipos de sentencias más utilizados en la práctica. Después, se pasará a
estudiar las sentencias de control de flujo, como las sentencias condicionales, las sen-
tencias repetitivas y las sentencias de salto.
Finalmente, para empezar a escribir programas que tengan interacción con el usuario,
se hará una pequeña introducción a las instrucciones de entrada/salida básica.
2. SENTENCIAS BÁSICAS
2.1. ASIGNACIÓN
Por tanto, al proceso de almacenar algo en una variable se le llama «asignar». Para
poder asignar valores a una variable, esta debe ser de un tipo compatible con el valor
238 www.udima.es
que se quiere guardar. Para que el valor entero 7 se almacene en una variable de tipo
int se haría:
x= 7;
Como puede observarse, la sentencia de asignación está formada por una expresión
en la que se usa el operador de igualdad (=) y, como toda sentencia, hay que añadir el
punto y coma al final. Por tanto, una sentencia de asignación tendrá el siguiente aspecto:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
variable= expresión;
El valor almacenado en una variable sigue disponible hasta que a esa misma va-
riable se le asigna otro valor distinto o se termina el programa o función en el que está
declarada.
LongitudCircunferencia= 3.1416 * 2 * radio;
Por supuesto, en lugar del operador de igualdad se puede utilizar alguno de los otros
operadores de asignación vistos en la unidad didáctica 6. Por ejemplo:
x *= 2;
a += b - x--;
c &= d << 2;
www.udima.es 239
FUNDAMENTOS DE LA PROGRAMACIÓN
a + b;
c && d;
(a != b) ? a : b;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
a /= 10;
x++;
i= j= k= '\0';
Otra expresión que también puede utilizarse como una sentencia es la llamada a una
función. Una función puede devolver un valor o puede no devolver nada. En el primer
caso, el valor se perdería, pero a veces es necesario ejecutar una función para realizar
cierta tarea. Es decir, aunque una función devuelva un valor, no es obligatorio recogerlo.
Para hacer una llamada a una función se escribe el nombre de la función seguido de un
par de paréntesis que encierran los parámetros (si los hubiera).
mayor= max (a, b);
// sentencia de asignación con llamada a función
leer_teclado (); // llamada a función sin parámetros
Hipotenusa (cateto1, cateto2);
// llamada a función con dos parámetros
240 www.udima.es
hipotenusa= sqrt (cateto1 * cateto1 + cateto2 * cateto2);
/* La hipotenusa es la raíz cuadrada de la suma del
cuadrado de los catetos. */
x= pow (3, 4); // 3 elevado a 4, es decir, 81
a= cos (pi/2); // a será 0
Esta sentencia tiene su utilidad cuando se emplea dentro de una función. La sen-
tencia return fuerza la finalización de la ejecución de la función. De esta manera, al
www.udima.es 241
FUNDAMENTOS DE LA PROGRAMACIÓN
encontrar esta sentencia dentro de una función se retorna de dicha función al lugar desde
donde fue realizada la llamada. En caso de que la sentencia return vaya acompañada de
una expresión, el resultado de la evaluación de esta es el valor que devuelve la función.
return [expresión];
algún tipo de retorno, la sentencia return debe devolver un valor compatible con el tipo de
la función. Las siguientes dos funciones constituyen un ejemplo de uso de esta sentencia:
int max (int a, int b)
{
return (a > b) ? a : b; // devuelve el resultado de la expresión
}
void imprime (int a, int b, int c)
{
Escribe (max (a, b) + c);
return; /* si se omite, la función termina al alcanzar la
llave de cierre */
}
Un tipo de sentencia que también se suele utilizar principalmente para dotar de mayor
claridad al código es la sentencia vacía. Esta sentencia, en realidad, no hace absolutamente
nada, aunque en ocasiones interesa utilizarla para mejorar la legibilidad del código fuente.
242 www.udima.es
Se dice que, a medida que el programa se va ejecutando, el control pasa de una sen-
tencia a otra.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
El flujo de control más elemental es el flujo secuencial, es decir, cuando las sen-
tencias se ejecutan secuencialmente en el orden en el que aparecen en el programa. Por
ejemplo, las siguientes sentencias siguen un flujo secuencial pues se ejecutan en el mismo
orden en el que están escritas:
a= b;
contador= contador + 1;
leer_teclado (b);
mayor= max (a, b);
www.udima.es 243
FUNDAMENTOS DE LA PROGRAMACIÓN
if (condición)
sentencia;
Una variante de esta sentencia es la que incluye varias sentencias en forma de bloque:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
if (condición)
{
sentencias;
}
if (a > b)
a= b - 10;
if ((x == 5) && !fin)
{
x--;
fin= funcion ();
}
244 www.udima.es
if (condición)
sentencia1;
else
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
sentencia2;
Una variante es la que incluye varias sentencias en forma de bloque (que puede
estar en la parte then o en la parte else):
if (condición)
{
sentencias1;
}
else
{
sentencias2;
}
if (a > b)
max= a;
else
max= b;
www.udima.es 245
FUNDAMENTOS DE LA PROGRAMACIÓN
if ((x == 5) && !fin)
{
x--;
fin= funcion ();
}
else
z= sqrt (2);
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Por supuesto, tanto dentro de la parte then como en la parte else se admite cual-
quier sentencia válida del lenguaje y eso incluye otras sentencias de control de flujo,
incluida la propia sentencia if:
if (a > b)
max= a;
else
{
if (x != y)
x= y;
max= b + x;
}
Cuando el número de posibles alternativas que hay que considerar es muy elevado,
puede resultar muy tedioso y complejo escribir una estructura de sentencias if anidadas. En
este caso, los lenguajes de programación suelen ofrecer otra estructura condicional a la que
se denomina sentencia de selección múltiple. En el lenguaje C++, su sintaxis es la siguiente:
switch (expresión)
{
246 www.udima.es
case et1: sentencias1;
...
case etn: sentenciasn;
[default: sentencias;]
}
sentencias del default (si existe). La expresión debe devolver un valor que sea de
tipo int o char.
switch (dia)
{
case 1: lunes();
case 2: martes();
case 3: miercoles();
case 4: jueves();
case 5: viernes();
default: fiesta();
}
www.udima.es 247
FUNDAMENTOS DE LA PROGRAMACIÓN
varias sentencias un cierto número de veces. Para conseguir esto, sin tener que escribir
repetidas veces la misma sentencia (y hay que tener en cuenta que el número de veces
exacto que hay que repetir su ejecución normalmente se desconoce durante la imple-
mentación), se utilizan las estructuras de control repetitivas, también llamadas estruc-
turas iterativas o bucles.
El cuerpo del while puede contener una única sentencia o un bloque de sentencias,
por lo que su sintaxis en lenguaje C++ es una de las que siguen:
while (condición)
{
sentencias;
}
248 www.udima.es
while (condición)
sentencia;
El bucle con condición de entrada hará que se ejecuten las sentencias mientras
que la condición sea verdadera (distinto de cero). Cuando resulte cero, se finalizará la
ejecución del bucle.
while (i < DIM)
{
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
escribe (cuadrado (i));
i= i + 1;
}
Dentro del cuerpo del while se puede colocar cualquiera de las sentencias válidas
del lenguaje e, incluso, otras sentencias de control de flujo. De esta manera, el siguiente
código escribirá los números comprendidos entre 1 y 1000 que sean divisibles por un
cierto número que deberá guardarse previamente en la variable divisor. Obsérvese cómo
se autoincrementa la variable contador, en este caso, dentro de la condición:
contador= 0;
while (++contador <= 1000)
if ((contador % divisor) == 0)
escribe (contador);
www.udima.es 249
FUNDAMENTOS DE LA PROGRAMACIÓN
Otra de las sentencias repetitivas es la que forma el bucle for. En este tipo de bucle,
normalmente, se usa una o varias variables que sirven como control del número de itera-
ciones, es decir, del número de veces que se van a repetir las sentencias que se incluyan
dentro de esta sentencia. La sintaxis del bucle for en el lenguaje C++ tiene dos formatos
dependiendo de si su cuerpo contiene una o varias sentencias:
Un bucle for en C++ es, por tanto, equivalente al siguiente grupo de instrucciones:
inicialización;
while (condición)
{
sentencias;
actualización;
}
La ventaja de utilizar el for en lugar del while es tener en la cabecera del bucle
tanto la inicialización como la condición y la actualización.
250 www.udima.es
for (ascii= 32; ascii < 128; ascii++)
escribe (ascii);
for (n= 1, total= 0; n < MAX; total += n, n++)
; // sentencia vacía
En este ejemplo, se inicializan dos variables (haciendo uso del operador coma) y,
mientras que se cumpla la condición, se ejecutará la sentencia vacía (que no hace nada).
Seguidamente, se actualiza el valor de las dos variables (de nuevo utilizando el operador
coma, por lo que primero se modifica el valor de la variable total y luego se incrementa
el valor de n) y se vuelve a comprobar la condición.
Por supuesto, dentro de un bucle for se puede escribir cualquier sentencia, incluso
otras sentencias de control de flujo. En el siguiente ejemplo se toma cada número com-
prendido entre 1 y 100 y se comprueba entre qué números es divisible de los compren-
didos entre 2 y 10; si es divisible, se llama a la función escribe con ambos valores:
int divisor, numero;
for (numero= 1; numero <= 100; numero++)
for (divisor= 2; divisor <= 10; divisor++)
if (numero % divisor == 0)
escribe (numero, divisor);
En este ejemplo aparece una iteración anidada dentro de otra. En total, la sentencia
for interna se ejecutará 100 veces y cada vez que se ejecute provocará la ejecución de
la sentencia if un total de nueve veces. Por lo tanto, la sentencia if de este ejemplo se
ejecutará 900 veces.
www.udima.es 251
FUNDAMENTOS DE LA PROGRAMACIÓN
do
sentencia;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
while (condición);
do {
sentencias;
} while (condición);
do {
i= i + 1;
calcular_probabilidad (i);
} while (i < MAXIMO);
252 www.udima.es
do
car= leer_caracter ();
while (car != '\n');
break;
Como ejemplo, supóngase que se tiene una lista de 3.000.000 de personas y se quiere
averiguar si hay alguna menor de edad. Se construirá un código que vaya leyendo la edad
de cada una de las personas, y tan pronto como encuentre alguna menor de 18 años, se
abandonará el bucle. La variable menor será cierta si se ha encontrado un menor de edad.
www.udima.es 253
FUNDAMENTOS DE LA PROGRAMACIÓN
int edad;
long contador;
bool menor;
for (contador= 1;
contador <= 3000000L;
++contador)
{
edad= leerEdad (contador);
if (edad < 18)
break;
}
menor= contador < 3000000L;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Si, por ejemplo, la quinta persona es menor de edad, el bucle solo se ejecutará cinco
veces (así se evita tener que seguir ejecutando el bucle si ya se ha cumplido el objetivo bus-
cado); de no utilizar la sentencia break, el bucle se ejecutaría siempre 3.000.000 de veces.
Este uso de la sentencia break, que puede parecer bastante corriente, siempre se
puede evitar, quedando normalmente un código mejor estructurado. Véase cómo se evita
el uso de break en el ejemplo anterior:
int edad;
long contador;
bool menor= false;
for (contador= 1;
(contador <= 3000000L) && (menor == false);
++contador)
{
edad= leerEdad ();
if (edad < 18)
menor= true;
}
Pero mucho más frecuente es el uso de la sentencia break dentro de una sentencia
switch. De hecho, lo habitual es utilizar la sentencia switch conjuntamente con la sen-
tencia break.
Cuando break aparece en una sentencia switch, se provoca un salto al final del
switch, sin que se ejecute el resto de sentencias que aparecen a continuación.
254 www.udima.es
Típicamente aparecerá una sentencia break como última sentencia de cada case.
En el siguiente ejemplo, solamente se llamará a la función correspondiente según el
valor de dia. De esta manera, si dia fuera 4, solamente se ejecutaría la función jueves:
switch (dia)
{
case 1: lunes(); break;
case 2: martes(); break;
case 3: miercoles(); break;
case 4: jueves(); break;
case 5: viernes(); break;
default: fiesta();
}
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
continue;
for (i= 0; i < MAX; i++)
{
if (!primo (i))
continue; // Se salta "escribe(i)" y pasa a
// la condición del bucle "for"
escribe (i);
}
www.udima.es 255
FUNDAMENTOS DE LA PROGRAMACIÓN
Este ejemplo consiste en un bucle que escribe todos los números primos entre 0 y
MAX. La sentencia condicional evalúa si el número es primo y, en caso de no serlo, se
ejecuta la sentencia continue, que provoca que se ejecute directamente el incremento
de la variable y prosiga la siguiente iteración del bucle.
Este ejemplo es muy sencillo y, al igual que ocurría con la sentencia break, no se
recomienda abusar de su uso por poder dificultar en ocasiones la comprensión del código.
El ejemplo anterior quedaría mucho más claro de la siguiente manera:
for (i= 0; i < MAX; i++)
if (primo (i))
escribe (i);
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
4. ENTRADA/SALIDA BÁSICA
El lenguaje no dispone de palabras reservadas para realizar todas estas tareas que,
por otro lado, resultan fundamentales para dotar de interacción al programa. El problema
se soluciona con una serie de librerías que proporcionan todas las herramientas necesa-
rias para realizar la entrada/salida que pueda requerir el programador.
En C++ se define un canal (stream) como un tipo de datos que transporta cualquier
flujo de datos desde una fuente a un consumidor. Los canales cin, cout y cerr son tres
canales estándar que se encuentran predefinidos y que se utilizan, respectivamente, para
la entrada, la salida y la generación de mensajes de error.
Para poder utilizar estos canales de entrada/salida debe incluirse el fichero de cabe-
cera iostream.h.
256 www.udima.es
4.1. SALIDA
La salida por un canal se indica con el operador de inserción (<<) que se encuentra
sobrecargado para las operaciones de salida. Recibe como primer operando un canal de
salida y, como segundo, la expresión cuyo valor se pretende mostrar. Además, dado que
es asociativo por la izquierda y que devuelve una referencia al primer operando, pueden
encadenarse varias salidas:
cout << "Resultado : z= " << x * y << '\n';
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
La clase diseñada para realizar la salida es ostream, y dispone de una serie de fun-
ciones que pueden emplearse para facilitar la salida de información y que se explicarán
en la unidad didáctica 10.
Una manera sencilla de dar un formato específico a la salida consiste en utilizar los
manipuladores. Para utilizarlos hay que incluir el fichero iomanip.h. Algunos manipuladores
se muestran en el cuadro siguiente (y en la unidad didáctica 10 se explicarán algunos más).
Su utilización es sencilla:
cout << hex << v << endl;
// Muestra v en hexadecimal y salta de línea
www.udima.es 257
FUNDAMENTOS DE LA PROGRAMACIÓN
Al igual que se usa el canal cout, se puede utilizar el canal cerr para mostrar infor-
mación. No obstante, este canal debería reservarse para mostrar únicamente información
sobre errores producidos durante la ejecución de la aplicación.
4.2. ENTRADA
cin >> x >> y; // Lee valores y los introduce en variables x, y
En este ejemplo, cuando se ejecute, se leerán del teclado dos valores (del tipo que
tengan x e y) y dichos valores se almacenarán, respectivamente, en las variables x e y.
Hay que tener en cuenta que las variables pueden ser de cualquier tipo de los válidos para
leer de teclado, como enteros, reales o cadenas, pudiéndose mezclar en una sentencia
de entrada de datos varios de estos tipos. Así, en el ejemplo anterior podrían haber sido
declaradas x como entera e y como real.
La clase diseñada para realizar la entrada es istream y dispone de una serie de fun-
ciones que pueden emplearse para realizar la entrada de información y que se explicarán
en la unidad didáctica 10.
258 www.udima.es
CONCEPTOS BÁSICOS
• El lenguaje C++ dispone de un conjunto reducido de sentencias, que son
fáciles de aprender.
• Dentro de las sentencias básicas, se encuentran la sentencia de asignación,
la sentencia de llamada a funciones, la sentencia de retorno de funciones y
la sentencia vacía.
• Las sentencias de control de flujo se dividen en sentencias condicionales,
sentencias repetitivas y sentencias de salto.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1
www.udima.es 259
FUNDAMENTOS DE LA PROGRAMACIÓN
Enunciado 2
Enunciado 3
Enunciado 4
La sentencia break:
260 www.udima.es
Enunciado 5
www.udima.es 261
FUNDAMENTOS DE LA PROGRAMACIÓN
Solución 1
Solución 2
Solución 3
Solución 4
Solución 5
ACTIVIDADES DE REPASO
1. Escribir un fragmento de código que lea tres números enteros del teclado y
luego imprima el menor de ellos.
2. Reescribir el código anterior para que calcule el número menor de una
cantidad cualquiera de números enteros introducidos con el teclado por el
usuario. El final de la lista de números vendrá dado cuando el usuario intro-
duzca un número negativo.
262 www.udima.es
1
2 3
4 5 6
7 8 9 10
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
REFERENCIAS BIBLIOGRÁFICAS
Básica
www.udima.es 263
FUNDAMENTOS DE LA PROGRAMACIÓN
ISO C++. News, Status & Discussion about Standard C++. Disponible en <https://isocpp.org/>.
Lippman, S. B. y Lajoie, J. C++ Primer. Addison-Wesley, 2005.
Stroustrup, B. Welcome to Bjarne Stroustrup's homepage! Disponible en <http://www.stroustrup.com/>.
Avanzada
264 www.udima.es
8
UNIDAD
DIDÁCTICA
FUNCIONES
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Objetivos de la unidad
1. Introducción
2. Funciones en C++
2.1. Declaración de funciones
2.2. Definición de funciones
2.3. Funciones de librería
2.4. Funciones en línea
3. Parámetros
3.1. Parámetros formales
3.2. Parámetros actuales
3.3. Paso de parámetros por valor
3.4. Paso de parámetros por referencia
3.5. Paso por dirección
3.6. Parámetros por omisión
4. Alcance y visibilidad
4.1. Definición de alcance
4.2. Variables locales
4.3. Variables globales
4.3.1. Variables globales del fichero
4.3.2. Variables globales del programa
www.udima.es 265
FUNDAMENTOS DE LA PROGRAMACIÓN
5. Recursividad
6. Sobrecarga de funciones
Conceptos básicos
Actividades de autocomprobación
Actividades de repaso
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Referencias bibliográficas
266 www.udima.es
OBJETIVOS DE LA UNIDAD
Para utilizar las técnicas de programación es necesario conocer y dominar todas las
características del lenguaje de programación que se vaya a usar. Por ello, en esta unidad
didáctica se explica detenidamente el elemento esencial que permite crear programas
modulares: las funciones. En los lenguajes de programación, las funciones pueden imple-
mentar cualquier operación que se desee, desde tareas sencillas como realizar una opera-
ción matemática, hasta la implementación de un complejo algoritmo. Se estudiará cómo
implementar las funciones en el lenguaje C++ explicando todas sus características y su
forma adecuada de utilización.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
www.udima.es 267
FUNDAMENTOS DE LA PROGRAMACIÓN
1. INTRODUCCIÓN
Esta unidad didáctica va a presentar el elemento fundamental del lenguaje C++, que
permite construir programas: las funciones.
Función. Permite dividir el problema completo en partes más pequeñas y, por tanto,
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Cada función puede recibir unos datos de entrada y devolver un resultado, además
de realizar cualquier cálculo u operación que se desee haciendo uso del resto de ele-
mentos del lenguaje.
2. FUNCIONES EN C++
Tal como ocurría con las variables, para poder utilizar una función es imprescindible
haberla declarado previamente. En C++, esta declaración de una función también recibe
el nombre de «prototipo de la función». El prototipo de la función sirve para indicar al
compilador cuál será el nombre de la función, el tipo de los parámetros y el valor devuelto.
De esta manera, la sintaxis para declarar una función es:
268 www.udima.es
Esta función se denomina max; recibe dos parámetros enteros y devuelve un entero.
www.udima.es 269
FUNDAMENTOS DE LA PROGRAMACIÓN
El siguiente ejemplo muestra una sencilla función que calcula el máximo de dos
números enteros:
int max (int a, int b)
{
if (a > b)
return a;
return b;
}
En este ejemplo se puede observar que la función se denomina max, que recibe dos
parámetros de tipo entero llamados a y b, y que la función devolverá un valor de tipo
entero. El bloque de la función incluye una sentencia if que realiza la comparación de
los valores de los parámetros recibidos y, si el primero es mayor que el segundo, hará
que la función termine devolviendo el valor de a; en caso contrario, la ejecución pro-
sigue con la siguiente sentencia que devuelve el valor de b.
270 www.udima.es
Para utilizar esta función, simplemente hay que llamarla como se vio en la unidad
didáctica dedicada a las expresiones. Por ejemplo:
a= max (4, 5);
b= max (5.8, 3);
c= max (a, b);
d= max (max (a * 2, b/2), c * c);
En el lenguaje C++ todo son funciones. Esto incluye una función con un nombre
especial denominada main. Esta función es importante y debe existir en todo programa
en C++, puesto que es la función que se ejecutará en primer lugar cuando se invoque
el programa. Generalmente, esta función ni recibe parámetros ni devuelve nada, pero,
en realidad, el lenguaje admite que esta función pueda recibir parámetros y devolver
un valor. Si main devuelve un valor, dicho valor será enviado al sistema operativo para
que lo trate como considere oportuno. Si main tiene que recibir parámetros, los tendrá que
recibir de una manera especial.
SORT VALORES.DAT -r
Este programa SORT recibe un fichero para ordenar (VALORES.DAT) y una opción
de ordenado (-r).
void main (int argc, char *argv[])
{
/* código de la función principal */
}
www.udima.es 271
FUNDAMENTOS DE LA PROGRAMACIÓN
Los parámetros del programa, que son proporcionados por el sistema operativo, se
almacenan en forma de cadenas en el vector de punteros a caracteres argv (estos tipos
de datos se estudiarán en la unidad didáctica 9).
• argc: 3
• argv[0]: SORT.EXE
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
• argv[1]: VALORES.DAT
• argv[2]:
-r
Por tanto, se comenzó a crear una serie de funciones que desde el punto de vista del
programador tenían la misma forma (la misma definición) para realizar la entrada/salida.
Estas funciones las definía el creador de cada compilador para la máquina en que este debía
trabajar. Pronto se unieron a estas otras funciones para desarrollar toda una serie de trabajos
comunes (manejo de cadenas, cálculos matemáticos, etc.), hasta llegar a la situación de hoy
en día. En la actualidad, un compilador de C++ viene con cientos de funciones de librería.
Para acceder a estas funciones se utilizan los ficheros de cabecera (extensión .h)
mediante la directiva #include del preprocesador. En estos ficheros se encuentran
272 www.udima.es
las declaraciones necesarias para poder utilizar las funciones. Así, si se desea usar las
funciones de entrada/salida de C, se utiliza el fichero stdio.h, pero si se desea usar las funciones
de entrada/salida de C++, se utiliza el fichero iostream.h. Si se desea usar funciones mate-
máticas, se utiliza el fichero math.h. Y otras funciones muy útiles, como exit, están en
el fichero stdlib.h. Por ello, resulta necesario que el programador conozca los detalles de
su compilador y el conjunto de librerías y funciones que incluye.
C++ ha introducido un modificador para las funciones: las funciones en línea. Para
ello, se usa la palabra reservada inline, que se coloca antes del tipo de retorno de
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
la función, y que constituye una solicitud al compilador para que expanda el código de la
función en el lugar donde es llamada. Las principales características que cumplen estas
funciones son:
inline [tipo] nombre_función ([parámetros]);
inline int max (int a, int b) // Máximo de dos enteros
{
return a > b? a: b;
}
Al escribir una función con un cuerpo muy conciso y que se va a utilizar en bas-
tantes ocasiones, el programador puede estimar que el tiempo de llamada y retorno de
www.udima.es 273
FUNDAMENTOS DE LA PROGRAMACIÓN
la función puede resultar algo elevado. En este caso, puede intentar optimizar el tiempo
de ejecución solicitando al compilador que la convierta en inline.
Una función ideal, candidata a ser convertida a inline, es aquella que realiza alguna
operación realmente simple, como devolver un valor, llamar a otra función o modificar
un valor; es decir, aquella que realiza alguna operación con una o dos sentencias simples.
3. PARÁMETROS
En este epígrafe se estudiará la diferencia que existe entre los parámetros formales
y los parámetros actuales. Este concepto es muy sencillo, pero conviene prestarle aten-
ción, sobre todo en lo concerniente a la correcta correspondencia de tipos entre los pará-
metros formales y los parámetros actuales que, junto con el uso indebido de punteros,
representan una gran parte de los errores cometidos en un programa. Además, también
se verán las distintas formas de pasar parámetros a un programa: paso por valor, paso
por referencia y paso por dirección.
274 www.udima.es
int max (int a, int b)
{
if (a > b)
return a;
return b;
}
x= max (5, 9);
y= max (x, i + j);
Estas sentencias llaman a max con distintos parámetros. En el primer caso, los pará-
metros son 5 y 9; en el segundo, son x e i + j. Por tanto, estos son parámetros actuales,
porque son los parámetros presentes en cada una de las llamadas.
Los parámetros actuales son aquellas expresiones de las que toman sus valores los
parámetros formales del procedimiento. Una vez invocada la función max en la primera
sentencia, el parámetro formal a de la misma pasa a tomar el valor 5 y el parámetro b
pasa a tomar el valor 9 (correspondientes a los parámetros actuales). En cambio, en la
segunda invocación de la función max, el parámetro formal a toma el valor de la variable x
y el parámetro b toma el valor de la expresión i + j.
www.udima.es 275
FUNDAMENTOS DE LA PROGRAMACIÓN
Es importante hacer notar que en el lenguaje C++ se exige que los tipos de los pará-
metros actuales coincidan en número y tipo con los parámetros formales. No obstante,
existen excepciones a esta norma. En primer lugar, como se verá en el epígrafe 3.6, una
función puede definir que ciertos parámetros sean opcionales. En segundo lugar, la coin-
cidencia de tipos se limita a que los tipos sean compatibles, teniendo en cuenta las reglas
de conversión automática de tipos que se explicaron en la unidad didáctica 6. De esta
forma, también sería válida la llamada:
i= max (x, 5.3); /* el real se convertirá a entero y el parámetro
formal b recibirá un 5 */
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
a= max (1, 2, 3); // demasiados parámetros actuales
b= max ("hola", 9); // primer parámetro actual no compatible
void swap (int x, int y)
{
int t;
t= x;
x= y;
y= t;
}
276 www.udima.es
int a= 3, b= 7;
swap (a, b);
cout << a << b; // imprime 3 y 7
Hay ocasiones en que cuando se invoca a una función, el programador necesita que
los cambios realizados en los parámetros formales se vean reflejados en los parámetros
actuales. Una forma de pasar parámetros a las funciones, de tal manera que se pueda
modificar el valor de los parámetros actuales desde la propia función, se denomina «paso
de parámetros por referencia».
La idea consiste en que en lugar de pasar el valor del parámetro actual, se pasa su
dirección. Dentro de la función se maneja realmente la dirección del parámetro actual,
por lo que cualquier modificación del parámetro formal supondrá modificar el valor
almacenado en dicha dirección pasada y, por tanto, se estará modificando también el
valor del parámetro formal. Es decir, tanto el valor del parámetro formal como el actual
se encuentran almacenados en la misma dirección de memoria.
Si la función del epígrafe anterior se modifica para indicar que sus parámetros son
por referencia (lo cual se indica en C++ mediante el signo &), la función quedaría así:
void swap (int &x, int &y)
{
int t;
t= x;
x= y;
y= t;
}
www.udima.es 277
FUNDAMENTOS DE LA PROGRAMACIÓN
int a= 3, b= 7;
swap (a, b);
cout << a << b; // imprime 7 y 3
lógica, etc.) como parámetros por referencia a una función; solamente se pueden enviar
identificadores o expresiones de los que se puede obtener una dirección (por ejemplo,
un elemento de un vector, un puntero, etc.).
En C++ también se pueden pasar punteros por valor, pero haciéndolo se puede simular
un paso por referencia. De esta manera, los programadores en C simulaban este modo de
funcionamiento, ya que C solamente tenía el paso de parámetros por valor. Este modo
de envío de parámetros se denomina «paso por dirección» porque se envía a la función
la dirección del parámetro actual.
Para conseguir este efecto, a una función se le debe pasar un «puntero al parámetro
actual» en lugar del parámetro en sí. Esto supone que el parámetro formal debe decla-
rarse de tipo puntero y que en el cuerpo de la función debe utilizarse el operador * de
acceso al contenido de un puntero. De esta forma, la función swap de los epígrafes ante-
riores quedaría:
void swap (int *x, int *y)
{
int t;
t= *x;
*x= *y;
*y= t;
}
278 www.udima.es
La llamada a esta función sería ahora diferente, ya que hay que enviar explícitamente
la dirección del parámetro actual mediante el operador & de dirección:
int a= 3, b= 7;
swap (&a, &b);
cout << a << b; // imprime 7 y 3
Una utilidad adicional para utilizar punteros como parámetros estriba en emplearlos
cuando el tamaño del parámetro tiene un tamaño grande. Si, por ejemplo, se está pasando
un tipo avanzado de datos (que se verán en la unidad didáctica 9) que ocupa varios cientos
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
de bytes, el proceso de copiar todos esos bytes del parámetro actual al parámetro formal
puede consumir un tiempo elevado, ralentizándose, por tanto, el proceso de llamada a la
función. En cambio, utilizando un puntero a ese dato, solamente habría que copiar unos
pocos bytes (normalmente menos de 10, dependiendo de la arquitectura de la máquina
y del tamaño de las direcciones). Se puede comprender que el ahorro es considerable.
El problema estriba en que el programador, al ver que una función recibe un pun-
tero, puede pensar que se va a modificar su valor. Para evitar esta incorrecta interpreta-
ción o los errores del programador de la función, se puede indicar que el parámetro no
se podrá modificar mediante la palabra const de la siguiente forma:
void funcion (const double *par);
El paso de parámetros por referencia también puede usarse para evitar pasar grandes
cantidades de datos a una función.
C++ permite definir valores iniciales para algunos de los parámetros formales de
una función. Los últimos argumentos de las funciones pueden recibir valores predefi-
www.udima.es 279
FUNDAMENTOS DE LA PROGRAMACIÓN
int aleat (int i= 0, int j= 100); // Dos valores por omisión
Esto significa que la función puede llamarse con dos, uno o ningún parámetro actual:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
aleat (5, 10); // i == 5; j == 10
aleat (50); // i == 50; j == 100
aleat (); // i == 0; j == 100
void proceso (int a, float b= 0.0, char c= '\n');
Hay que recordar que solo pueden tener valores por omisión los últimos paráme-
tros, por lo que una función como la siguiente sería errónea:
void mal (float b= 0.0, char c= '\n', int a);
Por tanto, la llamada a proceso podría ser de una de las siguientes formas (obsér-
vese como el primer parámetro actual tiene que estar siempre presente por no ser por
omisión y cómo se pueden omitir los parámetros empezando por el final):
proceso (5, 5.5, '5'); // a == 5; b == 5.5; c == '5'
proceso (5, 5.5); // a == 5; b == 5.5; c == '\n'
proceso (5); // a == 5; b == 0.0; c == '\n'
280 www.udima.es
4. ALCANCE Y VISIBILIDAD
Alcance o visibilidad. Zona de código fuente (el «ámbito») donde puede utilizarse
una variable dada.
void funcion (int a) // inicio de la visibilidad de a
{
int b= 5; // inicio de la visibilidad de b
while (b > a)
{
int c; // inicio de la visibilidad de c
c= b-- * a - 2;
if (c > 0) cout << b;
} // fin de la visibilidad de c
float f; // inicio de la visibilidad de f
f= b * .5;
cout << f;
} // fin de la visibilidad de a, b y f
www.udima.es 281
FUNDAMENTOS DE LA PROGRAMACIÓN
De esta forma, ninguna de las variables declaradas en funcion puede ser utilizada
desde el exterior a dicha función.
Variable local. Toda variable declarada dentro de un bloque y que, por tanto, sola-
mente puede ser utilizada dentro de su bloque.
Dicho de otra forma, su alcance abarca únicamente al bloque donde ha sido declarada.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Lo más habitual es que una variable local sea declarada al comienzo de una función
para que, de esta manera, se pueda utilizar en el cuerpo de la función. Los parámetros
formales constituyen también una declaración de variable local, puesto que solo son visi-
bles desde la propia función. No obstante, también se puede declarar una variable local
a un bloque, tal como se vio en el ejemplo del epígrafe anterior (variable c).
void imprimeCubo (int z) // z: parámetro local de imprimeCubo
{
long i; // i: variable local de imprimeCubo
i= z * z * z;
cout << "El cubo de " << z << " es: " << i << endl;
} // fin del alcance de i, z
void main (void)
{
int num; // num: variable local de main
cin >> num;
for (int i= 1; i <= num; i++) // i: variable local del for
282 www.udima.es
{
if ((i % 2) == 0)
imprimeCubo (i);
} // fin del alcance de i
cout << "Fin";
} // fin del alcance de num
Debe observarse que, como cada función define un ámbito distinto e independiente,
se pueden definir en distintos ámbitos variables con el mismo nombre que serán varia-
bles distintas. En el ejemplo, se puede ver que existen dos variables llamadas i, que no
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
void main (void)
{
int i; // i: variable local de main
cin >> i;
for (int i= 1; i <= 50; i++) // i: variable local del for
{ // i "oculta" la i de main
if ((i % 2) == 0) // se usa la i del for
imprimeCubo (::i); // se usa la i de main
} // fin del alcance de i del for
cout << "Fin";
} // fin del alcance de i de main
Variable global. Toda variable declarada fuera de cualquier bloque y que, por tanto,
puede ser utilizada dentro de cualquier bloque.
www.udima.es 283
FUNDAMENTOS DE LA PROGRAMACIÓN
Dicho de otra forma, su alcance abarca todos los bloques que se encuentren poste-
riormente a su declaración.
No obstante, en el lenguaje C++ existen dos tipos de variables globales cuya filo-
sofía de visibilidad es igual, pero que se diferencian en el alcance.
Aunque en ocasiones puede parecer más intuitivo o cómodo emplear una variable
global, por cuestiones de estilo, legibilidad y facilidad de mantenimiento se recomienda
no usar las variables globales (salvo en casos muy concretos).
Las variables globales del fichero se caracterizan por que su visibilidad alcanza úni-
camente al fichero donde están declaradas. Es decir, todas las funciones definidas en el
fichero tras la variable global podrán utilizarla.
float pi= 3.1416; // pi: variable global
float area (float radio) //radio: variable local a area
{
return 2 * pi * radio * radio;
}
float perimetro (float radio) //radio: variable local a perimetro
{
return 2 * pi * radio;
}
void main (void)
{
float radio; //radio: variable local a main
cin >> radio;
cout << "Área: " << area (radio) << endl;
cout << "Perímetro: " << perimetro (radio) << endl;
cout << "PI: " << pi << endl;
}
// fin de la visibilidad de pi
En el ejemplo puede verse como la variable pi, que está declarada fuera de las
funciones, es global y, por tanto, se puede utilizar por cualquiera de las tres funciones.
284 www.udima.es
Las variables globales del programa se caracterizan por que su visibilidad alcanza a
varios ficheros. Es decir, las funciones definidas en varios ficheros del programa podrán
utilizarla.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Para poder conseguir esto, la variable global debe ser declarada en un solo fichero.
En el resto de ficheros que se quiera utilizar, simplemente hay que indicar que se va a
utilizar una variable de otro fichero, es decir, una variable externa. Esto se consigue uti-
lizando la palabra reservada extern de la siguiente forma:
extern tipo variable;
El siguiente ejemplo consta de dos ficheros. En uno de ellos se define una va-
riable global, mientras que en el otro se manifiesta que se va a utilizar dicha variable
global:
• Fichero círculo.c:
float pi= 3.1416; // pi: variable global
float area (float radio) //radio: variable local a area
{
return 2 * pi * radio * radio;
}
float perimetro (float radio) //radio: variable local a perimetro
{
return 2 * pi * radio;
}
www.udima.es 285
FUNDAMENTOS DE LA PROGRAMACIÓN
• Fichero principal.c:
extern float pi; // pi es una variable global de otro fichero
void main (void)
{
float radio; //radio: variable local a main
cin >> radio;
cout << "Área: " << area (radio) << endl;
cout << "Perímetro: " << perimetro (radio) << endl;
cout << "PI: " << pi << endl;
}
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Se ha visto en el epígrafe anterior como una variable global puede ser global al fichero
o global al programa (usando la palabra extern). Esta palabra, por tanto, posibilita que
desde un fichero se utilice una variable de otro fichero.
En ocasiones puede ocurrir que no interese que una variable global de un fichero
se pueda utilizar desde otro (por ejemplo, porque almacena algún dato privado interno
que ningún otro módulo debería manejar). Para conseguir esta protección de las varia-
bles globales se utiliza la palabra reservada static colocada antes de la declaración de
la variable global:
static tipo variable;
286 www.udima.es
static float pi= 3.1416;
Si una variable local se declara como estática, sigue siendo local, pero su valor
se mantiene entre las sucesivas llamadas a su función. Es decir, las variables estáticas
solamente se inicializan una vez y nunca pierden su valor (aunque la función no esté
en ejecución). La sintaxis para declarar una variable estática utiliza la palabra reser-
vada static:
static tipo variable;
Un ejemplo del funcionamiento del modo estático podría ser una variable que acu-
mula el número de llamadas que se realizan a una función:
int llamada (void)
{
static int llamadas= 0; // Solo se inicializa la 1ª vez
return (++llamadas);
}
Lo que hace esta función es contar cuántas veces se la llama, de tal manera que la
primera vez que se la llame devolverá un 1 (se habrá inicializado a 0); la segunda, devol-
verá un 2; la tercera, un 3, y así sucesivamente. Si la variable llamadas no hubiera sido
estática, la función siempre devolvería un 1.
www.udima.es 287
FUNDAMENTOS DE LA PROGRAMACIÓN
Los modos se diferencian por la duración (tiempo durante el cual puede utilizarse
una variable), por el alcance (qué parte del programa puede emplearlos) y por el lugar
de definición (dentro o fuera de las funciones). El cuadro siguiente muestra un resumen de
todos los modos de almacenamiento:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Modo de
Palabra clave Duración Alcance Lugar de definición
almacenamiento
En este epígrafe se han estudiado casi todos los modos de almacenamiento mos-
trados en el cuadro. Simplemente quedan por explicar dos de ellos:
288 www.udima.es
void main (void)
{
float j= 0; // variable local automática
auto float i; // variable local automática
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
register int x; // variable local registro
for (i= 1; i < 1e9; i += 0.1)
{
x= int (((j/i) < 32767) ? j/i : -3e5);
j += x * x + i + x * (x - 1)/(x + 2);
}
}
5. RECURSIVIDAD
Si una función recursiva carece del caso base, no habrá forma de abandonar la eje-
cución y, por tanto, se tendrá una función recursiva infinita que jamás terminará (blo-
queándose, por tanto, el programa).
www.udima.es 289
FUNDAMENTOS DE LA PROGRAMACIÓN
int factorial (int n)
{
if (n == 0)
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
return 1; // caso base: salida de la recursividad
else
return n * factorial (n - 1); // llamada recursiva
}
Analizando el ejemplo de la función factorial, se dirá que el caso base está situado
en la parte then de la sentencia if, mientras que el paso recursivo se encuentra en la parte
else.
290 www.udima.es
int factorial (int n)
{
int contador, acumulador;
for (acumulador= contador= 1; contador <= n; contador++)
acumulador *= contador;
return acumulador;
}
Para terminar, hay que indicar que, dada cualquier función recursiva o su equiva-
lente secuencial, deben tomarse ciertas precauciones mínimas respecto a su implementa-
ción. En el caso de las funciones factoriales vistas, ¿qué ocurriría si se las invocara con
un número negativo (por ejemplo, factorial (-3))?
Por ello, la precaución mínima que se debe tomar es que, dado cualquier parámetro,
siempre hay que prever todos los posibles valores y comprobar que siempre se alcance
un caso base o una condición de finalización.
www.udima.es 291
FUNDAMENTOS DE LA PROGRAMACIÓN
int factorial (int n)
{
if (n < 0)
return -1; // caso base: salida con error
if (n == 0)
return 1; // caso base: salida de la recursividad
else
return n * factorial (n - 1); // llamada recursiva
}
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
6. SOBRECARGA DE FUNCIONES
En C++ se permite sobrecargar las funciones, es decir, definir varias funciones con
el mismo nombre y distintos parámetros y con una implementación distinta. A la hora
de ejecutarlas, las funciones sobrecargadas se diferencian entre sí por el tipo de los argu-
mentos o por su número.
El siguiente ejemplo muestra tres funciones print sobrecargadas. Una, recibe un entero
e imprime un mensaje diciendo que se imprime un entero, junto con el valor del
entero, y después imprime un salto de línea. Otra, recibe un real e imprime un mensaje
diciendo que se imprime un real, junto con el valor del real, y después imprime un salto
de línea. La última recibe dos enteros y los imprime juntos, separados por un punto, y
no imprime un salto de línea:
// Prototipos:
void print (int);
292 www.udima.es
void print (float);
void print (int, int);
// Definiciones:
void print (int e) // imprime un entero
{
cout << "El entero vale: " << e << endl;
}
void print (float f) // imprime un real
{
cout << "El real vale: " << f << endl;
}
void print (int ent, int dec)
{ // imprime dos enteros y los separa con un punto
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
cout << ent << "." << dec;
}
// Llamadas de ejemplo:
print (12); // llama a print (int)
print (20, 5); // llama a print (int, int)
print (3.14); // llama a print (float)
www.udima.es 293
FUNDAMENTOS DE LA PROGRAMACIÓN
CONCEPTOS BÁSICOS
• El lenguaje C++ implementa el concepto de modularidad mediante las fun-
ciones, por lo que es fundamental saber declarar y definir adecuadamente
una función.
• Las funciones permiten comunicarse con otras funciones a través del envío
de parámetros, por lo que se debe saber diferenciar las distintas formas de
enviar información a una función: por valor, por referencia o por dirección.
• Los identificadores se pueden declarar en distintos puntos del programa y,
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1
a) Por valor.
b) Por valor y por referencia.
294 www.udima.es
Enunciado 2
Enunciado 3
Enunciado 4
www.udima.es 295
FUNDAMENTOS DE LA PROGRAMACIÓN
Enunciado 5
a) int main (void);
b) void main (int);
c) int main (int, char *);
d) void main (int, char []);
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
296 www.udima.es
Solución 1
Solución 2
Solución 3
Solución 4
c) Una posibilidad que permite definir distintas funciones con el mismo nombre
pero distintos parámetros.
Solución 5
a) int main (void);
ACTIVIDADES DE REPASO
1. Escribir una función que imprima el producto de su parámetro actual por el
parámetro que se le pasó en la llamada anterior.
2. Escribir dos funciones que impriman los primeros n elementos de la serie
de Fibonacci. La primera función deberá ser recursiva y la segunda deberá
ser iterativa.
La serie de Fibonacci se define así:
Fibonacci (0) → 0
Fibonacci (1) → 1
Fibonacci (i) → Fibonacci (i – 1) + Fibonacci (i – 2) ∀i>1
www.udima.es 297
FUNDAMENTOS DE LA PROGRAMACIÓN
3. Escribir una función que reciba tres parámetros enteros y que los devuelva
elevados al cuadrado.
4. Escribir tres funciones sobrecargadas que permitan sumar sus tres paráme-
tros enteros, multiplicar sus tres parámetros reales o imprimir sus tres pará-
metros carácter.
5. Escribir un programa con una función que guarde en una variable global la
suma de los cinco números enteros recibidos como parámetros y con otra
función que imprima la proporción del valor de cada uno de esos cinco
números frente a la suma total. Los cinco números deberán ser leídos del
teclado por la función principal.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
REFERENCIAS BIBLIOGRÁFICAS
Básica
Avanzada
Deitel, H. M. y Deitel, P. J. C++ How to Program. 7.ª ed. Prentice Hall, 2009.
Fuertes, J. L. y González, Á. L. El lenguaje de programación C. Koobeth International, 2004.
Kernighan, B. W. y Ritchie, D. M. The C Programming language. 2.ª ed. Prentice Hall, 2004.
Liberty, J.; Rao, S. y Jones, B. L. Sams Teach Yourself C++ in One Hour a Day. Sams, 2008.
298 www.udima.es
9
UNIDAD
DIDÁCTICA
TIPOS AVANZADOS
DE DATOS
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Objetivos de la unidad
1. Introducción
2. Vectores y matrices
2.1. Vectores
2.2. Matrices
2.3. Representación interna de vectores y matrices
3. Punteros
3.1. Declaración de punteros
3.2. Operador puntero y dirección
3.3. Asignación y liberación de memoria dinámica
3.4. Aritmética de punteros
3.5. Punteros y vectores
4. Cadenas
4.1. Declaración de cadenas de caracteres
4.2. Inicialización
4.3. Uso de cadenas de caracteres
5. Estructuras y uniones
5.1. Concepto de estructura
www.udima.es 299
FUNDAMENTOS DE LA PROGRAMACIÓN
6. Definiciones de tipos
7. Tipos enumerados
7.1. Concepto de tipo enumerado
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Conceptos básicos
Actividades de autocomprobación
Actividades de repaso
Referencias bibliográficas
300 www.udima.es
OBJETIVOS DE LA UNIDAD
Para utilizar las técnicas de programación es necesario conocer y dominar todas
las características del lenguaje de programación que se vaya a usar, incluso las más
avanzadas. Por ello, en esta unidad didáctica se explican con detenimiento los tipos avan-
zados de datos que se encuentran disponibles en C++. Estos datos incluyen vectores y
matrices, punteros, estructuras, uniones, etc., y permiten crear tipos estructurados de
datos necesarios para programas con una cierta complejidad.
www.udima.es 301
FUNDAMENTOS DE LA PROGRAMACIÓN
1. INTRODUCCIÓN
En esta unidad didáctica se verán los tipos de datos avanzados que ofrece el lenguaje
C++: vectores, matrices, punteros, cadenas de caracteres, estructuras, uniones y tipos enu-
merados y se explicará qué significan y cómo se trabaja con ellos.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
2. VECTORES Y MATRICES
Vector. Secuencia de valores del mismo tipo, de tal manera que se puede acceder
directamente a cada uno de sus elementos indicando su posición (o índice) dentro
del vector.
2.1. VECTORES
Para declarar un vector en C++ hay que escribir el tipo de los elementos, seguido
por el nombre del vector y por el tamaño o dimensión (dim) del vector (es decir, el número
de elementos) encerrado entre corchetes. Por tanto, su sintaxis es:
tipo nombre [dim];
302 www.udima.es
Los vectores pueden ser de cualquier tipo básico de los vistos en la unidad didáctica 6
(enteros, reales, caracteres, etc.) y de los tipos avanzados que se verán en esta unidad didác-
tica (estructuras, uniones, enumerados, etc.). A continuación se muestran algunos ejemplos:
La dimensión del vector debe ser siempre una constante entera o una expresión
constante, es decir, una expresión cuyo valor se conozca a priori (por ejemplo, 10 + 10);
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Al igual que ocurre con los tipos básicos, los vectores pueden inicializarse con un
valor inicial constante en la declaración. Para hacerlo, tras un signo de igual, se escriben
entre llaves los valores iniciales de los elementos que forman el vector, separándolos
por comas. Por ejemplo:
int x[5]= {1, 2, 4, 8, 16};
float z[4]= {0.3, 9.0};
short int mal[3]= {0, 1, 2, 3}; // Error
www.udima.es 303
FUNDAMENTOS DE LA PROGRAMACIÓN
char respuestas[]= // respuestas es un vector de 10 elementos
{'b', 'a', 'c', 'c', 'a', 'b', 'c', 'c', 'a', 'b'};
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
En C++, el rango de los índices de un vector va siempre desde cero hasta la dimen-
sión del vector, menos uno. Por ejemplo, seguidamente se muestra la inicialización de
un vector y se indica cómo acceder a cada uno de sus elementos y el valor que tendrá:
char v[5]= {'a', 'e', 'i', 'o', 'u'};
v[0] == 'a'
v[1] == 'e'
v[2] == 'i'
v[3] == 'o'
v[4] == 'u'
El acceso a los elementos de un vector sirve tanto para obtener su valor como para
modificarlo. Por ejemplo, el siguiente fragmento de código tiene tres bucles: el primero,
rellena un vector entero, elemento a elemento, con los primeros 100 números naturales;
el segundo almacena en otro vector de enteros de gran precisión el cuadrado de esos
304 www.udima.es
primeros 100 números; en el último se recorre este vector para imprimir los elementos
situados en posición impar de ambos vectores:
int enteros[100], i;
long int grandes[100];
for (i= 0; i < 100; i++)
enteros[i]= i + 1;
for (i= 0; i < 100; i++)
grandes[i]= enteros[i] * enteros[i];
for (i= 1; i < 100; i += 2)
cout << enteros[i] << "->" << grandes[i] << endl;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Hay que destacar que con un elemento de un vector se pueden realizar las mismas
operaciones que con una variable del mismo tipo que el elemento. Es decir, si se tiene un
vector de enteros, cualquier elemento se puede utilizar como si fuera una variable entera.
2.2. MATRICES
Matriz. Similar a un vector, pero con más dimensiones. Esto significa que para
acceder a un elemento de una matriz son necesarios varios índices.
En C++ pueden definirse matrices con cualquier número de dimensiones. Las más
utilizadas, en general, son las bidimensionales (con dos índices). Por ejemplo, sea la
siguiente matriz bidimensional de números enteros:
0 0 0
1 0 1
0 1 1
1 1 0
Para acceder a los elementos de esta matriz se necesitarán dos índices (fila y columna).
Así, el elemento de la cuarta fila y tercera columna vale cero.
www.udima.es 305
FUNDAMENTOS DE LA PROGRAMACIÓN
de cada una de las dimensiones. En general, las matrices se declaran como sigue:
tipo matriz[dim1]...[dimn];
Igual que ocurre con el caso de los vectores, las dimensiones de las matrices se espe-
cifican con constantes o expresiones constantes. Por ejemplo, la siguiente línea declara
una matriz de dos por tres caracteres (es decir, la variable m es un vector de dos elementos,
que a su vez son vectores de tres elementos de tipo carácter):
char m[2][3];
De la misma forma que con los vectores, la operación básica que puede hacerse con
matrices es el acceso a uno de sus elementos, indicando el índice correspondiente para
cada una de sus dimensiones. Cada índice irá encerrado en un par de corchetes. Cada
índice podrá valer entre cero y el tamaño de la dimensión correspondiente, menos uno.
Igual que en el caso de los vectores, el lenguaje C++ no se preocupa de comprobar si los
índices son válidos. Es problema del programador asegurarse de que el programa nunca
se saldrá de los índices válidos.
306 www.udima.es
Las matrices se pueden inicializar de forma parecida a los vectores, poniendo entre
llaves la lista con los valores iniciales de cada elemento de la matriz. Estos elementos
se van metiendo en la matriz siguiendo el orden de las dimensiones declaradas. En el
caso de las matrices bidimensionales, se dice que se rellenan «por filas». Por ejemplo,
el código que aparece a continuación declara e inicializa una matriz bidimensional entera
de tres filas y cuatro columnas:
int mat[3][4]= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
tantos elementos como columnas hagan falta. Así, en el ejemplo anterior, se ha decla-
rado la siguiente matriz:
1 2 3 4
5 6 7 8
9 10 11 12
int mat[3][4]= {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
int mat1[3][4]= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
int mat2[3][4]= {{1, 2, 3, 4}, {5, 6}, {9, 10, 11, 12}};
int mat3[3][4]= {{1, 2, 3, 4}, {5, 6, 7, 8}};
www.udima.es 307
FUNDAMENTOS DE LA PROGRAMACIÓN
1 2 3 4 1 2 3 4 1 2 3 4
5 6 7 8 5 6 5 6 7 8
9 10 11 9 10 11 12
Cuando las matrices son de tres o más dimensiones, resulta más recomendable usar
las llaves para separar los elementos y así saber dónde se coloca cada uno.
Para terminar con la inicialización de matrices hay que indicar que, al igual que
ocurría con los vectores, cuando se inicializa una matriz se puede omitir el tamaño de la
primera dimensión, pero no los tamaños de las restantes.
Por ejemplo, la siguiente declaración es válida y define una matriz de dos filas y
tres columnas:
char respuestas[][3]= {{'b', 'a', 'c'}, {'c', 'a', 'b'}};
int x[][3]= {{0, 0}, {1, 0}, {0, 1}, {1, 1}};
for (int i= 0; i < 4; i++)
x[i][2]= x[i][0] ^ x[i][1];
308 www.udima.es
0 0
1 0
0 1
1 1
El bucle for completa la última columna y la deja tal como refleja la figura del
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Para terminar la parte dedicada a los vectores y las matrices se va a estudiar cómo se
representan internamente en memoria estos datos. Es muy importante conocerlo, dado que
C++ es un lenguaje de relativo bajo nivel y muchas veces va a ser necesario saber exacta-
mente cómo se ha representado algo en memoria. Los vectores se almacenan de forma que
todos los elementos ocupen posiciones consecutivas de memoria, empezando por el primer
elemento (aquel cuyo índice es cero). El espacio de memoria ocupado por un vector será el
resultado de multiplicar el tamaño del vector por el tamaño de cada uno de sus elementos.
3. PUNTEROS
Para explicar el concepto de puntero primero hay que recordar que en lenguaje C++
una variable es una zona de memoria a la que se accede utilizando su nombre. El tamaño
de esa zona de memoria será el número de bytes de memoria que ocupe el tipo de datos de
la variable y su posición habrá sido definida por el compilador. La relación entre el
www.udima.es 309
FUNDAMENTOS DE LA PROGRAMACIÓN
100
101 Nombre Dir Tam
102
103 Numero 103 4
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
104
105
106
107
100
101 Nombre Dir Tam
102
103 Numero 103 4
104
5
105
106
107
310 www.udima.es
Puntero. Variable cuyo valor es la dirección de una zona de memoria, es decir, una
posición dentro de la memoria disponible. Muchas veces, un puntero suele representar
la dirección de una variable; en ese caso, se dice que el puntero apunta a la variable.
int *Puntero; /* Declara un puntero a un número entero */
float *pf; // puntero a reales
long int *pl; // puntero a enteros grandes
short **pps; // puntero a punteros a enteros pequeños
char (*pc)[10]; // puntero a vectores de 10 caracteres
Como ya se ha dicho, un puntero es una variable cuyo valor es una dirección de una
zona de memoria. Los punteros son otro tipo de datos y, como tal, necesitan memoria
para almacenar la información asociada. El tamaño de un puntero depende de la máquina
y de cómo se organice el espacio de direcciones de memoria.
tipo *ptr;
www.udima.es 311
FUNDAMENTOS DE LA PROGRAMACIÓN
donde ptr será el nombre de la variable que apunta al tipo indicado; ptr contiene una
dirección de memoria.
Supóngase que se precisan 4 bytes para albergar una dirección de memoria (se tra-
baja con direcciones de 32 bits). Así, tras realizar la anterior declaración, la memoria
queda modificada como se muestra en la siguiente figura. En este caso, la información
asociada a Puntero es indeterminada, ya que no se ha inicializado con ningún valor. Lo
siguiente que se ha de hacer para poder utilizar el puntero es asignarle un dato válido;
en este caso, una dirección de memoria de tipo entero.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
100
101 Nombre Dir Tam
102
103 Numero 103 4
104 Puntero 110 4
5
105
106
107
108
109
110
111
112
113
114
312 www.udima.es
100
101 Nombre Dir Tam
102
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
C++ proporciona otro operador para acceder a la información referenciada por una
dirección de memoria, es decir, para realizar un acceso indirecto. Es el operador pun-
tero (*). Este operador toma el valor que tiene inmediatamente a su derecha como una
dirección de memoria. Con este valor va a dicha posición de memoria y accede al valor
que allí se encuentre.
www.udima.es 313
FUNDAMENTOS DE LA PROGRAMACIÓN
if (*Puntero == 5)
/*
da como resultado cierto, sin modificar el valor
almacenado en 103, puesto que Puntero apunta a un 5 */
*Puntero= Numero + 2;
/*
Hace que en la posición de memoria 103 se almacene el
valor 7 (resultado de sumar 5 + 2) */
/* Evidentemente, ahora Numero contiene un 7 */
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
100
101 Nombre Dir Tam
102
103 Numero 103 4
104 Puntero 110 4
7
105
106
107
108
109
110
111
103
112
113
114
Como último ejemplo resumen, las dos columnas siguientes son equivalentes entre
sí (en cuanto a que producen el mismo resultado):
float i, x, *ptr; float i, x;
ptr= &i; x= i;
x= *ptr;
314 www.udima.es
Hasta que se inicialice, un puntero hace referencia a una posición de memoria inde-
terminada. Por esta circunstancia no se puede utilizar su valor hasta que el puntero se
haya inicializado correctamente, y esto constituye un error muy frecuente de los progra-
madores en C++, puesto que los compiladores no suelen informar de esta circunstancia.
Ya se ha visto una de las formas de proceder para realizar esta inicialización: asignán-
dole la dirección de otro objeto.
new tipo
Esta expresión devuelve un puntero a una zona de memoria libre capaz de almacenar
un dato del tamaño indicado por el tipo. En caso de que no se pueda encontrar suficiente
memoria, el estándar de C++ indica que el operador new debe generar una excepción de
tipo std :: bad_alloc, que puede ser recogida mediante instrucciones avanzadas del
lenguaje para el manejo de excepciones.
Otra posibilidad (en compiladores más antiguos) es que new devuelva NULL cuando
no hay memoria.
Así, por ejemplo, partiendo del estado de la figura anterior, se va a proceder a eje-
cutar las siguientes sentencias:
int *Puntero2= new int;
*Puntero2= 3;
www.udima.es 315
FUNDAMENTOS DE LA PROGRAMACIÓN
99
100 Nombre Dir Tam
3
101
102 Numero 103 4
103 Puntero 110 4
104 Puntero 2 114 4
7
105
106
107
108
109
110
111
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
103
112
113
114
105
99
106
107
new tipo (expresión)
int *Puntero2= new int (3);
*Puntero= *Puntero2;
*Puntero2= 3 * 4;
316 www.udima.es
99
100 Nombre Dir Tam
12
101
102 Numero 103 4
103 Puntero 110 4
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Puntero= Puntero2;
Numero= *Puntero + 2;
lo que se ha hecho es cambiar la dirección a la que apunta Puntero. De esta forma, hay
dos punteros que hacen referencia a la información almacenada en 99. La segunda ope-
ración obtiene la información referenciada por Puntero (en este caso 12) y le suma 2.
El estado de la memoria tras esta operación es la mostrada seguidamente:
www.udima.es 317
FUNDAMENTOS DE LA PROGRAMACIÓN
99
100 Nombre Dir Tam
12
101
102 99 Numero 103 4
100
103 101 12
Puntero 110Nombre 4
Dir Tam
104 102 Puntero 2 114 4
14 103 Numero 103 4
105 104 Puntero 110 4
106 105 3 Puntero2 114 4
106
107 107
108 108
109 109
110
110 111
103
111 112
99 113
112
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
114
113 105
99
106
114 107
105
99
106
107
Siempre que se reserve memoria con new es preciso retornarla al sistema operativo
cuando esta deja de ser necesaria. Para ello, se utiliza el operador delete, cuya sintaxis
es la siguiente:
delete puntero;
318 www.udima.es
Puntero= NULL;
Puntero2= NULL;
99
100 Nombre Dir Tam
12
101
102 99 Numero 103 4
100
103 101 12
Puntero 110Nombre Dir
4 Tam
104 102 Puntero 2 114 4
14 103 Numero 103 4
105 104 Puntero 110 4
106 105 3 Puntero2 114 4
106
107 107
108 108
109 109
110
110 111
103
111 112
NULL 113
112 114
113 105
99
106
114 107
105
NULL
106
107
Con las sentencias vistas, se ha utilizado el operador new para pedir hueco para
almacenar un único dato de un determinado tipo. De esta manera, un puntero a entero
apunta a un número entero. No obstante, también se puede hacer que un puntero apunte a
varios elementos del mismo tipo, creando, por ejemplo, un puntero a un grupo de enteros
(que se almacenarán consecutivamente en memoria). Este modo de trabajar resulta bas-
tante habitual entre los programas en C++, por lo que es interesante saber cómo se hace
y cómo trabajar con ellos; dado que, además, permite dotar de una mayor potencia a los
algoritmos y programas.
www.udima.es 319
FUNDAMENTOS DE LA PROGRAMACIÓN
Si se quiere que un puntero apunte a varios elementos, hay que reservar espacio
suficiente para que quepan todos ellos usando la siguiente notación:
new tipo [tamaño]
De esta manera, para declarar un puntero a entero que apunte a 80 números, habría
que hacer:
int *q= new int [80];
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Las operaciones que se pueden realizar con el contenido de un puntero son las mismas
que con cualquier variable del mismo tipo. También está permitido asignar punteros,
compararlos y restarlos, aunque no es posible sumar dos punteros.
Si un puntero apunta a una zona de memoria capaz de almacenar varios datos con-
secutivos, entonces también se le puede sumar o restar valores enteros, entendiéndose
estos valores enteros como posiciones de memoria (no son bytes, sino posiciones de
memoria del tamaño del tipo del elemento). Por tanto, sumar un entero con valor 1 a un
puntero hará que este apunte al siguiente elemento:
int *ptri, *ptrj, y;
ptri= new int [2]; /* ptri apunta a 2 enteros */
*ptri= 3; /* se guarda un 3 en el entero 1º al que apunta */
*(ptri + 1)= 7; /* se guarda un 7 en el 2º entero al que apunta */
y= *ptri + 5; /* se almacena 8 en y */
if (ptri != ptrj)
ptrj= ptri + 1; /* ptrj apunta al segundo entero de ptri */
y= *ptrj; /* se almacena 7 en y */
delete ptri;
320 www.udima.es
float *ptri, *ptrj, y;
ptri= new float [200]; /* ptri apunta a 200 reales */
ptrj= ptri; // ptrj apunta al comienzo de la memoria
for (y= 0; y < 200; y++, ptrj++) //ptrj apuntará al siguiente real
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
*ptrj= 2.54 * y;
ptrj= ptri; // ptrj vuelve a apuntar al comienzo de la memoria
for (y= 0; y < 200; y++, ptrj++) //ptrj apuntará al siguiente real
cout << y << "\" = " << *ptrj << "cm." << endl;
delete ptri;
Los punteros y los vectores están muy relacionados entre sí. El nombre de un vector,
en realidad, es su dirección de comienzo en memoria y el contenido al que apunta esa
dirección es, por tanto, el primer elemento. Por tanto, &a[0] es lo mismo que a. Supón-
gase el siguiente grupo de sentencias:
int i, *ptra, a[100];
ptra= a; /* el puntero apunta al comienzo del vector */
www.udima.es 321
FUNDAMENTOS DE LA PROGRAMACIÓN
Los punteros y los vectores se diferencian en que un puntero es una variable, mien-
tras que el nombre de un vector es una constante. Por tanto:
char s[5]; char *t;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
t= "Hola"; /*
Solo está permitida si t no es un vector.
Lo que hace es asignar la dirección de memoria
de la cadena al puntero. */
s[0]= 'H';
s[1]= 'o';
s[2]= 'l';
s[3]= 'a';
s[4]= '\0'; /* Hay que poner el carácter nulo para terminar */
322 www.udima.es
char *p[DIM];
Resumiendo:
int var= 10; /* Suponemos que &var == 1000 */
int *punt; /* Suponemos que &punt == 2000 */
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
punt= &var;
Entonces, se tiene:
var == 10
&var == 1000
punt == 1000
&punt == 2000
*punt == 10
4. CADENAS
Se utilizan para representar información textual; por ejemplo, para almacenar mensajes
que se le van a dar al usuario o para representar una frase que haya introducido el usuario.
www.udima.es 323
FUNDAMENTOS DE LA PROGRAMACIÓN
char s[20];
char *s;
Existe una diferencia sutil entre ambas formas de declarar cadenas. Consiste en que,
como vector, hay que especificar el tamaño máximo de la cadena, mientras que, como
puntero, se podrá obtener la memoria necesaria en cada momento de forma dinámica
(con el operador new).
string s;
Este tipo de datos facilita el uso de las cadenas y elimina el engorro de manejar
vectores o punteros. No obstante, también se va a explicar aquí el manejo como vector o
como cadena, dado que a veces puede resultar necesario conocerlo. Para poder utilizar
el tipo string es necesario incluir el fichero de cabecera string.h.
4.2. INICIALIZACIÓN
Cuando se quiere dar un valor inicial a una cadena de caracteres, se suele poner
dicho valor encerrado entre comillas dobles. La notación cambia dependiendo de cómo
se haya declarado la cadena. Por ejemplo:
324 www.udima.es
char cadena[5]= "Hola";
char *cadena= "Hola";
string cadena ("Hola");
Es importante recordar que, cuando se representa una cadena con las comillas dobles,
el lenguaje C++ añade automáticamente el carácter '\0' al final de la cadena. También se
pueden inicializar las cadenas de la misma forma que los vectores, es decir, poniendo los
valores entre llaves. En este caso sí que habrá que poner explícitamente el carácter '\0'.
Por ejemplo, las siguientes declaraciones son también válidas y equivalentes a las anteriores:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
char cadena [5]= {'H', 'o', 'l', 'a', '\0',};
char cadena [ ]= {'H', 'o', 'l', 'a', '\0',};
El uso básico que permite hacer el lenguaje C++ de las cadenas es el mismo que
el de los vectores o los punteros: acceder a un elemento de la cadena, tanto para leerlo
como para modificarlo. Por ejemplo, continuando con el ejemplo del epígrafe anterior:
cadena[0]= 'h';
cout << cadena; // imprime "hola"
char *cadena= "Hola";
cadena= "Adiós"; /*
ahora cadena apunta a otra posición de memoria
donde está "Adiós" */
www.udima.es 325
FUNDAMENTOS DE LA PROGRAMACIÓN
char *cad1, *cad2;
cad1= new char [20]; /* se obtiene una dirección de memoria para
almacenar 20 caracteres */
cad1= "Lenguaje C++"; /* cad1 apunta a la dirección de la constante
y, por tanto, ya no apunta a la dirección
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
obtenida con el new */
cad2= new char [20]; /* se obtiene otra dirección de memoria
para almacenar 20 caracteres */
cad2= "Lenguaje C"; /* cad2 apunta a la dirección de la constante
y, por tanto, ya no apunta a la dirección
obtenida con el new */
cad1= cad2; /* cad1 ahora apunta a la misma dirección que cad2, es
decir, los dos punteros apuntan exactamente al
mismo sitio */
*cad1= 'l'; /* se modifica el primer carácter de la cadena apuntada */
cout << cad1 << cad2; /* imprime dos veces "lenguaje C" */
delete cad1; delete cad2; /*
Peligro: se está liberando una zona de
memoria no obtenida con new. Además,
como las dos variables apuntan al
mismo sitio, se está intentando liberar
dos veces la misma zona de memoria */
Por tanto, si se desea copiar una cadena en una variable cadena, conservando la
dirección obtenida para esta, deben copiarse los caracteres uno a uno. Esto se puede
realizar con una función que puede implementarse de alguna de las formas que se mues-
tran a continuación (se ha escrito de tres maneras distintas para mostrar el manejo de
variables de tipo cadena):
void copia (char s[], char t[]) /* versión 1ª: con vectores */
{
int i= 0;
s[i]= t[i];
326 www.udima.es
while (s[i] != '\0')
{
i++;
s[i]= t[i];
}
}
void copia (char *s, char *t) /* versión 2ª: con punteros */
{
*s= *t;
while (*s != '\0')
{
*s= *t;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
s++;
t++;
}
}
void copia (char *s, char *t) /* versión 3ª: con punteros */
{
*s++ = *t++;
while (*s != '\0')
*s++= *t++;
}
Pero, sin duda alguna, la mejor forma de copiar cadenas es utilizar la función de
librería denominada strcpy, que se encuentra definida en cstring.h, y que será explicada
en la unidad didáctica 10.
Si, en lugar de utilizar vectores o punteros, se empleara el tipo string, todo sería
mucho más fácil, puesto que para copiar cadenas simplemente habría que utilizar el ope-
rador de asignación, tal como se indica en el siguiente ejemplo:
www.udima.es 327
FUNDAMENTOS DE LA PROGRAMACIÓN
5. ESTRUCTURAS Y UNIONES
seis campos: dos cadenas de caracteres (el nombre y la dirección), un carácter (para el
sexo), un entero grande sin signo (para el número de DNI) y dos fechas (fecha de naci-
miento y fecha de expedición del DNI). Además, como no existe un tipo de datos fecha en
C++, habría que construirlo, y ello se puede realizar con otra estructura con tres campos
enteros para el día, el mes y el año.
struct [nombre]
{
tipo1 campo_1;
tipo2 campo_2;
...
tipon campo_n;
} [variable];
El nombre es un identificador que representa el nombre del tipo de datos que se está
creando. Entre llaves se declaran los campos (con la misma notación que se usa para
declarar cualquier variable). Finalmente, se puede declarar una variable del tipo estruc-
tura que se acaba de definir. Con esta declaración, se obtiene un nuevo tipo de datos, al
que se puede referir como struct nombre o, simplemente, nombre. Por tanto, se podrán
declarar variables utilizando este tipo.
328 www.udima.es
Por ejemplo, si se desea declarar una estructura para representar las fechas, se podría
hacer de la siguiente forma:
struct Fecha
{
int d, m, a;
};
Los campos de una estructura pueden ser de cualquier tipo válido en C++: números,
caracteres, vectores, matrices, punteros, estructuras, etc. El siguiente ejemplo muestra
cómo declarar una estructura para representar los datos de una persona:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
struct DNI
{
char nombre[50], direccion[50], sexo;
unsigned long int numero;
struct Fecha fecha_nac
Fecha fecha_exp; // no es necesario poner la palabra struct
};
También se permite declarar estructuras anónimas (es decir, sin darle un nombre a
ese tipo). Esto tiene la desventaja de que posteriormente no se podrán declarar más varia-
bles de este tipo. Por ejemplo, se puede declarar una variable que sea una estructura que
tenga las dimensiones de un rectángulo:
struct {int ancho, alto;} rectangulo;
www.udima.es 329
FUNDAMENTOS DE LA PROGRAMACIÓN
definir una variable de tipo fecha que represente el día 11 de febrero de 1966 habrá que
escribir el siguiente código:
Fecha f= {11, 2, 1966};
En el caso de que uno de los campos sea un vector, una matriz, otra estructura o
cualquier otro tipo complejo, para inicializarlo se usan llaves adicionales (aunque estas
pueden suprimirse, es conveniente ponerlas para reducir la posibilidad de cometer errores
y ambigüedades). Por ejemplo, para inicializar los datos de una persona, se puede escribir:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
DNI yo {{'P', 'e', 'p', 'e', '\0'}, "c/ del suspiro, 13", 'H', 17549785,
{11, 2, 1966}, {15, 10, 2009}};
variable.campo
cout << yo.nombre;
yo.numero= 4422188;
330 www.udima.es
Esto es aplicable independientemente del tipo de cada campo. Así, si uno de los
campos es un vector, se podrá acceder a cada uno de sus elementos usando la notación
propia de vectores. Por ejemplo:
cout << "Mi inicial es: " << yo.nombre[0];
Por último, hay que tener en cuenta que los campos también pueden ser de tipo
estructura, como se ha visto en el ejemplo. En ese caso, el operador . también se puede
aplicar al campo correspondiente. En ese caso, se puede acceder al año de nacimiento
de una persona de la siguiente forma:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
cout << yo.nombre << " tiene " <<
2009 - yo.fecha_nac.a << " años";
DNI *persona, alumnos;
persona= &yo;
alumnos= new DNI [200];
/* puntero a los datos de 200 alumnos */
cout << (*persona).nombre;
www.udima.es 331
FUNDAMENTOS DE LA PROGRAMACIÓN
rador se representa con un guion seguido del signo mayor: -> (simula una especie de
flecha). Usando este operador, para realizar el acceso anterior, bastaría con escribir
lo siguiente:
cout << persona->nombre;
Por supuesto, el operador -> se puede combinar con el operador . si uno de los
campos es de tipo estructura, o con los operadores corchete si un campo es un vector,
etc. O incluso, mezclarlos con el nombre de la variable. Por ejemplo, para acceder al
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
año de la fecha de nacimiento de la persona, para copiarlo en los datos del décimo
alumno sería:
alumnos[9]->fecha_nac.a= persona->fecha_nac.a
Al declarar los campos de una estructura, el lenguaje C++ ofrece una posibilidad
interesante si se necesita realizar una programación a bajo nivel: se puede definir el
tamaño en bits de cada uno de los campos. Esto se suele usar, en general, simplemente
para ahorrar memoria, por lo que solamente se utilizará en situaciones muy concretas.
Para indicar que un campo de una estructura ocupa un número determinado de bits,
se indica con la siguiente notación:
tipo campo: nº de bits;
El tipo de los campos puede ser uno de los siguientes: bool, char, unsigned char,
short, unsigned short, long, unsigned long, int o unsigned int.
332 www.udima.es
almacenar un día del mes (es decir, con un valor entre 1 y 31), para ahorrar memoria, se
podrían agrupar todas ellas en una sola estructura de la forma siguiente:
struct Campos
{
unsigned numero: 2; // Con dos bits es suficiente
unsigned flag1: 1;
unsigned flag2: 1;
unsigned flag3: 1;
unsigned flag4: 1;
unsigned flag5: 1;
unsigned dia: 5; // Con cinco bits es suficiente
};
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
El acceso a cada uno de los campos se realiza exactamente igual que si fueran
campos normales de una estructura. Por ejemplo, para asignar un 22 al dia si el flag3
vale 1, habría que escribir lo siguiente:
Campos var;
if (var.flag3 == 1)
var.dia= 22;
Una limitación que tienen los campos de bits es que no se puede obtener su direc-
ción. Por ejemplo, el siguiente código sería erróneo: &var.numero.
www.udima.es 333
FUNDAMENTOS DE LA PROGRAMACIÓN
union [nombre]
{
tipo1 campo_1;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
tipo2 campo_2;
...
tipon campo_n;
} [variable];
Por ejemplo, se puede declarar una unión que tenga tres campos, un entero, un
número real y un puntero a caracteres. Esta unión se podría declarar de la siguiente forma:
union Almacen
{
double r;
int i;
char *s;
};
Los campos de las uniones pueden ser de cualquier tipo presente en el lenguaje:
enteros, reales, vectores, matrices, punteros, estructuras, otras uniones, etc. Y como se
ha visto en el ejemplo anterior, los campos de una misma unión pueden ser de tipos dis-
tintos. En ese caso, el espacio de memoria que ocupa la unión es el espacio necesario para
almacenar el campo más grande. Así, la unión del ejemplo anterior ocuparía el espacio
de un número real (que normalmente será más grande que un entero y un puntero).
334 www.udima.es
nombre. Por ejemplo, para declarar una variable de la unión anterior bastaría con escribir
una de las siguientes declaraciones:
Para inicializar una unión se pone entre llaves el valor del primer campo utilizando
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Para acceder al valor de uno de los campos de una unión se utiliza el mismo ope-
rador que para las estructuras: el operador punto (.). La diferencia estriba en que todos
los campos de una unión están compartiendo memoria, por lo que solo uno de ellos con-
tendrá información válida.
var.i= 8;
www.udima.es 335
FUNDAMENTOS DE LA PROGRAMACIÓN
Por tanto, es necesario asegurarse, al acceder a una unión, de que lo que se desea
hacer tiene sentido y consultar el campo que tiene el tipo correcto:
var.r= 8.3; /* ahora var tiene solo un real */
cout << var.r + 0.5; // se imprime un real
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
var.i= 7; /* ahora var tiene solo un entero */
cout << var.i + 1; // se imprime un entero
var.s= "Hola"; /* ahora var tiene solo una cadena */
cout << var.s; // se imprime una cadena
Al igual que ocurría con las estructuras y con otros tipos de datos, en C++ también
se pueden definir punteros a uniones y, como con las estructuras, se utiliza el operador
-> para acceder a uno de los campos de la unión.
6. DEFINICIONES DE TIPOS
La sintaxis que ofrece el lenguaje C++ para declarar algunos de los tipos de datos
dificulta un poco la claridad del código generado. Esto puede solucionarse utilizando la
instrucción typedef, que permite definir sinónimos para los tipos.
Con typedef se pueden definir nuevos nombres de tipos en C++, partiendo de tipos
básicos o complejos. Su sintaxis básica es:
336 www.udima.es
Estas declaraciones definen los tipos real y natural como float y entero sin signo.
Después de declarar este tipo, se pueden declarar variables usando la sintaxis habitual
de C++ y usarlas como cualquier otra variable:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
real z;
natural *n; // puntero a un entero sin signo
Pero typedef se puede utilizar también con tipos como vectores, punteros, estruc-
turas y uniones. Como ejemplo, se va a ver cómo definir el tipo Matriz, que represente
matrices de números reales de 20 filas y 50 columnas, y cómo se puede utilizar:
Finalmente, C++ ofrece una total libertad al programador para definir tipos tan com-
plejos como desee. Se pueden mezclar distintos tipos de datos para obtener tipos mucho
más complejos, pero que dificultan quizá excesivamente su utilización.
• []: vector.
• (): función.
• * : puntero.
www.udima.es 337
FUNDAMENTOS DE LA PROGRAMACIÓN
Las reglas que rigen estos cambios, cuando en una definición de tipos interviene
más de un modificador, son:
int (*f[5])();
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
7. TIPOS ENUMERADOS
Los tipos enumerados se utilizan cuando se desea que algunas variables tengan como
valor un nombre en vez de un número. Por ejemplo, si existe una variable que repre-
senta los días de la semana, en lugar de utilizar los números del 1 al 7, se podría querer
representar los nombres de los días (lunes, martes, miércoles, etc.). La utilización de
tipos enumerados mejora la claridad de los programas, ya que facilitan la comprensión
de expresiones que usan nombres en vez de números.
enum [nombre]
{
valores, ...
} [variable];
338 www.udima.es
El nombre será el nombre que se le quiere dar al tipo y los valores serán la lista de
identificadores que representan los distintos posibles valores que puede tomar el tipo (y
que no podrán coincidir con otro identificador ya declarado). Como se ve, este tipo de
datos se caracteriza por estar formado por un conjunto de identificadores que describen
por extensión el conjunto de elementos del dominio.
enum Dias {lunes, martes, miercoles, jueves, viernes, sabado, domingo};
Dias hoy, manana; // también sirve: enum Dias hoy, manana;
hoy= jueves;
if (hoy == jueves) manana= viernes;
A una variable enumerada solo se le puede asignar un valor dentro del rango indi-
cado en la definición.
Sin embargo, en lenguaje C++ se pueden realizar más acciones sobre los tipos enu-
merados, ya que, en realidad, son equivalentes a números enteros. Un valor de un tipo
enumerado es equivalente a un número entero, cuyo valor indica su posición en la decla-
ración del tipo enumerado (empezando por cero). Así, en el caso del tipo Dias, lunes
es equivalente a 0, martes a 1, y así sucesivamente. Por esta razón, se pueden aplicar
a los tipos enumerados las mismas operaciones que a los números enteros (suma, resta,
incremento, comparar, etc.).
www.udima.es 339
FUNDAMENTOS DE LA PROGRAMACIÓN
Una forma muy común de utilizar los tipos enumerados es para acceder a vectores,
ya que se pueden usar como índice de los elementos del vector aumentando notablemente
la legibilidad del código. Como ejemplo, se va a declarar un vector con las horas labo-
rables de cada día de la semana y se va a inicializar dicho vector con 8 horas de lunes a
viernes y con 0 el sábado y el domingo:
int horas[7];
Dias dia;
for (dia= lunes; dia < sabado; dia++)
horas[dia]= 8;
horas[sabado]= horas[domingo]= 0;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Por tanto, al definir un tipo de dato enumerado se establece también una relación
de orden entre los elementos que lo conforman. El orden viene dado por el orden en el
que se especifica cada uno de los elementos del tipo enumerado. Por eso, el bucle for
anterior funciona correctamente.
enum Meses {enero= 1, febrero, marzo, abril, mayo, junio, julio,
agosto, septiembre, octubre, noviembre, diciembre};
Con esta declaración, el número entero asignado a cada valor coincide con el número
del mes. Aunque, como se ha comentado, las asignaciones pueden ser múltiples y arbi-
trarias, y no es necesario respetar el orden creciente:
340 www.udima.es
CONCEPTOS BÁSICOS
• C++ permite declarar vectores y matrices para almacenar grupos de datos
del mismo tipo y a los que se necesita acceder mediante sus índices.
• C++ ofrece punteros de cualquier tipo que el programador debe saber uti-
lizar con cuidado, solicitando y liberando siempre la memoria necesaria
antes de usar un puntero.
• C++ permite dos formas de utilizar las cadenas de caracteres que deben
conocerse bien, dado que el manejo de las cadenas es una tarea fundamental
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1
a) v[5, 20]= 0;
b) v[5][1]=3, v[v[5][1]]['5']= 0;
www.udima.es 341
FUNDAMENTOS DE LA PROGRAMACIÓN
c) for (int i= 1; i <= 500; i++) v[i][0]= 0;
d) v["hola"][5]= 0;
Enunciado 2
a) int *p= new int (8);
b) float *f= new float [8];
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
c) char *s= "hola";
d) double *d= 0.1;
Enunciado 3
Enunciado 4
a) enum A {a, b, c} B;
b) enum A {a= -5, b= 0, c= 5};
c) enum A {a, b= 3, c} B;
d) enum A {A, B, C} B;
342 www.udima.es
Enunciado 5
a) string hola ("hola");
b) int (*f[5])();
c) int x[][2]= {{1}, {2, 3}, {4, 5, 6}};
d) struct {char a : 3; char b : 5} c;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
www.udima.es 343
FUNDAMENTOS DE LA PROGRAMACIÓN
Solución 1
b) v[5][1]=3, v[v[5][1]]['5']= 0;
Solución 2
d) double *d= 0.1;
Solución 3
Solución 4
d) enum A {A, B, C} B;
Solución 5
c) int x[][2]= {{1}, {2, 3}, {4, 5, 6}};
ACTIVIDADES DE REPASO
1. Escribir una función que reciba como parámetros dos matrices de 3 × 3 y
devuelva en un tercer parámetro la matriz resultante de multiplicar las otras
dos.
2. Escribir un programa que pida al usuario el tamaño de un vector (que
deberá ser creado a continuación por el programa); seguidamente, que pida
al usuario que escriba los números enteros necesarios para llenar todo el
vector; finalmente, el programa devolverá como resultado la suma de los
elementos del vector y su media aritmética. Como se desconoce el tamaño
del vector, deberá utilizarse memoria dinámica para el vector.
3. Definir los tipos de datos más adecuados para almacenar los datos de los
alumnos de una escuela. Los datos serán el nombre, la fecha de nacimiento,
344 www.udima.es
5. Realizar un programa que pida al usuario las horas trabajadas cada día de la
semana y que devuelva la media de horas trabajadas al día, el día que más
ha trabajado y los días que no ha trabajado. Deberá utilizarse un tipo enu-
merado para representar los días de la semana y un vector para almacenar
las horas de cada día, al que deberá accederse mediante el nombre del día
de la semana.
REFERENCIAS BIBLIOGRÁFICAS
Básica
Avanzada
Deitel, H. M. y Deitel, P. J. C++ How to Program. 7.ª ed. Prentice Hall, 2009.
www.udima.es 345
FUNDAMENTOS DE LA PROGRAMACIÓN
346 www.udima.es
10
UNIDAD
DIDÁCTICA
EL PREPROCESADOR
DE C++. LIBRERÍAS
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Objetivos de la unidad
1. Introducción
2. Preprocesador de C++
2.1. Nombres simbólicos y macros
2.2. Inclusión de ficheros
2.3. Compilación condicional
2.4. Otras directivas
3. Librerías
3.1. Cadenas de caracteres
3.1.1. Librería cstring
3.2. Librerías de entrada/salida
3.2.1. Salida
3.2.2. Entrada
3.2.3. Ficheros
3.2.4. Formatos
3.2.5. Errores
3.3. Librería cstdlib
3.4. Librería cmath
www.udima.es 347
FUNDAMENTOS DE LA PROGRAMACIÓN
Conceptos básicos
Actividades de autocomprobación
Actividades de repaso
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Referencias bibliográficas
348 www.udima.es
OBJETIVOS DE LA UNIDAD
Para sacar el máximo partido a las técnicas de programación es conveniente co-
nocer y dominar todas las características del lenguaje de programación que se vaya a
utilizar. Por ello, en esta unidad didáctica se explican las características principales del
preprocesador de C++ y se destacan sus principales funcionalidades. Finalmente, tam-
bién se comentan, de forma resumida, algunas librerías con sus funciones principales,
que pueden encontrarse en la mayoría de los compiladores de C++. Una de estas libre-
rías contiene operaciones para realizar la entrada/salida.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
www.udima.es 349
FUNDAMENTOS DE LA PROGRAMACIÓN
1. INTRODUCCIÓN
En esta última unidad didáctica se van a tratar dos temas muy relacionados con
el C++ y que acompañan siempre a los compiladores del lenguaje. El primero de ellos
se refiere al preprocesador de C++. Todos los compiladores de C++ realizan una fase
previa de preprocesado que permite definir nombres, crear macros, incluir ficheros o
realizar una compilación condicional. Esto facilita la labor de programación en C++, ya
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
El segundo tema se refiere a las librerías. Los compiladores de C++ vienen acom-
pañados de un conjunto más o menos extenso de librerías de funciones o clases que
están disponibles para el programador. De esta manera, se simplifica también la tarea de
programación, ya que el programador se encuentra funciones ya implementadas.
2. PREPROCESADOR DE C++
350 www.udima.es
site la directiva (todo en la misma línea). La palabra y el resto de los datos tienen que ir
separados obligatoriamente por, al menos, un espacio; entre la almohadilla y la palabra
pueden escribirse espacios opcionalmente. En los epígrafes siguientes se van a estudiar
las directivas más importantes.
Estos nombres simbólicos pueden ser cualquier construcción del lenguaje, aunque
lo más habitual es utilizarlos para representar números, caracteres, cadenas de caracte-
res, etc.
Para definir un nombre simbólico basta con poner la directiva, el nombre que se
quiere utilizar y su valor (opcional), separados por espacios:
#define nombre [valor]
Por ejemplo, en la siguiente línea se crea un nombre simbólico para usar la cons-
tante PI:
#define PI 3.141592
x= 2 * PI * radio;
www.udima.es 351
FUNDAMENTOS DE LA PROGRAMACIÓN
lo que quedará después de que el preprocesador realice la sustitución, listo para ser
compilado, será:
x= 2 * 3.141592 * radio;
Estos nombres simbólicos usados para nombrar constantes (de hecho, muchas veces
se les llama constantes en vez de nombres simbólicos) dotan de mayor legibilidad a los
programas, ya que suelen permitir hacer expresiones más claras. No obstante, para faci-
litar la lectura del código a otros programadores, existe la costumbre extendida de bau-
tizar los nombres simbólicos con nombres en mayúsculas.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
#define NULL 0
#define HABITANTES 3E6
#define CR '\n'
#define THEN
#define ELSE else
if (numHabitantes < HABITANTES)
THEN cout << numHabitantes + 1 << CR;
ELSE numHabitantes++;
if (numHabitantes < 3E6)
cout << numHabitantes + 1 << '\n';
else numHabitantes++;
352 www.udima.es
El segundo tipo de elementos que puede definirse con la palabra define son las
macros. Las macros son como los nombres simbólicos, pero con argumentos:
#define nombre(argumentos) expresión
Lo que permiten las macros es evitar crear ciertas funciones en un programa, ya que
algunas funciones sencillas pueden escribirse como macros. La ventaja de usar macros
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
#define cuadrado(x) x * x
a= cuadrado (2);
a= 2 * 2;
b= cuadrado (a + 2);
www.udima.es 353
FUNDAMENTOS DE LA PROGRAMACIÓN
b= a + 2 * a + 2;
Para solucionar este problema, siempre se aconseja encerrar los parámetros entre
paréntesis dentro de la definición de la macro e, incluso también, la definición completa.
De esta forma, la macro cuadrado tendría que definirse así:
#define cuadrado(x) ((x) *(x))
Así definida, las dos sentencias anteriores quedarían tras el preprocesado así:
a= ((2) * (2));
b= ((a + 2) * (a + 2));
No obstante, tampoco conviene abusar de las macros, ya que pueden tener unos
impredecibles efectos colaterales nada deseados. Supóngase ahora que la llamada a la
macro se realiza de la siguiente forma:
c= cuadrado (a++);
354 www.udima.es
cuenta que cuadrado no es una función, sino que es una macro que será sustituida por el
preprocesador de la siguiente manera:
c= ((a++) * (a++));
Para finalizar con las macros y nombres simbólicos, hay que indicar que existe una
directiva para deshacer su definición: la directiva undef. De esta manera, deja de estar
definido el nombre simbólico o macro. Su utilización consiste en poner a continuación
el nombre que se quiere dejar sin definición. Por ejemplo:
#undef PI
Existe una directiva que permite incluir un archivo dentro de otro: la directiva
include. Se utiliza fundamentalmente para incluir ficheros de cabecera de funciones de
librería y de módulos del programa. Esta directiva tiene dos notaciones:
#include <fichero>
#include "fichero"
www.udima.es 355
FUNDAMENTOS DE LA PROGRAMACIÓN
Los ficheros que hay que incluir deben ser ficheros de cabecera (header) con la
extensión .h. Si el fichero pertenece a las librerías de C, hay que indicar la extensión; si
el fichero pertenece a las librerías estándar de C++ (aunque sean librerías convertidas de
C), no debe indicarse la extensión. Es importante resaltar que no deben incluirse ficheros
de código C++ (.cpp). En el caso de utilizarse las librerías estándar de C++, también es
necesario incluir la siguiente instrucción tras los include correspondientes:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
using namespace std;
#include <iostream>
#include "micabecera.h"
#ifdef NOMBRE
#ifndef NOMBRE
#if expresión
#else
#elif expresión
#endif
356 www.udima.es
La compilación condicional tiene varios usos. Por un lado, permite escribir pro-
gramas para usarlos en varias máquinas o compiladores en los que una parte del código
depende de la máquina o del compilador. El siguiente ejemplo muestra cómo hacerlo:
#ifdef WINDOWS
cout << "Compilación para Windows";
#elif defined UNIX
cout << "Compilación para UNIX";
#else
cout << "Compilación para DOS";
#endif
En este ejemplo bastaría con definir el símbolo WINDOWS para que el programa se
compilara en su versión para Windows. Si ese símbolo no está definido, pero está defi-
nido el símbolo UNIX, se compilaría en su versión para UNIX; en caso contrario, se com-
www.udima.es 357
FUNDAMENTOS DE LA PROGRAMACIÓN
pilaría una versión para DOS. Este tipo de compilación condicional puede ser necesario,
por ejemplo, si algún cálculo depende de los tamaños de los datos o de las direcciones.
Un ejemplo sería si un sistema tuviera enteros de 2 bytes y otro de 4 bytes. Si se nece-
sitan enteros que no caben en 2 bytes, se podría hacer:
#ifndef GRANDES
long int sueldo;
#else
int sueldo;
#endif
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
#ifndef _CIRCULO_H_
#define _CIRCULO_H_
// Código que se tiene que compilar una sola vez
#endif
Un último uso que se puede hacer de las directivas de compilación condicional con-
siste en usarlas para, durante el desarrollo, compilar código adicional que ayude en la
depuración, en los cálculos de eficiencia del código, etc.:
#if !defined FINAL
cout << "Se va a llamar a la función f";
inicializarContadorTiempo (0);
358 www.udima.es
#endif
f(5);
#ifndef FINAL
cout << "La función f ha tardado: "
<< tiempoTranscurrido () << " segundos";
#endif
C++ proporciona también otras directivas algo menos utilizadas. Se resumen bre-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
vemente a continuación:
#line constante ["fichero"]
La directiva line permite definir que la línea actual será la que indique la cons-
tante (un número entero). Esto se usa normalmente para el diagnóstico de errores o
para la depuración simbólica, o también cuando otro programa genera código C++. Si,
además de la constante, se da el nombre de un fichero, entonces se considerará que el
fichero tiene este nombre. Tanto el nombre del fichero como la línea son utilizados por
el compilador para emitir sus mensajes de error.
#error cadena
#pragma parámetros
www.udima.es 359
FUNDAMENTOS DE LA PROGRAMACIÓN
3. LIBRERÍAS
En C++ existen dos librerías estándar que permiten utilizar y manipular cadenas de
caracteres. La primera de ellas, cstring.h, proviene del lenguaje C y utiliza las cadenas
propias del lenguaje (char *). La segunda de ellas, string.h, utiliza una definición nueva
(string), que dota de mayor facilidad y seguridad al manejo de cadenas de caracteres.
360 www.udima.es
char cadena[10]= "Hola";
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
• int strcmp (const char * str1, const char * str2). Compara dos cadenas
de caracteres. Se empieza comparando el primer carácter de cada cadena y,
si son iguales, continúa hacia el siguiente. Se repite esto hasta encontrar una
diferencia o llegar al final de alguna de las cadenas.
Si el valor devuelto es cero, indica que ambas cadenas son iguales. Si devuelve
un valor positivo, quiere decir que el primer carácter distinto tiene un valor
mayor en str1 que en str2; si devuelve un valor negativo, quiere decir lo
contrario.
• char * strcpy (char * destino, char * origen). Esta función copia el con-
tenido de origen en destino y devuelve el destino. Es importante des-
tacar que destino debe tener, al menos, el mismo tamaño que origen,
incluyendo el carácter nulo. Por ejemplo:
char origen[10]= "hola";
int tamano= strlen(origen) + 1; //para incluir el \0
char *destino= new char[tamano];
strcpy (destino, origen);
www.udima.es 361
FUNDAMENTOS DE LA PROGRAMACIÓN
char cadena[50];
strcpy (cadena, "Con");
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
strcat (cadena, "cate");
strcat (cadena, "nado");
El lenguaje no dispone de palabras reservadas para realizar todas estas tareas que,
por otro lado, resultan fundamentales para dotar de interacción al programa. El problema
se soluciona con una serie de librerías que proporcionan todas las herramientas necesa-
rias para realizar la entrada/salida que pueda requerir el programador.
362 www.udima.es
En estas nuevas librerías se encuentra definida una jerarquía de clases1 que incorporan
las funciones para realizar todas las operaciones de entrada/salida a través de canales. En
la siguiente figura se encuentra representada, de manera resumida, parte de esta jerarquía:
ios
istream ostream
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
iostream
ifstream ofstream
fstream
La clase ios es una clase abstracta que actúa como clase base del resto de las clases.
El significado de las otras clases queda reflejado en el siguiente cuadro:
istream
ostream
iostream
ifstream
ofstream
fstream
1 Como el lenguaje C++ es un lenguaje orientado a objetos, estas librerías hacen uso de este paradigma.
No obstante, para utilizarlas no se necesita conocer la orientación a objetos, aunque en la explicación se
usarán diversos conceptos que, probablemente, el lector no conozca todavía.
www.udima.es 363
FUNDAMENTOS DE LA PROGRAMACIÓN
Un canal (stream) es un tipo de datos que refleja cualquier flujo de datos, desde una
fuente a un consumidor. Los canales cin, cout y cerr son tres canales estándar que se
encuentran predefinidos y que se utilizan, respectivamente, para la entrada, la salida y la
generación de mensajes de error.
3.2.1. Salida
La salida por un canal se indica con el operador de inserción (<<), que se encuentra sobre-
cargado para las operaciones de salida. Recibe, como primer operando, un canal de salida y,
como segundo, la expresión cuyo valor se pretende mostrar. Además, dado que es asocia-
tivo por la izquierda y que devuelve una referencia al primer operando, puede encadenarse:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
cout << "Resultado : z= " << x * y << '\n';
La clase diseñada para realizar la salida es ostream y dispone de una serie de funciones
que pueden emplearse para realizar la salida de información, entre las que pueden citarse:
cout.put ('A').put('B'); // Imprime A y B en cout
cout.write ("Solución", 3); // Imprime Sol
364 www.udima.es
3.2.2. Entrada
cin >> x >> y; // Lee valores y los introduce en variables x, y
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
La clase diseñada para realizar la entrada es istream y dispone de una serie de fun-
ciones que pueden emplearse para realizar la entrada de información, entre las que destacan:
char c= cin.getc (); // Almacena en c el carácter leído
cin.get (c);
const int MAX= 256;
char cad[MAX];
cin.getline (cad, MAX);
www.udima.es 365
FUNDAMENTOS DE LA PROGRAMACIÓN
3.2.3. Ficheros
Modo Acción
ios::noreplace Si el fichero existe, error si se abre para escribir y no está ios::app ni ios::ate
366 www.udima.es
ifstream fi ("datos.bin", ios::binary); // se define fi
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
ifstream fi;
fi.open ("datos.bin");
3.2.4. Formatos
www.udima.es 367
FUNDAMENTOS DE LA PROGRAMACIÓN
Indicador Significado
ios::basefield ios::dec,
ios::hex,
ios::oct
.../...
368 www.udima.es
.../...
ios::floatfield ios::fixed,
ios::scientific
Existe una serie de funciones que permiten modificar el formato en las operaciones
de salida; entre ellas, pueden destacarse:
www.udima.es 369
FUNDAMENTOS DE LA PROGRAMACIÓN
Ejemplo de uso:
#include <iostream>
using namespace std;
void main(void)
{
cout << 10; // imprime 10
cout.width (6); // fija el ancho de escritura
cout << 20 << '\n'; // imprime 20 dejando 4 blancos
cout.flags (ios::hex | ios::showbase);
cout << 30 << '\n'; // imprime 30 en hexadecimal
cout.flags (ios::dec);
cout << true << '\n'; // imprime verdadero en decimal
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
cout.setf (ios::boolalpha);
cout << true << '\n'; // imprime "true"
}
10 20
0x1e
1
true
Una manera sencilla de dar un formato específico, evitando manejar los indicadores
directamente, consiste en utilizar los manipuladores. Para utilizarlos hay que incluir el
fichero iomanip.h. Los principales manipuladores se muestran en el cuadro siguiente:
.../...
370 www.udima.es
.../...
Su utilización es sencilla:
cout << hex << v << endl;
// Muestra v en hexadecimal y salta de línea
canal &manipulador (canal &);
Para diseñar, por ejemplo, el manipulador upperhex, que establezca base hexade-
cimal en mayúsculas mostrando la base, podría programarse:
ostream &upperhex (ostream &os)
{
os << setiosflags (ios::showbase | ios::uppercase) << hex;
return os;
}
www.udima.es 371
FUNDAMENTOS DE LA PROGRAMACIÓN
cout << upperhex << valor << endl;
3.2.5. Errores
Cada canal tiene asociado un estado. Los errores y situaciones anómalas se manejan
activando y comprobando dicho estado, que puede consultarse utilizando las funciones:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Además, en caso de que se produzca algún error en un canal, este tomará el valor cero:
ifstream fich ("prueba.txt");
if (!fich)
error ("Imposible abrir el fichero");
while (fich) // Cuando fich llegue al final, será cero
{
fich.get (c); // Lee un carácter
cout << c; // y lo imprime
}
372 www.udima.es
• void exit (int estado); Esta función abandona la ejecución del pro-
grama, cerrando los ficheros abiertos y vaciando los buffers. Si se escribe
un número entre los paréntesis, será el valor que devuelva el programa.
int num= atoi ("421"); // num valdrá el valor entero 421
double num= atof ("421.12"); //num valdrá el valor real 421.12
int n= abs (-400); // n valdrá 400
div_t res= div (38, 5);
int resultado= res.quot; // resultado valdrá 7
int resto= res.rem; // resto valdrá 3
www.udima.es 373
FUNDAMENTOS DE LA PROGRAMACIÓN
• int rand (); Genera números pseudoaleatorios que van desde cero hasta
RAND_MAX (nombre simbólico definido en esta librería). Utilizando el operando
módulo, se pueden generar números aleatorios definidos dentro de un rango:
(rand() % 100 ) // devolverá un valor entre 0 y 99.
(rand() % 10 + 1 ) // devolverá un valor entre 1 y 10.
(rand() % 30 + 2009 ) // devolverá un valor entre 2009 y 2038.
• Redondeo:
int n1= ceil (4.3); // n1 valdrá 5.0
int n2= ceil (2.8); // n2 valdrá 3.0
int n3= ceil (-3.3); // n3 valdrá -3.0
int n4= ceil (-7.8); // n4 valdrá -7.0
double n1= floor (4.3); // n1 valdrá 4.0
double n2= floor (2.8); // n2 valdrá 2.0
374 www.udima.es
double n3= floor (-3.3); // n3 valdrá -4.0
double n4= floor (-7.8); // n4 valdrá -8.0
double n1= fmod (5.3, 2); // n1 valdrá 1.3
double n2= fmod (18.5, 4.2); // n2 valdrá 1.7
3.5.1. Clasificación
Esta librería contiene funciones que ayudan a clasificar los caracteres, es decir, ayudan
a averiguar a qué grupo de caracteres pertenece uno dado. Estas funciones devuelven un
valor falso (cero) si no se cumple la condición o verdadero en caso de que se cumpla:
www.udima.es 375
FUNDAMENTOS DE LA PROGRAMACIÓN
• int islower (int c); Comprueba si el carácter es una letra minúscula (a-z).
• int isupper (int c); Comprueba si el carácter es una letra mayúscula (A-Z).
• int isspace (int c); Comprueba si el carácter recibido es blanco, tabu-
lador o nueva línea.
• int ispunct (int c); Comprueba si el carácter es un signo de puntuación.
• int isxdigit (int c); Comprueba si el carácter corresponde a un dígito
hexadecimal; es decir, si está entre 0 y 9 o entre A y F.
3.5.2. Manipulación
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Además de las funciones anteriormente vistas, esta librería proporciona dos fun-
ciones muy útiles de manipulación de caracteres:
• int toupper (int c); Si el carácter recibido corresponde a una letra minús-
cula con representación mayúscula, devuelve su equivalente en mayúsculas;
si no, devuelve el carácter recibido.
• int tolower (int c); Si el carácter pasado corresponde a una letra mayús-
cula con representación minúscula, devuelve su equivalente en minúsculas;
si no, devuelve el carácter que se recibió.
#include <cctype>
//...
int i= 0;
char str[]="Prueba Uno.";
char c;
cout << str << endl;
while (str[i] != '\0')
{
c= str[i];
if (isupper (c))
str[i]= tolower (c);
if (islower (c))
str[i]= toupper (c);
i++;
}
cout << str << endl;
376 www.udima.es
3.6. ERRORES
#include <cstdio>
#include <cerrno>
#include <cmath>
#include <iostream>
using namespace std;
void main (void)
{
double n= acos (-2);
if (errno)
{
perror ("Ha ocurrido el siguiente error");
errno= 0;
}
else
{
cout << "acos(-2)= " << n << "\n";
}
n= acos(-1);
if (errno)
{
www.udima.es 377
FUNDAMENTOS DE LA PROGRAMACIÓN
perror ("Ha ocurrido el siguiente error");
errno= 0;
}
else
{
cout << "acos(-1)= " << n << "\n";
}
}
Ha ocurrido el siguiente error: Domain error
acos(-1) = 3.14159
No obstante, C++ dispone del mecanismo de las excepciones para manejar de una
manera más cómoda y adecuada los errores que puedan producirse durante la ejecución
de un programa.
Nombre Descripción
.../...
378 www.udima.es
Nombre Descripción
.../...
.../...
www.udima.es 379
FUNDAMENTOS DE LA PROGRAMACIÓN
.../...
stack Contiene los tipos de datos • size: devuelve el número de elementos que contiene
y la funcionalidad para • empty: indica si la pila está vacía
manejar una estructura de • push: inserta un elemento en la cima
datos del tipo pila, en la que • pop: elimina el elemento de la cima
los elementos se insertan y
• top: devuelve el elemento de la cima
se extraen siempre de un
mismo extremo de la estruc-
tura (la cima).
.../...
380 www.udima.es
.../...
queue Contiene los tipos de datos • size: devuelve el número de elementos que contiene
y la funcionalidad para • empty: indica si la cola está vacía
manejar una estructura • push: inserta un elemento
de datos del tipo cola, en • pop: elimina el siguiente elemento
la que los elementos se
• top: devuelve el elemento de la cima
insertan por un extremo y
se extraen por el contrario. • front: devuelve el siguiente elemento
• back: devuelve el último elemento (el más nuevo)
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
priority_queue Contiene una cola con prio- • size: devuelve el número de elementos que contiene
ridades en la que siempre • empty: indica si la cola está vacía
se devuelve el elemento que • push: inserta un elemento
más prioridad tenga, según • pop: elimina el elemento de la cima
un criterio de ordenación.
• top: devuelve el elemento de la cima
set Guarda un conjunto de ele- • size: devuelve el número de elementos que contiene
mentos únicos, es decir, no • empty: indica si el conjunto está vacío
puede haber dos elementos • insert: inserta un elemento
iguales. Los elementos son • erase: elimina un elemento
su propia clave.
• swap: intercambia el contenido de dos conjuntos
• clear: borra todo el contenido
• find: busca un elemento
• count: cuenta las veces que está un elemento en el
conjunto
multimap Al igual que map, pero per- Las mismas que map
mite más de un elemento
con la misma clave.
.../...
www.udima.es 381
FUNDAMENTOS DE LA PROGRAMACIÓN
.../...
bitset Es un contenedor de valores • Los operadores que manejan bits (&, |, ^, etc.)
lógicos, es decir, contiene • operador [] / test: devuelve el bit de una posición
valores 0 (falso) o 1 (cierto). • set: pone a 1 los bits (todos o el indicado)
• reset: pone a cero los bits (todos o el indicado)
• flip: cambia el valor de un bit al opuesto (uno o
todos)
• to_ulong: convierte el conjunto a un entero sin
signo
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
382 www.udima.es
CONCEPTOS BÁSICOS
• El preprocesador de C++ ofrece la posibilidad de definir nombres simbó-
licos con un cierto valor. Cada vez que aparece dicho nombre simbólico en
el código fuente, se sustituye por su valor y luego se compila.
• El preprocesador de C++ permite definir macros para realizar ciertas ope-
raciones sencillas. Debe saberse definir adecuadamente y evitar posibles
efectos colaterales.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1
www.udima.es 383
FUNDAMENTOS DE LA PROGRAMACIÓN
a) x= z > a ? a : b
b) x= z > i ? i : j
c) x= z > j ? j : i
d) x= z > (i ? i : j)
Enunciado 2
¿Qué se imprimirá por pantalla al ejecutar el código: z= 6; i= 0; cout << RANGO (++z);
teniendo en cuenta que se tiene #define RANGO(x) (((x)> 5 && (x) < 10) ? (x) : (i))?
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
a) 6
b) 7
c) 9
d) 0
Enunciado 3
Enunciado 4
384 www.udima.es
Enunciado 5
¿Cómo se puede imprimir el valor real de f con dos decimales y el valor entero de
i en octal seguido de un salto de línea?
www.udima.es 385
FUNDAMENTOS DE LA PROGRAMACIÓN
Solución 1
b) x= z > i ? i : j
Solución 2
c) 9
Solución 3
Solución 4
Solución 5
ACTIVIDADES DE REPASO
1. Escribir una macro que permita calcular el mínimo de tres números. Explicar
un ejemplo de uso de esta macro que proporcione un resultado no esperado.
2. Escribir un código que permita calcular el cubo de un número real. El código
deberá escribirse de tres maneras: como macro, como función y como fun-
ción inline. Buscar en las librerías de funciones del compilador alguna
función para obtener la hora y usarla para estimar el tiempo de ejecución
de cada llamada. Para facilitar la medida de tiempos, deberían crearse unos
bucles que calculen varios miles de veces el cubo de distintos números
mediante las tres técnicas. Dar, finalmente, las conclusiones sobre la téc-
386 www.udima.es
REFERENCIAS BIBLIOGRÁFICAS
Básica
Avanzada
Deitel, H. M. y Deitel, P. J. C++ How to Program. 7.ª ed. Prentice Hall, 2009.
Fuertes, J. L. y González, Á. L. El lenguaje de programación C. Koobeth International, 2004.
Kernighan, B. W. y Ritchie, D. M. The C Programming language. 2.ª ed. Prentice Hall, 2004.
Liberty, J.; Rao, S. y Jones, B. L. Sams Teach Yourself C++ in One Hour a Day. Sams, 2008.
www.udima.es 387
ÍNDICE SISTEMÁTICO
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
PÁGINA
Sumario ...................................................................................................... 5
Prólogo ....................................................................................................... 7
www.udima.es 389
FUNDAMENTOS DE LA PROGRAMACIÓN
un programa ......................................................... 41
Objetivos de la unidad ...................................................................................................... 43
1. Algoritmo .................................................................................................................... 44
1.1. Características básicas .................................................................................. 45
1.2. Algoritmo de Euclides .................................................................................. 46
1.3. Algoritmos computables y no computables............................................... 48
390 www.udima.es
Índice sistemático
1. Introducción ............................................................................................................... 85
2. Definición de los requisitos del problema .............................................................. 87
3. Análisis ........................................................................................................................ 93
4. Diseño .......................................................................................................................... 96
4.1. Diseño general ............................................................................................... 96
4.2. Diseño detallado ............................................................................................ 98
www.udima.es 391
FUNDAMENTOS DE LA PROGRAMACIÓN
392 www.udima.es
Índice sistemático
www.udima.es 393
FUNDAMENTOS DE LA PROGRAMACIÓN
394 www.udima.es
Índice sistemático
www.udima.es 395
FUNDAMENTOS DE LA PROGRAMACIÓN
1. Introducción................................................................................................................ 268
2. Funciones en C++ ....................................................................................................... 268
2.1. Declaración de funciones ............................................................................. 268
2.2. Definición de funciones ................................................................................ 270
2.3. Funciones de librería ..................................................................................... 272
2.4. Funciones en línea ......................................................................................... 273
396 www.udima.es
Índice sistemático
1. Introducción................................................................................................................ 302
2. Vectores y matrices .................................................................................................... 302
2.1. Vectores .......................................................................................................... 302
2.2. Matrices .......................................................................................................... 305
2.3. Representación interna de vectores y matrices ......................................... 309
www.udima.es 397
FUNDAMENTOS DE LA PROGRAMACIÓN
398 www.udima.es
Fundamentos de
tiene dos partes diferenciadas.
En la primera parte se definen los conceptos fundamentales
que se aplican en cualquier programa de ordenador reali-
zado mediante lenguajes de programación estructurados
la programación.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B
Fundamentos de la programación
programas de ordenador y aplicar conceptos que son válidos
para cualquier lenguaje de programación estructurada.
Más en concreto, se espera que el lector pueda aprender David Lizcano Casas (coord.)
a definir algoritmos, implementar estructuras de datos y
determinar la eficiencia de los programas realizados. Fernando Alonso Amo
Loïc Antonio Martínez Normand
José Luis Fuertes Castro
902 02 00 03
www.udima.es
Ediciones
Ediciones
1/1