Está en la página 1de 400

David Lizcano Casas (coord.

Loïc A. Martínez Normand


José Luis Fuertes Castro
Fernando Alonso Amo
El presente manual pretende introducir los conceptos
básicos de la construcción de programas de ordenador y

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


de alto nivel. Los ejemplos de esta parte están presentados
usando un lenguaje genérico, llamado pseudocódigo. El
objetivo de usar este pseudocódigo es poder plasmar los
conceptos de forma independiente a como se representan
en cada lenguaje de programación.
En la segunda parte se aplican los conceptos presentados
anteriormente a un lenguaje concreto de programación, el
lenguaje C++. Este lenguaje ha sido elegido por su versa-
tilidad y potencia.
El objetivo fundamental que se persigue es que el lector
pueda ser capaz de resolver problemas sencillos mediante

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

Powered by TCPDF (www.tcpdf.org)

1/1
Fundamentos de
la programación.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

David Lizcano Casas (coord.)


Profesor de la Escuela de
Ciencias Técnicas e Ingeniería, UDIMA

Fernando Alonso Amo


Profesor catedrático de la ETS
de Ingenieros Informáticos, UPM

Loïc Antonio Martínez Normand


Profesor de la ETS de
Ingenieros Informáticos, UPM

José Luis Fuertes Castro


Profesor de la ETS
de Ingenieros Informáticos, UPM

Powered by TCPDF (www.tcpdf.org)


Esta obra es fruto del análisis y de los estudios, estrictamente personales, del autor.
Los comentarios que se efectúan a lo largo de este libro constituyen la opinión personal
del autor. El autor no aceptará responsabilidades por las eventualidades en que puedan
incurrir las personas o entidades que actúen o dejen de actuar como consecuencia de las
opiniones, interpretaciones e informaciones contenidas en este libro.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

«Cualquier forma de reproducción, distribución, comunicación pública o transformación de esta


obra solo puede ser realizada con la autorización de sus titulares, salvo excepción prevista por la ley.
Diríjase a CEDRO (Centro Español de Derechos Reprográficos) si necesita fotocopiar o escanear
algún fragmento de esta obra (www.conlicencia.com; 91 702 19 70 / 93 272 04 47)»

© Edita: CENTRO DE ESTUDIOS FINANCIEROS


I.S.B.N.: 978-84-454-3

Powered by TCPDF (www.tcpdf.org)


Sumario │

SUMARIO
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

PÁGINA

Prólogo........................................................................................................ 7

Unidad didáctica 1. Concepto de programa informático ................. 9

Unidad didáctica 2. Algoritmos y sistemas de representación de


un programa ......................................................... 41

Unidad didáctica 3. Tratamiento informático de un problema ...... 83

Unidad didáctica 4. La programación y los lenguajes informá-


ticos ......................................................................... 115

Unidad didáctica 5. El lenguaje imperativo C++ ................................ 155

Unidad didáctica 6. Expresiones ........................................................... 175

Unidad didáctica 7. Sentencias y entrada/salida básica ................... 235

Unidad didáctica 8. Funciones ............................................................... 265

www.udima.es 5

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Unidad didáctica 9. Tipos avanzados de datos .................................. 299

Unidad didáctica 10. El preprocesador de C++. Librerías .................. 347

Índice sistemático ..................................................................................... 389


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

6 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

PRÓLOGO
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Cuando hablamos de fundamentos de un concepto nos estamos refiriendo a los prin-


cipios u orígenes en los que se asienta dicho concepto; en este caso, nos referimos a las
bases de la programación informática o programación algorítmica, consistentes en dise-
ñar, codificar, depurar y mantener el código fuente de un programa informático que se
ejecute en una computadora.

Haciendo un poco de historia sobre la computadora, soporte de la ejecución de un


programa informático, señalemos que fue el profesor británico Charles Babbage en 1837
quien diseñó la máquina analítica origen de la computadora moderna de uso general,
aunque la máquina no se pudo construir por razones políticas. Si la máquina analítica
hubiera estado construida, hubiera sido digital, programable y Turing completo. Babbage
alistó para la divulgación de su máquina a Augusta Ada King, condesa de Lovelace,
que fue la primera persona en el mundo que describió un lenguaje de programación de
carácter general al interpretar las ideas de Babbage. El lenguaje de programación Ada,
creado por el Departamento de Defensa de los Estados Unidos, fue nombrado así para
su reconocimiento.

Centrándonos en los conceptos que definen los fundamentos de la programación,


cabe señalar que la resolución de cualquier problema de la vida precisa una reflexión
sobre la forma de resolverlo y las herramientas utilizadas para: identificarlo, establecer
un modelo de planificación para desarrollar las acciones pertinentes a su resolución y
ejecutar dichas acciones.

www.udima.es 7

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

En el caso de la resolución de un problema utilizando una computadora, los elemen-


tos fundamentales que se utilizan son:

La identificación y definición del problema, o enunciado del problema, que se basa


en un texto escrito que describa el problema que se debe resolver.

Para la planificación y diseño de la solución se utiliza un algoritmo o pseudocódigo


apropiado que permita, mediante un conjunto de instrucciones o reglas bien definidas,
ordenadas y finitas, partir, a través de pasos sucesivos, desde un estado inicial hasta lle-
gar a un estado final que resuelva el problema planteado. Evidentemente, la implemen-
tación del algoritmo dependerá de la herramienta que se utilice para su resolución que,
en el caso de un problema informático, es la computadora. Esto exige la codificación
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.

Fernando Alonso Amo


Catedrático de Ciencias de la Computación

8 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

1
UNIDAD
DIDÁCTICA

CONCEPTO DE
PROGRAMA INFORMÁTICO
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Objetivos de la unidad

1. Introducción a las computadoras


2. La programación
3. Concepto de programa
4. El pseudocódigo
4.1. Reglas generales del pseudocódigo

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

6. Estructuras de control: repeticiones


6.1. Estructura de tipo «Mientras»
6.2. Estructura de tipo «Hasta»
6.3. Estructura de tipo «Para»

Conceptos básicos

www.udima.es 9

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Concepto de programa informático

 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.

Posteriormente, se pasa a explicar el concepto de programación como el proceso


que se lleva a cabo para resolver problemas mediante computadoras. La programación
tiene como resultado la construcción de programas, que son secuencias de instrucciones
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

que ejecutará la computadora para resolver los problemas planteados.

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

1. INTRODUCCIÓN A LAS COMPUTADORAS

Como es sabido, el hombre se ha esforzado desde el principio de la humanidad en


inventar sistemas y máquinas que le hagan el trabajo más llevadero, es decir, conseguir
con el mínimo esfuerzo el máximo rendimiento. Por ejemplo, la lavadora, el automóvil,
el tractor, la calculadora, etc.

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

miento de la información y de la ejecución de grandes volúmenes de cálculos compli-


cados mediante el empleo de la computadora (también llamada computador u ordenador).
Esta máquina tiene una velocidad de operación muy superior a la humana, ya que nunca
se cansa y tiene muchas menos probabilidades de cometer errores.

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.

Computadora. Máquina capaz de realizar un elevado número de operaciones en


un breve espacio de tiempo y con gran precisión.

12 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Concepto de programa informático

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.

Profundizando un poco más en el concepto de computadora, se puede considerar


el esquema básico recogido en la figura 1. El elemento central de la computadora es la
unidad central de proceso (CPU), que es la encargada de ejecutar las instrucciones con-
tenidas en los programas. Para poder llevar a cabo estas instrucciones, la CPU alma-
cena información en su memoria (que podrá consultar en cualquier momento) y debe
ser capaz de obtener y enviar información al exterior, para lo que cuenta con una unidad
de entrada/salida (E/S) encargada de comunicarse con dispositivos de entrada (teclado,
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

ratón, etc.) y dispositivos de salida (monitor, altavoces, etc.).

Figura 1. Esquema básico de una computadora

Memoria Unidad E/S

CPU

Programa

Teniendo esto en cuenta, las instrucciones que procesa una computadora (es decir,
su CPU) se pueden clasificar en los siguientes tipos:

• Entrada. Operaciones destinadas a obtener información del exterior (por


ejemplo, datos introducidos por la persona que utiliza la computadora). Estas
operaciones requieren participación de la unidad de E/S y suelen producir
la aparición de nuevos datos en la memoria.

www.udima.es 13

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

• Salida. Operaciones destinadas a enviar información al exterior (por ejemplo,


los resultados de la ejecución del programa enviados al usuario). Estas ope-
raciones también requieren participación de la unidad de E/S y suelen uti-
lizar los datos de la memoria para producir las salidas deseadas.
• Cómputo. Operaciones internas de la computadora que realiza con datos
almacenados en la memoria. Dentro de las operaciones de cómputo hay ope-
raciones aritméticas (sumas, restas, multiplicaciones, etc.), lógicas (mayor
que, menor que, etc.) y de memoria (mover un dato de una posición a otra
de memoria, copiar un dato, etc.).
• Control. Operaciones utilizadas para determinar cuál es la siguiente ins-
trucción que debe ejecutar la CPU. Estas operaciones de control son las
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

que permiten que una computadora tenga comportamientos diferentes que


sean adecuados para los datos almacenados en memoria y para las entradas
recibidas en cada momento.

En resumen, las computadoras son capaces de seguir instrucciones muy sencillas,


pero sus ventajas son la rapidez y la exactitud en el seguimiento de dichas instrucciones.
Por lo tanto, una computadora resolverá bien los problemas que se le plantean si opera
con una programación adecuada.

2. LA PROGRAMACIÓN

Cuando se habla de «programación» dentro del campo de la informática, en su sen-


tido más simple, se trata de diseñar y codificar un programa que, al ejecutarse en una
computadora, resuelva un problema.

Programación. Proceso de planificar y desarrollar la resolución de un problema


mediante una computadora.

Por ejemplo, si se tiene una serie de números y se pide seleccionar el menor y


el mayor, el proceso normal de selección es muy simple cuando se dispone de pocos
números, pero se complica muchísimo si la selección se debe realizar con gran cantidad
de números (por ejemplo, con 5.000).

14 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Concepto de programa informático

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

girían cientos de horas e incluso serían inviables.

En la figura 2 se representa de forma esquemática el proceso de resolución de un


problema mediante computadora. En dicha figura se especifica que un problema plan-
teado se traduce en un programa informático y en unos datos que va a tratar ese pro-
grama. La ejecución del programa en la computadora con los datos de entrada producirá
los resultados esperados.

Figura 2. Resolución de un problema por computadora

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Figura 3. Ejemplo de resolución de un problema usando una computadora

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

La resolución de un problema con una computadora se reduce, pues, a construir un


programa que resuelva el problema planteado.

Pero, ¿qué es un programa informático? Realmente, un programa informático es


semejante, por su función, al programa de una lavadora o de un lavavajillas. Es decir,
es una serie de instrucciones que se ejecutan en una computadora para realizar una serie
de acciones. Más formalmente:

Programa. Secuencia de instrucciones codificadas de una forma determinada y


registradas en un soporte informático. Al ejecutarlo, la computadora realiza una
serie de operaciones preestablecidas para resolver un problema.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Concepto de programa informático

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

El programa MAXMIN-PRIMOS lee un número, NUM, que inicialmente sería a la


vez el menor y el mayor número leído porque no habría otro. Seguidamente, cada vez que
lee un número, comprueba si es el menor o el mayor de todos los números leídos hasta
ese instante. Para ello pregunta si es menor que MENOR, en cuyo caso guarda en MENOR el
valor de NUM, o si es mayor que MAYOR, en cuyo caso guarda en MAYOR el valor de NUM.

Finalizada esta secuencia de operaciones, se tiene en MENOR y en MAYOR los números


menor y mayor leídos hasta el momento.

A continuación comprueba si NUM es primo, para lo cual pregunta si NUM es positivo


y, en caso afirmativo, lo va dividiendo por 2, 3, 4, etc., hasta NUM – 1. Si resulta que no
es divisible por ninguno de ellos, entonces el número es primo y lo escribe.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Si el número no es positivo, el programa no analiza ya si es primo o no y escribe


directamente que no es positivo y pasa a leer el siguiente número.

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.

Supóngase que el programa MAXMIN-PRIMOS trata los siguientes números:


4, – 7 y 13. El proceso de ejecución sería el recogido en el cuadro 1, que tiene cinco
columnas. En la primera columna se mostrarán las operaciones que se están ejecutando
en cada momento. Las tres columnas siguientes (NUM, MENOR, MAYOR) recogen el valor
de estos tres datos durante la ejecución del programa. Finalmente, la última columna
(resultado) muestra las salidas que irá mostrando el programa durante su ejecución.
Hay que señalar, además, que en este cuadro se considera que el mayor número que
puede manejar la computadora es 32.767 y que el menor número que puede repre-
sentar es – 32.768.

Cuadro 1. Ejecución del programa de cálculo de menor, mayor y números primos

Operaciones NUM MENOR MAYOR Resultado

MENOR = mayor posible + 32767

MAYOR = menor posible – 32768

Leer número (NUM = 4) 4

.../...

18 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Concepto de programa informático

Operaciones NUM MENOR MAYOR Resultado

.../...

NUM < MENOR → sí 4

NUM > MAYOR → sí 4

I = 2

NUM divisible por 2 → sí


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Leer un número (NUM = ‒ 7) –7

NUM < MENOR → sí – 7

NUM > 0 → no –7 no es positivo.

Leer un número (NUM = 13) 13

NUM < MENOR → no

NUM > MAYOR → sí 13

NUM > 0 → sí

I = 2

NUM divisible por 2 → no

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

La ejecución anterior del programa MAXMIN-PRIMOS mostraría la siguiente infor-


mación en la pantalla de la computadora, donde el carácter mayor (>) se utiliza para
señalar las entradas recibidas por el programa:

www.udima.es 19

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

En realidad, el programa MAXMIN-PRIMOS descrito anteriormente no podría ser


ejecutado de forma directa por una computadora porque no entiende el castellano. Las
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.

Programar en lenguaje máquina es una tarea impracticable para el ser humano y


por ello se han desarrollado otros lenguajes de programación que ocultan algunos de los
detalles de la computadora y permiten programar de una manera más sencilla, es decir,
más cercana al ser humano que la computadora, y que reciben el nombre de «lenguajes
de alto nivel». Uno de ellos es el lenguaje C++, que será objeto de estudio a partir de la
unidad didáctica 5.

4. EL PSEUDOCÓDIGO

Si el lenguaje utilizado anteriormente no es un lenguaje informático, y dado que


tampoco es castellano, ¿de qué tipo de lenguaje se trata? Este tipo de representación se
denomina «lenguaje de pseudocódigo»:

Lenguaje de pseudocódigo. Mezcla de castellano y expresiones matemáticas que


permite describir de un modo preciso un programa.

Esta representación del programa utilizando pseudocódigo es un paso previo antes


de codificar el programa en un lenguaje de programación. El pseudocódigo es un len-

20 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Concepto de programa informático

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.

4.1. REGLAS GENERALES DEL PSEUDOCÓDIGO

No hay una forma estándar de escribir un programa en pseudocódigo, ya que depende


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

en gran medida del criterio del programador. No obstante, es aconsejable respetar lo más
rigurosamente posible las siguientes pautas de carácter general:

• Todo programa escrito en pseudocódigo comienza con la palabra Inicio


y termina con la palabra Fin.
• Cada instrucción se debe escribir en una línea.
• Para su descripción se utiliza una serie de palabras reservadas, tales como:
Inicio, Fin, Si, Entonces, Si no, Fin_si, Mientras, Fin_mientras,
Seguir, Fin_seguir, que tienen un significado específico.
• Debe escribirse indentado (tabulando o introduciendo espacios) para mos-
trar visualmente las dependencias de unas instrucciones del programa con
respecto a otras.
• Cada una de las estructuras de control que definen un programa (se des-
criben en los epígrafes siguientes) tendrá un punto de comienzo y uno de
fin, especificados por las palabras reservadas que definen la estructura.
• Se escribirá en minúscula, excepto aquellos nombres que elija el progra-
mador, que irán en mayúscula (como NUM, MAYOR, MENOR, etc., del ejemplo
anterior).

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

5. ESTRUCTURAS DE CONTROL

5.1. SECUENCIA

Normalmente, un programa, o una parte del mismo, consiste en una secuencia


de instrucciones que se tienen que ejecutar una detrás de otra para realizar una
operación.

Esto se denomina «estructura secuencial» y se compone de un grupo de acciones


que se han de realizar todas y en el orden en que están escritas, sin posibilidad de omitir
ninguna de ellas.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.

Estas acciones se deben ejecutar en este orden y secuencialmente. El programa en


pseudocódigo sería:

Inicio
Leer A y B
SUMA = A + B
PRODUCTO = A * B
Mostrar SUMA, PRODUCTO
Fin

Se ve que la estructura secuencial expresa perfectamente la solución al problema.

5.2. CONDICIONES

Cuando se está construyendo un programa, es normal tener que seleccionar un con-


junto de instrucciones entre varias posibles, dependiendo de que se cumpla o no una
determinada condición. Esto constituye lo que se denomina «estructura condicional»
de control, y presenta tres variantes: condición simple, condición doble y condición
múltiple.

22 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Concepto de programa informático

5.2.1. Estructura condicional simple

En este tipo de estructura condicional, si la condición se cumple, se ejecuta un con-


junto de acciones, pero si no se cumple, no se realiza ninguna acción y se pasa a la ins-
trucción posterior al fin de la condición.

El pseudocódigo de esta estructura es el siguiente:

...
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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

En el programa MAXMIN-PRIMOS del epígrafe 3 se tienen dos estructuras con-


dicionales simples:

• Una comprueba si NUM es mayor que el número MAYOR:

...
Si NUM > MAYOR
Entonces
MAYOR = NUM
Fin_si
...
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• Otra comprueba si al terminar el recorrido de I se ha llegado a NUM o bien


NUM es 1, en cuyo caso NUM será un número primo:

...
Si I = NUM o NUM = 1
Entonces
Escribir NUM " es primo."
Fin_si
...

5.2.2. Estructura condicional doble

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Concepto de programa informático

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 problema es sencillo: primero se leen los dos números, A y B. Si A es mayor que B,


entonces se visualiza en la pantalla el texto El mayor es: y a continuación el valor de A.
En caso contrario, es decir, si A no es mayor que B, se visualiza el texto El mayor es:
seguido del valor de B.

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.

En el programa MAXMIN-PRIMOS se tienen dos estructuras condicionales dobles:

• Una comprueba si NUM es el menor o el mayor de todos los números leídos:

...
Si NUM < MENOR
Entonces
MENOR = NUM

www.udima.es 25

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Si no
...
Fin_si
...

• La otra comprueba si NUM es un número positivo (antes de comprobar si es


o no un número primo):

...
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      
...

5.2.3. Estructura condicional múltiple

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Concepto de programa informático

El bloque En otro caso es opcional; no es necesario que aparezca en todas las


estructuras condicionales múltiples de un programa. Es útil cuando no se quiere (o no se
puede) recoger todos los posibles valores de una expresión.

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

En primer lugar, se lee el número de la carta y, a continuación, dependiendo del


valor de la variable NUM_CARTA, se mostrará el nombre de la carta si está entre 1 y 12.
En caso contrario, se indicará que la carta no es válida.

Las estructuras condicionales múltiples derivan de las estructuras condicionales dobles


de tipo anidado, es decir, cuando la parte Si no de una estructura condicional doble se trans-
forma en otra estructura condicional.

Así, el ejemplo de estructura condicional doble consistente en seleccionar y visua-


lizar el mayor de dos números dados debería realmente quedar programado como sigue,
teniendo en cuenta que los dos números, A y B, pueden ser iguales:

www.udima.es 27

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

El programa lee dos números, A y B; si A es mayor que B, muestra A como el mayor;


si no, pregunta si A es menor que B y, en caso afirmativo, muestra B como el
mayor. Además, si no se cumple ninguna de las dos condiciones anteriores, entonces el
programa señala que ambos números son iguales.

El programa anterior se puede simplificar si se transforma utilizando una estructura


condicional múltiple. Quedaría como sigue:

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

En este caso, se compara A con B mediante la función Comparación (A, B), que


devuelve como posibles valores 1, – 1 o 0, según sea el resultado de comparar A con B.
Si el resultado de la comparación es igual a 1, quiere decir que A > B; si es – 1, indica
que A < B, y si es 0, señala que A y B son iguales.

28 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Concepto de programa informático

6. ESTRUCTURAS DE CONTROL: REPETICIONES

En un programa, es muy habitual tener que ejecutar repetidamente un conjunto de


instrucciones, dependiendo de que sea cierta o no una condición. La condición se conoce
como «condición de salida» y la estructura de control de este tipo se denomina «repe-
titiva» o «de bucle». Existen tres versiones: estructura de tipo Mientras, estructura de
tipo Hasta y estructura de tipo Para.

6.1. ESTRUCTURA DE TIPO «MIENTRAS»

En este tipo de estructura de control, el bloque de instrucciones (acciones) se repetirá


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

mientras que la condición sea cierta. La condición se evalúa al comienzo de la estructura.


Esto implica que el bloque de instrucciones puede no ejecutarse ninguna vez si la condición
de salida es inicialmente falsa. El pseudocódigo de esta estructura es de la siguiente forma:

...
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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

En primer lugar, se leen los datos de un empleado; a continuación se evalúa la con-


dición de salida (haya_empleado) preguntando si existen empleados. Si la condición es
cierta, porque realmente se han leído los datos de un empleado, entonces se comprueba
con una estructura condicional simple si la edad del empleado es mayor de 55 años; si
lo es, se muestra el nombre del empleado. Después, se vuelve a leer otro empleado y
se retoma la evaluación de la condición de salida del bucle, cuya finalización se rea-
liza cuando no existan más empleados. Obsérvese que si en la primera lectura no hay
empleados, las instrucciones del interior del bucle Mientras no se ejecutan nunca, ya
que se comprueba la condición al principio de la estructura Mientras y, solo si es cierta,
se entra en esas instrucciones.

El programa MAXMIN-PRIMOS tiene dos estructuras repetitivas del tipo


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

• La segunda comprueba si el número leído NUM es primo, preguntando si no


es divisible por algún número comprendido entre 2 y NUM – l:

...
Mientras NUM no sea divisible por I y I < NUM
I = I + 1
Fin_mientras
...

30 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Concepto de programa informático

6.2. ESTRUCTURA DE TIPO «HASTA»

En este tipo de estructura de control, el bloque de acciones se repetirá hasta que la


condición sea cierta. Dicha condición se evalúa al final de la estructura. Esto implica que
el bloque de instrucciones se ejecutará al menos una vez, aunque la condición de salida
ya sea cierta al entrar en dicha estructura.

Esta es la diferencia fundamental entre la estructura Mientras y la estructura Hasta:


en el primer tipo, las acciones del bucle no se realizan nunca si la condición de salida del
mismo es inicialmente falsa. Por el contrario, las acciones del bucle, en el segundo tipo,
se realizarán al menos una vez, ya que la condición se evalúa después de haber sido rea-
lizadas dichas acciones. El pseudocódigo para esta estructura es:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

...
Repetir
Acción 1
Acción 2
...
Acción n
Hasta condición
...

El siguiente programa de ejemplo visualiza la tabla de multiplicar del número 4:

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

6.3. ESTRUCTURA DE TIPO «PARA»

Si el número de repeticiones del bucle (iteraciones) es fijo o se conoce de antemano,


se puede utilizar una estructura de tipo Para, en lugar de una estructura de tipo Mientras.
La estructura Para indica que las acciones del bucle se realizan un número específico de
veces y que la estructura controla automáticamente el número de repeticiones.

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

La evaluación de la condición de salida se realiza al comienzo de cada iteración. El pseu-


docódigo de este tipo de estructura es el siguiente:

...
Para VAR desde VI hasta VF incremento INC
Acción 1
Acción 2
...
Acción n
Fin_para
...

En esta representación, VAR es la variable que actúa de contador; VI es su valor ini-


cial; VF es su valor final, e INC es el incremento. Hay que señalar que, si el incremento
es la unidad, entonces no es necesario especificar el valor de INC.

Por ejemplo, si se desea construir un programa en pseudocódigo que calcule la suma


de los números comprendidos entre 1 y 100, ambos inclusive, se tendría el siguiente
resultado:

Inicio
SUMA = 0
Para NUM desde 1 hasta 100 
SUMA = SUMA + NUM
Fin_para
Mostrar SUMA
Fin

32 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Concepto de programa informático

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.

La estructura Para es similar en esencia a la estructura Mientras, dado que en ambos


casos se comprueba la condición antes de empezar la ejecución del bucle. La diferencia
fundamental radica en que en la estructura Mientras hay que realizar, mediante instruc-
ciones explícitas, la inicialización de la variable que controla el bucle y su incremento;
mientras que en la estructura Para esto se hace automáticamente.

Así, el ejemplo anterior desarrollado con una estructura de tipo Mientras, daría
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

lugar al siguiente código:

Inicio
SUMA = 0
NUM = 1
Mientras NUM <= 100 
SUMA = SUMA + NUM
NUM = NUM + 1
Fin_mientras
Mostrar SUMA
Fin

Obsérvese que en el código anterior hay que incorporar la instrucción de iniciali-


zación de NUM (NUM = 1), y de incremento (NUM = NUM + 1), cosa que no hizo falta en la
estructura Para. Pero recuérdese que la estructura Para solo es aplicable cuando se conoce
a priori el número de repeticiones del bucle, es decir, el valor VF de la variable VAR.

www.udima.es 33

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

ticas que permite describir de un modo preciso un programa.

 ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1

Resolver un problema por computadora significa:

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Concepto de programa informático

c) Un lenguaje informal que permite describir de un modo preciso un programa.


d) Un lenguaje natural como el español o el inglés.

Enunciado 3

No es una estructura básica de control la estructura:

a) Secuencial.
b) Condicional.
c) Tipo Para.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

d) Tipo Según.

Enunciado 4

Una estructura repetitiva:

a) Ejecuta un conjunto de instrucciones dependiendo de una condición.


b) Ejecuta alternativamente un conjunto de instrucciones dependiendo de una
condición.
c) Ejecuta repetidamente un conjunto de instrucciones mientras se verifica una
condición.
d) Ejecuta repetidamente un conjunto de instrucciones por lo menos una vez.

Enunciado 5

Un problema que se debe resolver por computadora tiene varios componentes:

a) El programa y los datos.


b) El algoritmo y el programa.
c) El organigrama, el programa y los datos.
d) El algoritmo y los datos.

www.udima.es 35

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Solución 1

b) Construir un programa.

Solución 2

c) Un lenguaje informal que permite describir de un modo preciso un programa.

Solución 3

d) Tipo Según.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Solución 4

c) Ejecuta repetidamente un conjunto de instrucciones mientras se verifica una


condición.

Solución 5

a) El programa y los datos.

 ACTIVIDADES DE REPASO
Enunciado 1

Desarrollar el pseudocódigo de un programa que calcule el máximo común divisor


(MCD) de dos números, A y B. Para ello, se tendrá en cuenta que si R es el resto de
dividir A/B, entonces se cumple que MCD (A, B) = MCD (B, R). Por lo tanto, para cal-
cular MCD (A, B) se irán calculando los restos sucesivos hasta conseguir uno que sea
igual a cero, en cuyo caso, el resto anterior es el MCD buscado.

36 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Concepto de programa informático

Enunciado 2

Desarrollar el pseudocódigo de un programa que calcule la raíz cuadrada o el cua-


drado de un número N, dependiendo de si es par o impar, respectivamente.

Enunciado 3

Explicar qué operación realiza el programa siguiente sobre el dato leído N:

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Se trata de un programa que calcula el factorial de N (N! = 1 * 2 * 3 * ... * N). Pri-


mero lee el número N; luego comprueba que se puede calcular el factorial (no se puede si el
número es negativo o no es un entero) y, finalmente, calcula el factorial de forma iterativa.

38 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Concepto de programa informático

 REFERENCIAS BIBLIOGRÁFICAS
Básica

Alonso, F. y Segovia, J. Entornos y metodologías de programación en C++. Paraninfo, 1995.

Avanzada

Balcázar, J. L. Programación metódica. McGraw-Hill, 1993.


Dahl, D.; Dijkstra, E. W. y Hoare, C. A. R. Structured programming. Academic Press, 1972.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

«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

Powered by TCPDF (www.tcpdf.org)


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Powered by TCPDF (www.tcpdf.org)


Sumario │

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

2. Diagramas de flujo y ordinogramas


2.1. El diagrama de flujo
2.1.1. Características
2.1.2. Tipos
2.2. El ordinograma
2.2.1. Reglas de diseño
2.2.2. Ordinograma del algoritmo de Euclides
2.2.3. Ordinograma de un número primo mayor que N

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

3.2.2. El bloque condicional, condición o alternativa


3.2.3. El bloque de repetición, bucle o iteración
3.3. Programa estructurado
3.4. Teoremas de la programación estructurada
3.4.1. Teorema de estructura (existencia)
3.4.2. Corolario de arriba abajo (top-down)
3.4.3. Teorema de corrección (o validación)
3.4.4. Teorema de descomposición

4. Diagramas estructurados arborescentes


4.1. Diagrama arborescente del MCD
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

5. Diagramas estructurados de la metodología Nassi-Shneiderman o de Chapin


5.1. Diagrama N-S o de Chapin del MCD
5.2. Ventajas de los diagramas estructurados con respecto a los ordinogramas clásicos

Conceptos básicos
Actividades de autocomprobación
Actividades de repaso
Referencias bibliográficas

42 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

 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

Definido el concepto de programa informático en la unidad didáctica 1, procede


ahora comentar que:

• Un programa informático se describe en lenguaje natural mediante un algo-


ritmo a través de un conjunto de pasos. Dicho algoritmo debe cumplir cinco
requisitos básicos: ser finito, ser definible, recibir datos de entrada, propor-
cionar resultados de salida y ser efectivo.
• Un ordinograma es la representación gráfica de un algoritmo informático
que utiliza en su representación diagramas de flujo.
• La programación estructurada es esencialmente una técnica para construir
programas modulares que sean fáciles de implementar en un lenguaje infor-
mático, fáciles de mantener, y que puedan proporcionar al programador la
capacidad de programar sin errores. Nace como consecuencia de los pro-
blemas que crea la programación clásica con sus programas monolíticos,
poco estructurados, con bifurcaciones incondicionales del tipo GOTO que los
hacen muy difíciles de seguir y de mantener.
• Los diagramas estructurados son las herramientas básicas para diseñar
un programa estructuradamente. Los diagramas son de tres tipos: bloque
secuencial, bloque condicional y bloque de repetición.

Los diagramas estructurados arborescentes, diseñados por Tabourier, y los dise-


ñados por Nassi-Shneiderman y Chapin, con su representación de rectángulos anidados,
son los más ampliamente utilizados.

www.udima.es 43

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

1. ALGORITMO

Se ha descrito en la unidad didáctica anterior que un problema se traduce informá-


ticamente, en un sentido estricto, en un programa de una computadora, y que una forma
simple y precisa de describir un programa es utilizando el «lenguaje de pseudocódigo».
Es decir, el pseudocódigo es una herramienta para describir programas.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Por otra parte, un programa se ha definido como un conjunto de instrucciones codi-


ficadas de una forma determinada que, al ejecutarse en una computadora, realiza una
serie de operaciones que resuelven el problema. El conjunto de instrucciones que define
un programa informático implementa un «algoritmo».

La noción de algoritmo es básica en la programación informática. La palabra «algo-


ritmo» (del latín dixit algorithmus y este, a su vez, del matemático persa al-Jwarizmi)
no presenta un origen muy claro; al parecer, proviene de la palabra «algorismo», cuyo
significado es «el proceso de hacer aritmética usando guarismos arábigos».

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).

El significado moderno de algoritmo es similar al de receta, proceso, método, téc-


nica, procedimiento o rutina.

Algoritmo. Conjunto finito de reglas que crean una serie de operaciones para
resolver un tipo específico de problema.

Un algoritmo lo conforma una lista bien definida, ordenada y finita de operaciones


que permite hallar la solución a un problema. Dado un estado inicial y una entrada, a
través de pasos sucesivos y bien definidos se llega a un estado final y se obtiene una
solución. Los algoritmos son objeto de estudio de la algoritmia, y su definición queda
formalizada por el modelo computacional de la máquina de Turing.

44 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

Su importancia radica en mostrar la manera de llevar a cabo procesos y resolver


mecánicamente problemas matemáticos o de otro tipo. Al igual que las funciones mate-
máticas, los algoritmos reciben una entrada y la transforman en una salida. Se comportan
como una caja negra.

Interesa destacar que el concepto de algoritmo, aunque similar y obviamente rela-


cionado, no debe confundirse con el concepto de programa. Mientras el primero es
la especificación de un conjunto de pasos (operaciones, instrucciones, órdenes, etc.)
orientados a la resolución de un problema, el segundo es ese conjunto de operaciones
especificadas en un determinado lenguaje de programación y susceptible de ser ejecu-
tado (o compilado o interpretado) en una computadora. Un algoritmo, estrictamente
hablando, no puede ejecutarse hasta que se implementa, ya sea en un lenguaje de pro-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

gramación, en un circuito eléctrico, en un aparato mecánico o en algún otro modelo


de computación.

1.1. CARACTERÍSTICAS BÁSICAS

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:

• Debe ser finito. Un algoritmo siempre debe terminar después de un número


finito de pasos.
• Debe ser definible. Cada paso de un algoritmo debe estar precisamente defi-
nido y sin ambigüedades. Es decir, las operaciones que hay que llevar a cabo
deben ser especificadas de manera rigurosa y no ambigua para cada caso.
• Recibir datos de entrada. Un algoritmo tiene cero o más entradas que le
son dadas al inicio o en momentos concretos mientras el algoritmo se eje-
cuta. Es normal que el algoritmo reciba datos del exterior que luego utiliza
y trata.
• Proporciona resultados de salida. Un algoritmo produce uno o varios
resultados en su ejecución que envía al exterior como valores de salida.
Estos resultados son consecuencia de la ejecución del algoritmo y tienen,
normalmente, una relación específica con los datos de entrada.

www.udima.es 45

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

• Debe ser efectivo. Un algoritmo debe resolver el problema de forma rápida


y eficiente. Es decir, se espera que un algoritmo sea efectivo en el sentido
de que todas las operaciones que se deben realizar tienen que ser suficien-
temente básicas como para que en principio puedan ser hechas de manera
rápida, exacta y en un tiempo finito.

Aunque la descripción de Knuth es intuitivamente clara, carece de rigor formal,


puesto que no está exactamente claro qué significa «precisamente definido», «de manera
rigurosa y no ambigua», «suficientemente básicas», y así sucesivamente.

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.

La descripción de un algoritmo usualmente se puede hacer en tres niveles:

• Descripción informal en lenguaje natural. Planteado el problema, se


explica el algoritmo que lo resuelve mediante pasos, descritos en un len-
guaje natural. Se pueden incorporar ilustraciones en su descripción y se
tiende a omitir los detalles.
• Descripción formal. Se usa pseudocódigo o diagramas de flujo para des-
cribir la secuencia de pasos del algoritmo que encuentra la solución.
• Implementación. Se muestra el algoritmo expresado en un lenguaje de
programación específico, codificando cada paso mediante un conjunto de
instrucciones.

En este epígrafe describiremos los algoritmos de modo informal, utilizando el len-


guaje natural.

1.2. ALGORITMO DE EUCLIDES

A continuación presentamos el algoritmo que resuelve el máximo común divisor


(MCD) de dos números utilizando el algoritmo desarrollado por Euclides, por lo que se
denomina también algoritmo de Euclides.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

Para resolver este problema, se puede diseñar un algoritmo con los siguientes pasos:

1. Leer dos números enteros positivos, A y B.


2. Si A o B son negativos o tienen valor 0, escribir mensaje de error: «A o B
no son dos números positivos». Fin del algoritmo.
3. Si B no es menor que A, se intercambia el contenido de ambos: A ↔ B.
4. Calcular el resto, R, de dividir A entre B.
5. Si el resto, R, es igual a 0, entonces escribir que el MCD será el contenido
de B. Fin del algoritmo.
6. Si el resto, R, no es igual a 0, entonces pasar el contenido de B a A, el de R
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

a B, e ir al paso 4.

Así, el MCD de 10 y 4 es 2. Y viene representado por MCD (10, 4) = 2:

• 1.ª iteración: A = 10, B = 4, R = 2;


• 2.ª iteración: A = 4, B = 2, R = 0;
• Resultado: 2.

Y el MCD (11, 3) = 1:

• 1.ª iteración: A = 11, B = 3, R = 2;


• 2.ª iteración: A = 3, B = 2, R = 1;
• 3.ª iteración: A = 2, B = 1, R = 0;
• Resultado: 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:

• Es finito. Acaba cuando los valores de entrada A y B son negativos o cero.


O cuando el resto, R, es cero y se obtiene el MCD en el contenido de B. Es
decir, se resuelve en un tiempo finito.
• Es definible. Cada paso del algoritmo queda perfectamente definido y sin
ambigüedades.
• Recibe datos de entrada. Recibe del exterior el par de números A y B para
los cuales halla su MCD.

www.udima.es 47

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

• Proporciona resultados de salida. El programa proporciona diferentes


resultados de salida, tales como: «A o B no son dos números positivos», si
los datos de entrada son erróneos, y «el MCD es el contenido de B», si los
datos de entrada son correctos.
• Es efectivo. Resuelve el problema de un modo rápido y eficiente, y todas
las operaciones que hay que realizar son básicas.

1.3. ALGORITMOS COMPUTABLES Y NO COMPUTABLES

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:

1. Leer N (número entero y positivo).


2. Asignar a P = N.
3. Asignar a P = P + 1; I = 2; J = P/2.
4. Si I > J, entonces escribir P «es el primer primo mayor que» N. Fin del
algoritmo.
5. Si P no es divisible por I, entonces I = I + 1 e ir al paso 4.
6. Si P es divisible por I, ir al paso 3.

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?

En este caso, el algoritmo que teóricamente lo resuelve será el siguiente:

1. Leer N (número entero y positivo).


2. Asignar a P = N.
3. Asignar a P = P + 1; I = 2; J = (P + 2)/2.

48 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

4. Si I > J, entonces escribir P y P + 2 «son los dos primeros primos gemelos


mayores que» N. Fin del algoritmo.
5. Si P y P + 2 no son divisibles por I, entonces I = I + 1 e ir al paso 4.
6. Si P o P + 2 es divisible por I, ir al paso 3.

Este problema es muy distinto al anterior porque no sabemos si la cantidad de


primos gemelos pares de la forma P, P + 2, ambos primos, es finita o infinita. Si vamos
probando con valores de N y siempre encontramos un par de primos gemelos mayores
que N, no podemos asegurar que esto se verifique para todos los posibles valores de N.
No podemos responder a la pregunta en este caso. Si ante un valor N observamos que
el algoritmo que utilizamos no se detiene, tampoco se puede responder a la pregunta.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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).

2. DIAGRAMAS DE FLUJO Y ORDINOGRAMAS

Como se ha señalado anteriormente, los algoritmos se pueden representar de muchas


maneras: mediante el lenguaje natural, pseudocódigo, diagramas de flujo y lenguajes de
programación, entre otros. Las descripciones en lenguaje natural, que es la que hemos
utilizado en el epígrafe anterior, tienden a ser ambiguas y extensas. El uso de pseudocó-
digo y diagramas de flujo evita las ambigüedades propias del lenguaje natural. Dichas
expresiones son formas más estructuradas para representar algoritmos y se mantienen
independientes de un lenguaje de programación específico.

2.1. EL DIAGRAMA DE FLUJO

Diagrama de flujo. Representación gráfica de un algoritmo o de una secuencia


rutinaria.

www.udima.es 49

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Los diagramas de flujo se basan en la utilización de diversos símbolos para repre-


sentar operaciones específicas. Se les llama así porque los símbolos utilizados se conectan
por medio de flechas para indicar la secuencia de la operación. El diagrama de flujo
representa gráficamente los detalles algorítmicos de un proceso multifactorial. Se utiliza
principalmente en programación, economía y procesos industriales y, a partir de estas
disciplinas, ha pasado a formar parte fundamental de otras, como la psicología cognitiva.

2.1.1. Características

En los diagramas de flujo se presuponen las siguientes características:


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• Existe un punto de inicio del diagrama de flujo.


• Existe siempre un camino que permite llegar a una solución (finalización
del algoritmo).
• Existe, por lo menos, un camino que permite llegar a cualquier punto del
diagrama de flujo.

Para ello, es importante que se observen las siguientes recomendaciones a la hora


de construir los diagramas de flujo:

• Evitar sumideros infinitos, burbujas que tienen entradas pero no salidas.


• Evitar las burbujas de generación espontánea, que tienen salidas sin tener
entradas, porque son sumamente sospechosas y generalmente incorrectas.
• Evitar flujos y procesos no etiquetados. Esto suele ser un indicio de una falta
de atención por parte del diseñador del diagrama, porque se le ha olvidado
etiquetarlo. Aunque, a veces, esconde un error más grave, como que el flujo
o proceso no corresponda a ninguna acción del diagrama de flujo.

Por otra parte, los diagramas de flujo presentan las siguientes ventajas:

• Favorecen la comprensión del algoritmo y, por lo tanto, la resolución plan-


teada para el problema, al mostrarlo de forma gráfica. Un buen diagrama
de flujo reemplaza varias páginas de texto.
• Permiten identificar los problemas y las posibilidades de mejorar el proceso
de resolución. Se identifican los pasos redundantes, los flujos de retroali-
mentación, los cuellos de botella y los puntos de decisión.

50 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

2.1.2. Tipos

Los diagramas de flujo se pueden representar en diferentes formatos, tales como:

• Formato vertical. El flujo o la secuencia de las operaciones va de arriba


hacia abajo. Es una lista ordenada de las operaciones de un proceso con toda
la información que se considera necesaria, según su propósito.
• Formato horizontal. El flujo o la secuencia de las operaciones va de
izquierda a derecha.
• Formato panorámico. El proceso entero está representado en una sola hoja,
por lo que puede apreciarse de un solo vistazo y de modo más rápido que
leyendo el texto, lo que facilita su comprensión. Registra no solo en línea ver-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

tical, sino también horizontal, distintas acciones simultáneas y la participación


de más de un puesto o departamento que el formato vertical no registra.
• Formato arquitectónico. Describe el itinerario de ruta de un elemento
sobre el plano arquitectónico del área de trabajo.

2.2. EL ORDINOGRAMA

En ciencias de la computación, al diagrama de flujo se le denomina «ordinograma».

Ordinograma. Muestra la secuencia lógica y detallada de las operaciones que se


necesitan para la realización de un programa.

Todo ordinograma debe estar compuesto por:

• Un símbolo de inicio de ejecución del programa.


• La secuencia de operaciones necesarias para el correcto funcionamiento del
programa. Las operaciones seguirán un orden (de arriba abajo y de izquierda
a derecha).
• Un símbolo que indique el final del programa.

Los símbolos de ordinograma están normalizados. En concreto, en España están nor-


malizados por la norma UNE 71-001 de AENOR (Asociación Española de Normaliza-
ción y Certificación). Los símbolos más utilizados son los que se indican en el cuadro 1.

www.udima.es 51

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Cuadro 1. Símbolos de ordinograma de la norma UNE 71-001

Símbolos utilizados Descripción

Comienzo, fin, interrupción. Representa una etapa en el ordinograma.

Entrada/salida de información.

Proceso o tratamiento. Representa la ejecución de una operación que tenga


como resultado una modificación en el valor, en la forma o en la situación de
una información.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Predicado. Representa una operación de decisión o bifurcación que determina


la alternativa que hay que seguir entre varias posibles.

Conector. Conecta diferentes partes del ordinograma, especificando una salida


o una entrada a otra parte del ordinograma.

Proceso predefinido. Se utiliza para realizar una llamada a un módulo del


programa. Ejemplo: un procedimiento o subrutina.

Entrada manual. Indica la entrada de información manual desde un disposi-


tivo periférico. Ejemplo: un teclado.

Salida en documento impreso. Indica la salida de resultados impresos a un


periférico. Ejemplo: una impresora.

Pantalla de la computadora o de otro dispositivo externo.

Almacenamiento en acceso directo. Ejemplo: un disco magnético.

Conector de una página del ordinograma a otra.

52 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

2.2.1. Reglas de diseño

A la hora de diseñar un ordinograma, es importante seguir las siguientes reglas:

• Debe existir un inicio y un fin, que se representan por el símbolo terminal.


• La secuencia se indica mediante flechas y conectores a la misma u otra
página.
• El orden es de arriba abajo y de izquierda a derecha.
• Se aconseja un símbolo por acción aunque, si las acciones son simples,
puede haber varios.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• Dentro de los símbolos no se pondrán instrucciones propias de un lenguaje


para que la representación gráfica sea independiente de cualquier lenguaje.
• A todos los símbolos, excepto al de inicio, fin y conectores, llega una y solo
una línea, y solo puede salir una de él.
• Tanto las conexiones de entrada como las de salida deben estar etiquetadas
para aclarar el enlace.
• Todos los símbolos utilizados deben estar unidos por líneas de flujo.
• No se pueden cruzar las líneas de flujo.
• Al símbolo de inicio no puede llegarle ninguna línea de flujo y del símbolo
de fin no puede salir ninguna línea de flujo.

2.2.2. Ordinograma del algoritmo de Euclides

En la figura 1 presentamos el ordinograma del algoritmo de Euclides, anteriormen-


te descrito en lenguaje natural. Como vemos, el seguimiento del ordinograma es mucho
más sencillo, formal y preciso que hacerlo en lenguaje natural.

2.2.3. Ordinograma de un número primo mayor que N

El ordinograma de la figura 2 describe el proceso de obtener el primer número primo


mayor que un número positivo dado N. El ordinograma presenta de forma gráfica el algo-
ritmo descrito en lenguaje natural anteriormente.

www.udima.es 53

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Figura 1. Ordinograma del MCD

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


B>A A↔B

R ← A mod B

no
A←B
R=0
B←R

El MCD es B

Fin

54 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

Figura 2. Número primo mayor que N

Inicio

Leer N


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


I←I+1 P es el 1.er primo
I>J Fin
mayor que N

no

no
P mod I = 0

3. LA PROGRAMACIÓN ESTRUCTURADA

Las técnicas de desarrollo y diseño de programas informáticos mediante ordino-


gramas, que son los que se utilizan en la programación convencional, tienen grandes

www.udima.es 55

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

inconvenientes, sobre todo a la hora de verificar y modificar un programa. En la progra-


mación informática tienen gran importancia las técnicas de programación, cuyo objetivo
es el de facilitar la comprensión del programa y permitir, de forma rápida, las amplia-
ciones y modificaciones que surjan en la fase de explotación del ciclo de vida de un pro-
grama o una aplicación informática.

En la programación convencional se suele hacer un uso indiscriminado y sin con-


trol de las instrucciones de salto condicional e incondicional, lo cual produce cierta
complejidad en la lectura y en las modificaciones de un programa. Eliminar estas
dificultades es uno de los propósitos de la programación estructurada y, por ello, en
ocasiones se ha definido como la técnica de programación sin saltos condicionales e
incondicionales.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Los fundamentos de la programación estructurada se forjaron en los años sesenta


por Edsger W. Dijkstra en sus Notes on Structured Programming. Se basa en el deno-
minado «teorema de la estructura», desarrollado en 1966 por Böhm y Jacopini, que se
ratificó con los trabajos de Harlan D. Mills. Dijkstra y otros autores propusieron el uso
de un conjunto de construcciones lógicas, denominadas diagramas estructurados o dia-
gramas privilegiados (que comentaremos más adelante), con las que podría formarse
cualquier programa. Cada construcción tenía una estructura lógica predecible, se entraba
por el principio de la estructura y se salía por el final, y facilitaba al lector el seguimiento
del flujo procedimental.

La programación estructurada es esencialmente una técnica para construir los


esquemas de encadenamiento de las sentencias del programa de un modo lógico. Se
intenta con ella:

• Obtener una programación de «arriba abajo» (top-down) según una descom-


posición arborescente que permita el fraccionamiento de los programas en
módulos o segmentos que sean de fácil seguimiento (a ser posible, que cada
uno no ocupe más de un par de páginas de listado de ordenador).
• Facilitar el mantenimiento de los programas, al permitir modificar un
«subárbol» del esquema general sin necesidad de tocar el que está encima
de él o a su lado.
• Dar a los programas una estructura suficientemente fuerte para que los ordi-
nogramas no sean tan fundamentales como en la programación clásica.
• Proporcionar a los programadores la capacidad de programar sin errores y
la convicción de que son efectivamente capaces de ello.

56 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

3.1. DIAGRAMAS Y PROGRAMA PROPIO

La programación estructurada utiliza los tres símbolos de ordinograma (que denomi-


naremos a partir de ahora «diagramas») que se citan a continuación:

• Tratamiento o procedimiento puro Figura 3. Diagramas propios


(figura 3 a). Sirve para representar
una sentencia de asignación, una a)
secuencia de sentencias, la llamada
a un subprograma o una parte de un
programa que no tiene nada más que f
una entrada o una salida. E S
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Desde el punto de vista abstracto, f es


una función que efectúa una modifi- b)
cación de los datos de entrada.
S
• Predicado o condición, o expre-
sión booleana o test p (figura 3 b). E
Sirve para representar una alternativa p
dependiente del valor (verdadero o
falso) del dato de entrada y, según el S
caso, toma una de ambas salidas.
• Reagrupamiento. Este diagrama se c)
utiliza para unir, en una sola, diversas
salidas de tratamientos y/o predicados
E
(figura 3 c). S

El diseño de un programa estructurado se fun- E


damenta en los conceptos de diagrama propio y
programa propio.

Diagrama propio. Aquel que posee un solo punto de entrada y uno de salida.
Programa propio. Aquel que cumple las siguientes condiciones:

• Posee un solo inicio y un solo fin; es decir, es un diagrama propio.


• Todo elemento del programa es accesible; es decir, existe al menos un camino
desde el inicio al fin que pasa a través de todos los diagramas que lo componen.
• No posee bucles infinitos.

www.udima.es 57

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Por ejemplo, el diagrama de la figura 4 no es un diagrama propio ni un programa


propio por dos razones: tiene dos salidas y no todos los diagramas tienen un camino
hacia la salida.

Figura 4. Programa no propio


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

58 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

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.

Figura 5. Programa del MCD

AyB
Leer
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

AoB
B>A

<= 0


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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

3.2. DIAGRAMAS ESTRUCTURADOS O DIAGRAMAS PRIVILEGIADOS

Reciben el nombre de diagramas estructurados o privilegiados tres «conjuntos de


diagramas» que destacan por ser de empleo muy frecuente y porque permiten ellos solos
programar estructuradamente cualquier tipo de programa. Son: la secuencia, la condi-
ción y la repetición.

3.2.1. El bloque secuencial, secuencia o encadenamiento

Define un conjunto de tratamientos en secuencia que pueden ser varias sentencias


simples o varios diagramas más complejos.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Se representa, para una serie de tratamientos en secuencia, como indica la figura 6.


Equivale a: BLOCK (f1, f2, ..., fn) o BLOCK [n] (f1, f2, ..., fn), para una serie de
tratamientos f1, f2, ..., fn.

Interesa señalar que: BLOCK [n] (f1, f2, ..., fn) = BLOCK (BLOCK [n-l]) (f1


, f2, ..., fn -l, fn); teniendo en cuenta que BLOCK [1] (f1) = f1.

Este diagrama privilegiado se suele representar en los lenguajes de programación


por una serie de sentencias comprendidas entre un BEGIN y un END (bloque BEGIN) como
en Pascal, o entre { y } como en C/C++.

Figura 6. Secuencia de n tratamientos

fi f2 fn

3.2.2. El bloque condicional, condición o alternativa

Define un predicado p en la entrada, dos tratamientos, f y g, y un agrupamiento para


la salida. Se representa por los diagramas de la figura 7 a) (Si p es cierto, ejecutar f; si
no, ejecutar g) que corresponden literalmente a un IFTHENELSE (p, f, g).

60 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

• Variante IFTHEN. Este bloque condicional define un predicado, p, un solo


tratamiento f y un agrupamiento. Se representa por el conjunto de diagramas
de la figura 7 b) (Si p es cierto, ejecutar f ), que corresponde literalmente a:
IFTHEN (p, f).
• Variante CASE OF. Este bloque generaliza el IFTHENELSE. Dispone de una
ramificación de alternativas después del predicado p, seguido a la salida de
un reagrupamiento automático. Se representa por el diagrama de la figura 7 c)
(Si p = a, ejecutar fa; si p = b, ejecutar fb, etc.), que corresponde literalmente
a CASE OF (p, fa, fb, ..., fn).

Figura 7. Bloque condicional


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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; 

Ejemplo (en C/C++):


switch (p) {
case a: fa; break;
case b: fb; break;
...
default: ...; }
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

3.2.3. El bloque de repetición, bucle o iteración

Define un predicado, p, un tratamiento, f (que se ejecuta repetidas veces dependien-


do del valor del predicado), y un reagrupamiento en la entrada. Se representa por los
diagramas de la figura 8 a) (mientras p sea cierto, ejecutar f ), que corresponden literal-
mente a un DOWHILE (p, f).

• 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).

El bloque de repetición corresponde, en los lenguajes de programación, a senten-


cias tales como:

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

Figura 8. Bloque de repetición

a) DOWHILE b) DOUNTIL

falso
cierto
f

f p
p

c) CASE OF


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Vc ← Vi Vc > Vf f Vc ← Vc + k
no

Debido a su amplia utilización, y aunque no es un diagrama privilegiado, vamos


a describir un nuevo bloque: el DOFOR. El bloque DOFOR es la combinación de los dia-
gramas privilegiados Secuencia y DOWHILE . Se representa por los diagramas de la
figura 8 c), siendo:

Vc = variable de control.
Vi = valor inicial.
Vf = valor final.
k = incremento de la variable de control.
f = tratamiento.

Y corresponde literalmente a un: DOFOR (p, f).

El bloque DOFOR corresponde, en los lenguajes de programación, a sentencias tales


como:

DOFOR (p, f) → DO <eti> Vc = Vi, Vf, k
(Instrucciones)  }    (en Fortran)
<eti> CONTINUE

www.udima.es 63

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

3.3. PROGRAMA ESTRUCTURADO

Dada la familia E de diagramas privilegiados definidos en el epígrafe anterior,


E = (BLOCK, IFTHEN, IFTHENELSE, CASEOF, DOWHILE, DOUNTIL), se dice que un pro-
grama propio está estructurado según E, o simplemente, está estructurado, si se puede
representar exclusivamente con los diagramas de E. Cuando esta estructura existe, se
obtiene automáticamente una descomposición funcional representable por cada una de
las estructuras de los diagramas. En la figura 9 se presenta el programa estructurado del
MCD, que corresponde literalmente a:

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))].

En un programa estructurado, los diagramas se van ejecutando secuencialmente uno


detrás del otro, lo que quiere decir que no está permitido el retorno a un diagrama privi-
legiado ya ejecutado. Por ejemplo, en el caso del MCD, el diagrama DOWHILE no puede
utilizar el tratamiento anterior R ← A mod B, por lo que debe repetirse dicho tratamiento.
Por ello, un programa escrito siguiendo la metodología de la programación estructurada
exige más código que si se codifica mediante la programación convencional.

Figura 9. Programa estructurado del MCD

sí Escribir
AoB
no > 0

Leer AoB R←A A←B


AyB <= 0 mod B B←R

R←A no Escribir
R≠0
mod B MCD es B


IFTHEN B>A A←B DOWHILE

64 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

Programar de forma estructurada consiste esencialmente en analizar el problema


como si el lenguaje de programación no dispusiera de la orden GOTO. Es la idea de pro-
gramar «sin GOTO». Para ello, es preciso que el lenguaje disponga de las sentencias que
definen los diagramas privilegiados; en caso contrario, como en Assembler, no habrá
más remedio que utilizar el GOTO.

La programación estructurada no es propiamente un método; es, ante todo, una


disciplina, un estado de espíritu y una guía:

• Una disciplina, que hace que se considere incongruente la utilización de


sentencias GOTO o similares, salvo si se emplean para simular los compo-
nentes estructurados en los lenguajes que no disponen de esas sentencias.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• Un estado de espíritu, que obliga a analizar el problema de «arriba abajo»,


en una descomposición progresiva en elementos más simples.
• Una guía que orienta cuáles son las elecciones posibles de las diversas des-
composiciones y cuáles son los límites de esas elecciones. Por supuesto, la
personalidad del programador influirá en la elección.

3.4. TEOREMAS DE LA PROGRAMACIÓN ESTRUCTURADA

Seguidamente se presentan los cuatro teoremas en los que se basa la programación


estructurada.

3.4.1. Teorema de estructura (existencia)

Todo programa propio es equivalente a un programa en el que todas sus ramas


resultan únicamente del empleo de diagramas de los tipos BLOCK, IFTHENELSE y DOWHILE
(y/o DOUNTIL).

Este teorema significa que todo lo que se puede programar se puede poner bajo la
forma estructurada.

3.4.2. Corolario de arriba abajo (top-down)

Todo programa propio es equivalente a un diagrama de una de las siguientes formas:


BLOCK (f, g); IFTHENELSE (p, f, g); DOWHILE (p, f) y/o DOUNTIL (f, g).

www.udima.es 65

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Donde:

p = un predicado del programa original.


f y g = programas más reducidos, o subprogramas a los que se referencia
desde el programa original.

3.4.3. Teorema de corrección (o validación)

La validación de un programa estructurado se puede efectuar por pasos sucesivos,


examinando cada nodo de su estructura y probando localmente la validación de la des-
composición funcional realizada. Como es obvio, las pruebas de un nodo implican las
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

de sus descendientes directos en el árbol de descomposición; es decir, todo el subárbol


cuya cabeza es ese nodo.

3.4.4. Teorema de descomposición

La descomposición de una función k (en BLOCK, IFTHENELSE o DOWHILE) obedece


a las reglas siguientes:

• Descomposición de k = BLOCK (f, g):

– Sea f una función definida en todo el intervalo donde k está definida.


– Si, para dos datos diferentes, k da resultados diferentes, lo mismo
ocurre para f.
– No hay otra condición sobre f, pero una vez elegida f, las especifica-
ciones funcionales de g quedan determinadas.

• Descomposición de k = IFTHENELSE (p, f, g):

– p está definido en todo el intervalo donde k está definida.


– No hay otra condición sobre p, pero una vez elegido el predicado, las
especificaciones funcionales de f y g quedan determinadas.

• 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

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

– Si se cumple la condición anterior, la descomposición de k en DOWHILE


es siempre posible.
– f es una función que, al aplicar sus propios resultados de manera repe-
tida, ejecuta la función p para todos los datos.
– Una vez elegida f, p queda determinado.

Este teorema es el útil que nos sirve para guiar la descomposición funcional; es
decir, la programación.

El teorema de estructura es el garante de que se podrá realizar la descomposición


hasta el final, y el teorema de corrección indica que la validación se puede realizar a
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

medida que avanza el trabajo.

4. DIAGRAMAS ESTRUCTURADOS ARBORESCENTES

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.

La lectura del árbol se realiza de arriba abajo y de izquierda a derecha. Es decir, se


lee la raíz; a continuación, el subárbol izquierdo y subárboles sucesivos, y por último, el
subárbol derecho. Cada subárbol se recorre hasta llegar a los nodos terminales del árbol.

Los símbolos que utiliza básicamente son dos: el rectángulo y el rombo.

La figura 10 representa el bloque secuencial en formato arborescente. Se representa


con el nodo BLOCK que ejecuta secuencialmente los tratamientos f1, f2, ..., fn.

La figura 11 representa el bloque condicional IFTHENELSE en formato arborescente


(si p es cierto, ejecutar f; si no g), con sus dos variantes IFTHEN (si p es cierto, ejecutar
f) y CASE OF (si p = a ejecutar fa; si p = b, ejecutar fb, etc.).

La figura 12 representa el bloque de repetición DOWHILE en formato arborescente


(mientras p sea cierto, ejecutar f), con sus dos variantes: DOUNTIL (ejecutar f hasta que p
sea cierto) y DOFOR (dada la variable de control, Vc, con un valor inicial, Vi, y un valor

www.udima.es 67

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

final, Vf; y dado un incremento k de la variable de control en que se incrementa en cada


iteración: Vc + k, Vc + 2 k, ..., se produce un proceso repetitivo del cálculo de f hasta
que el valor de Vc > Vf). Como se ha señalado anteriormente, este diagrama no repre-
senta un proceso puro de repetición, ya que es una combinación de la secuencia y del
bloque DOWHILE.

Figura 10. Bloque secuencial arborescente

BLOCK
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

f1 f2 ... fn

Figura 11. Bloque condicional arborescente

IFTHENELSE IFTHEN CASE OF

=n
=a

p f g p f p fa ... fn

Figura 12. Bloque de repetición arborescente

DOWHILE DOUNTIL DOFOR

p f f p
Vc = Vi, k, Vf f

68 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

4.1. DIAGRAMA ARBORESCENTE DEL MCD

El ejemplo del MCD que se presenta en la figura 13, en la representación arbores-


cente, es un algoritmo general que sirve para hallar el MCD de parejas de números hasta
detectar un fin de fichero (fin de los datos).

Figura 13. Diagrama arborescente del MCD

MCD

DOWHILE
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Trata dos datos


No EOF
BLOCK

Leer A y B
IFTHENELSE

Escribir "Error
AoB
datos de
<=0 BLOCK
entrada A, B"

Escribir
IFTHEN DOWHILE
R ← A mod B "MCD: " B

B>A B↔A B←A


R≠0 R←B
R ← A mod B

Todo el programa es un bloque de repetición DOWHILE, cuyo tratamiento, f, es


un BLOCK con un tratamiento «Leer A y B» y un bloque condicional IFTHENELSE. Si
el predicado p «A o B son <= 0» se verifica, entonces se escribe un mensaje de error:
«Error datos de entrada A, B». En caso contrario, se ejecuta otro BLOCK con cuatro
procesos:

• Un bloque condicional IFTHEN que intercambia el contenido de A con B si


B > A.
• Un tratamiento que calcula en R el resto de dividir A con B.

www.udima.es 69

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

• Un bloque de repetición DOWHILE que se ejecuta mientras el resto R sea


diferente de 0.
• Un tratamiento que escribe el MCD: «Escribir MCD contenido de B».

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

El método de programación estructurada desarrollado por Nassi y Shneiderman y


perfeccionado por Ned Chapin viene descrito en el artículo de Chapin «A New Format
for Flowcharts».

Más que una nueva metodología estructurada de programación, lo que representa


es una nueva forma de representar los diagramas estructurados (denominados aquí como
«organigramas N-S o diagramas de Chapin»). Este método no facilita, de entrada, la
tarea del programador; de hecho, le pide una mayor comprensión. Pero una vez pasada
esta barrera, los beneficios que se obtienen en la depuración, documentación y manteni-
miento de los programas compensan con creces este esfuerzo inicial.

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.

A continuación se describen los diagramas estructurados según la modalidad de


Chapin:

• El bloque secuencial es un rectán- Figura 14. Bloque secuencial con


gulo que se puede emplear para repre- dos tratamientos, f y g
sentar una sentencia de asignación o
de entrada-salida, así como la llamada
f
a un subprograma. Se pueden añadir
características para distinguir entre sí
g
las tres sentencias mencionadas. La
más importante es quizá la llamada a

70 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

un procedimiento, para lo que se coloca una elipse interior en el rectángulo


con el nombre del procedimiento llamado.
La secuencia de ejecución va siempre de arriba hacia abajo; no hacen falta
flechas descendentes; por ejemplo, en la figura 14 se tienen dos tratamientos
que hay que ejecutar, f y g, en el orden indicado (en los ordinogramas clá-
sicos estarían unidos por flechas verticales hacia abajo).

• El bloque condicional IFTHENELSE se Figura 15. Bloque condicional


representa como se indica en la figura
15 a) y se le llama también símbolo a)
de decisión, en el que los triángulos
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

OF se representa con el bloque de la Parte


Then
figura 15 c), en el que los tratamientos
a la izquierda del vértice del triángulo c)
son las posibles salidas según el valor
1
de la variable de control y el bloque p
2
de la derecha es la salida por defecto. 3 o
f1 t
En el caso de la figura 15 c), si p = 1, f2 f3 r
o
2 o 3, se ejecuta respectivamente f1,
f2 o f3, y si p tiene otro valor, se eje-
cuta el tratamiento otro.
La estructura formada por bloques Figura 16. Bloque secuencial ani-
IFTHENELSE anidados resalta muy dado
claramente las diferentes posibili-
dades lógicas existentes. Por ejemplo,
en la figura 16, el tratamiento f 1 se T p F

ejecuta si p es cierto; el tratamiento f2, f1


T
p1
F
si p y p2 son ciertos; el tratamiento f3, p2
T F
si p es cierto y p2 es falso; el trata- f4 f5
f2 f3
miento f4, si p es falso y p1 es cierto; y
el tratamiento f 5, si p y p1 son falsos.

www.udima.es 71

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

• El bloque de repetición DOWHILE se representa gráficamente como indica la


figura 17 a).
El cuerpo f puede contener a su vez varias sentencias, así como otros blo-
ques DOWHILE. La variante DOUNTIL tiene en el diagrama N-S un grafismo
similar al del bloque DOWHILE; se representa mediante la figura 17 b). Mien-
tras que la variante DOFOR se representa con el mismo esquema de represen-
tación que para el bloque DOWHILE, se diferencia en que se escribe su ley o
progresión aritmética (Vc = Vi, k, Vf), en vez del predicado p.

Figura 17. Bloque de repetición


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

a) b) c)

p Vc = Vi, k, Vf
f
f f
p

5.1. DIAGRAMA N-S O DE CHAPIN DEL MCD

Se describe en la figura 18 el dia- Figura 18. Diagrama N-S/Chapin del MCD


grama estructurado del MCD utilizando
las representaciones N-S o de Chapin.
Programa MCD
El estudio que se ha efectuado de
este ejemplo en diferentes modalidades No Fin Datos
de programación (clásica con el ordino- Leer A y B
grama y estructurada con los diagramas AyB>0
T F
estructurados) y aplicando diferentes
B>A
metodologías estructuradas como la T F

arborescente de Tabourier o la de N-S/ A↔B


Escribir
Chapin nos ha de permitir comparar la R ← A mod B ("Error
datos:"
mayor o menor eficiencia de cada una R≠0 A, B)
A ← B; B ← R;
de ellas. R ← A mod B
Escribir ("MCD", B)

72 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

5.2. V
 ENTAJAS DE LOS DIAGRAMAS ESTRUCTURADOS CON RES-
PECTO A LOS ORDINOGRAMAS CLÁSICOS

Además de todas las ventajas señaladas anteriormente de la programación estruc-


turada con relación a la programación clásica, interesa destacar que la construcción de
un diagrama estructurado nos ayuda a ver (mejor que con los ordinogramas clásicos) la
estructura y el enlace entre los módulos. Además, como no es fácil introducir muchos
símbolos en una página (y no hay conectores de página), se consiguen programas o pro-
cedimientos cortos (que es uno de los objetivos de la metodología estructurada). Pero
si el programa o módulo resultara extenso, es más fácil, a la vista del diagrama, aislar
un trozo bastante grande para tomarlo como un subprograma independiente, e incluso
se facilita conseguir que la parte que se separa responda a un aspecto funcional claro
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

• Programación estructurada. Técnica para construir programas modulares


y sin bifurcaciones incondicionales del tipo GOTO, de modo que sean fáciles
de implementar en un lenguaje informático, de seguir y de mantener.
• Diagramas estructurados. Instrumentos básicos para diseñar un programa
estructuradamente. Son tres: el bloque secuencial (BLOCK), el bloque condi-
cional (IFTHENELSE, IFTHEN, CASE OF) y el bloque de repetición (DOWHILE,
DOUNTIL, DOFOR).
• Diagramas arborescentes y N-S o de Chapin. Son dos tipos de diagramas
estructurados de amplio uso. Los arborescentes están basados en el método
de la programación estructurada de Tabourier. Los diagramas N-S/Chapin
están basados en el método de la programación estructurada de Nassi-
Shneiderman y de Chapin.

 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

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

Enunciado 2

Escribir el algoritmo que resuelve una ecuación de segundo grado:

Ax2 + Bx + C = 0

Enunciado 3

Diseñar el diagrama estructurado N-S/Chapin que resuelva el problema de si una


palabra de menos de nueve caracteres es o no palíndroma; es decir, que de izquierda a
derecha y de derecha a izquierda se lee igual.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Enunciado 4

Construir estructuradamente, utilizando los diagramas arborescentes, un «cuadro


mágico de orden impar». Para ello, se disponen en una matriz cuadrada de orden N impar
los números enteros naturales de 1 a N2. La matriz constituye un cuadro mágico cuando
se obtengan las mismas sumas sobre las filas, las columnas y las diagonales principales.

Enunciado 5

Diseñar el diagrama estructurado N-S/Chapin que resuelva el problema de los nú-


meros amigos. Dos números son «amigos» si cada uno de ellos es igual a la suma de
los divisores del otro. Se trata de diseñar estructuradamente utilizando la representación
N-S/Chapin un programa que determine si dos números son amigos. Para lo cual, se
leerá un fichero de entrada con una colección de números y se comprobará si dos a dos
son o no amigos.

Por ejemplo, los números 220 y 284 son amigos porque:

• Suma de divisores de

220 = 1 + 2 + 4 + 5 + 10 + 11 + 20 + 22 + 44 + 55 + 110 = 284.

• Suma de divisores de

284 = 1 + 2 + 4 + 71 + 142 = 220.

www.udima.es 75

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Solución 1
Un número primo P mayor que N

Primo > que N


BLOCK

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

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;

Pal[I] ≠ " " and S = 0

I=I+1

I>9
T F

Escribir "error: palabra > 8 caracteres"; Leer(C); Pal[I] = C


S=1

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

Se procede como sigue:

a) Se coloca el número 1 en medio de la primera fila.


b) Para colocar los siguientes números, pasar a la fila anterior y a la columna
siguiente, entendiéndose que la fila anterior a la primera es la última, y que
la columna siguiente de la última de la derecha es la primera de la izquierda.

www.udima.es 77

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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]

Cuadrado j←j+1 i←i+2 IFTHEN


j= [i, j] ← k
Ocupado j←j–1
1, 1, n Ocupado
[i, j] ← false IFTHEN
[i, j] ← true IFTHEN
i←i–1 i>n i←1
IFTHEN

i=0 i←n j>n j←1

j <= 0 j←n

Solución 5

Los pasos previstos son:

a) Se leen dos números, N1 y N2, y se calcula si son amigos. Este proceso se


repite hasta detectar un fin de fichero (EOF).
b) Para ver si dos números son amigos, se determinan los divisores de N1 y
se acumulan en la variable D1. Si D1 es igual a N2, hay posibilidad de que
sean amigos.

78 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

c) Entonces se calculan los divisores de N2 y se acumulan en la variable D2.


Si D2 es igual a N1, entonces son amigos.

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

2. La función de Ackermann está definida por:

A (m, n) = A (m – 1, A (m, n – 1)), para m, n > 0


A (0, n) = n + 1
A (m, 0) = A (m – 1, 1), para m > 0

Se pide diseñar el diagrama estructurado N-S/Chapin que resuelva el


problema.

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

Aciertos: 1 exacto, 2 aproximados 1 exacto, 3 aproximados

Se trata de diseñar estructuradamente un diagrama arborescente que resuelva


este problema.

4. Caminos hamiltonianos. Se denominan caminos hamiltonianos aquellos que


contienen exactamente una vez todos y cada uno de los vértices del grafo.
Por ejemplo, el grafo de la figura a) tiene dos caminos hamiltonianos, mien-
tras que el grafo de la figura b) no tiene ninguno.
Se trata de diseñar un diagrama estructurado N-S/Chapin que lea diversos
grafos uno tras otro e indique para cada grafo todos sus caminos hamilto-
nianos, si los hay.

80 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano Algoritmos y sistemas de representación de un programa

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

5. El juego de la vida. Se trata de simular la evolución de unos organismos


hipotéticos, que viven sobre una cuadrícula, de modo que en cada casilla
solo puede haber un organismo. Dos organismos se consideran vecinos
si sus casillas son contiguas en sentido horizontal, vertical o diagonal. La
simulación se hará calculando cada generación a partir de la anterior con
las siguientes reglas:

• Un organismo sobrevive solo si tiene exactamente dos o tres vecinos;


en caso contrario, muere.
• En una casilla vacía nace un nuevo organismo si dicha casilla tiene
al menos tres organismos vecinos.

Se trata de diseñar un diagrama estructurado arborescente o N-S/Chapin


que lea una matriz inicial de 12 * 12 elementos con una serie de organismos
vivos y que proporcione la matriz final del juego de la vida al alcanzar una
situación estable o al completarse un número máximo de 50 generaciones.

 REFERENCIAS BIBLIOGRÁFICAS
Básica

«Algorithm». Wikipedia. Disponible en <http://en.wikipedia.org/wiki/Algorithm>.


Alonso Amo, F. y Morales Lozano, Á. Problemas de programación. Madrid: Paraninfo, 1989.

www.udima.es 81

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Álvarez, S. «Ordinogramas», 12 de enero de 2007. Disponible en <http://www.desarrolloweb.com/articulos/


ordinogramas.html>.
Chapin, N. «Flowcharting with the ANSI Standard: A Tutorial». ACM Computing Surveys, 1989, vol. 2,
núm. 2, pp. 119-146.
Dijkstra, E. W. A Discipline of Programming. Prentice-Hall, 1975.
Knuth, D. E. Algoritmos fundamentales. Reverte, 1980.
— The Art of Computer Programming, vols. 1-3. Addison-Wesley, 1998.
«Nassi-Shneiderman diagram». Wikipedia. Disponible en <http://en.wikipedia.org/wiki/Nassi-Shneiderman_
diagram>.
Nassi, I. y Shneiderman, B. «Flowchart Techniques for Structured Programming». SIGPLAN Notices, núm. 12,
1973.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Shneiderman, B. «A Short History of Structured Flowcharts (Nassi-Shneiderman Diagrams)», 2003. Dis-


ponible en <http://www.cs.umd.edu/hcil/members/bshneiderman/nsd/>.
«Structured_programming». Wikipedia. Disponible en <http://en.wikipedia.org/wiki/Structured_progra
mming>.
«Structured programming». Disponible en <http://www.c2.com/cgi/wiki?StructuredProgramming>.
Tabourier, Y.; Rochfeld, A. y Frank, C. La programmation structurée en informatique. París: Éditions
d'organisation, 1975.

Avanzada

Brassard, G. y Bratley, T. Fundamentos de algoritmia. Prentice-Hall, 1997.


Dahl, O. J.; Dijkstra, E. W. y Hoare, C. A. R. Structured Programming. Academic Press, 1972.
Galve, J. et al. Algorítmica: diseño y análisis de algoritmos funcionales e imperativos. Wilmington, EE. UU.:
Addison-Wesley Iberoamericana, 1993.
López, C. G. Algoritmia, arquitectura de datos y programación estructurada. Nueva Librería, 2003.
Yourdon, E. Modern Structured Analysis. Yourdon Press Computing Series, Prentice Hall PTR, 1989.

82 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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:

• Definición de los requisitos del problema.


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• Análisis.
• Diseño.
• Codificación.
• Pruebas.
• Mantenimiento.

La descripción teórica de estas etapas se acompañará del ejemplo del desarrollo de


un sistema para la gestión académica de un centro docente universitario.

84 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Tratamiento informático de un problema

1. INTRODUCCIÓN

En la unidad didáctica 1 se ha señalado que la «programación informática» es, en


un sentido amplio, el proceso de planificar, desarrollar y mantener la resolución de un
problema mediante la computadora.

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

informático que resuelva un problema, el proceso de desarrollar programas (o en un sen-


tido genérico, el proceso de desarrollar software) requiere una serie de etapas que hay
que realizar si se quiere obtener un buen programa. Este conjunto de etapas se denomina
«ciclo de vida de desarrollo del software» (véase figura 1).

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.

Este ciclo de vida incluye las siguientes etapas de desarrollo:

• Definición de los requisitos del problema. En esta etapa se estudia el


problema planteado de forma general con el objetivo de dar respuesta a las
siguientes preguntas: ¿de qué trata el problema y qué se desea obtener? ¿Se
puede resolver con un programa informático?
• Análisis. Una vez que se ha decidido realizar el programa, se procede a estu-
diar el problema más en detalle para dar respuesta a las siguientes preguntas:
¿se va a resolver todo el problema en la computadora o solo una parte? ¿Qué
tratamiento va a tener la parte que se resuelve en la computadora? ¿Cómo
van a ser los datos y los procesos? ¿Cómo se van a producir los resultados?
• Diseño. Consiste en diseñar el o los algoritmos que definen el programa
informático y producir el pseudocódigo. Esta etapa también incorpora el
diseño de las estructuras de datos que intervienen en el problema.

www.udima.es 85

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

• Codificación. Consiste en transformar el pseudocódigo en un programa


escrito en un lenguaje de programación.
• Pruebas. Se trata de comprobar que el programa informático funciona
correctamente.
• Mantenimiento. Consiste en tener actualizado el programa para que siempre
funcione correctamente.

Figura 1. Ciclo de vida del software


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Definición de
los requisitos
del problema

Análisis

Diseño

Codificación

Pruebas

Mantenimiento

En la figura 1 se muestra un modelo de ciclo de vida en el que las etapas se realizan


de forma consecutiva; no comienza una etapa hasta que está totalmente terminada la etapa
anterior. Este modelo se conoce como «ciclo de vida en cascada» y fue desarrollado en 1970.

86 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Tratamiento informático de un problema

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:

• Gestión del profesorado: tratamiento de altas, alteraciones y bajas del


profesorado.
• Gestión del alumnado: tratamiento de altas, alteraciones y bajas del
alumnado.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• Gestión de asignaturas: tratamiento de altas, alteraciones y bajas de


asignaturas.
• Gestión de resultados:

– Relación de alumnos por asignatura (un listado con el nombre de la


asignatura, curso, profesor que imparte la asignatura y alumnos matri-
culados en ella).
– Calificación de alumnos por asignatura (obtener las actas de la
asignaturas).
– Certificación académica del curso (documento con las notas del
alumno en ese curso).
– Certificado de estudios (documento con las notas del alumno de todos
los cursos recibidos).
– Listado de alumnos con asignaturas en las que están matriculados.
– Listado de profesores con las asignaturas que imparten.
– Listado de asignaturas.

2. DEFINICIÓN DE LOS REQUISITOS DEL PROBLEMA

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Pasos de la definición de los requisitos del problema: identificar las necesi-


dades del cliente, realizar un estudio técnico y económico del sistema, establecer
restricciones de tiempo y coste, evaluar la viabilidad del sistema, asignar funciones
al sistema y definir el sistema.

El primer paso de la definición de los requisitos es identificar las necesidades del


cliente. Con ello se contesta a la pregunta: ¿de qué trata el problema y qué se desea obtener?

En el caso del sistema de gestión de un centro docente, se podría obtener el siguiente


enunciado del problema:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

EJEMPLO 1. Enunciado del problema de gestión de un centro docente

Un centro docente desea informatizar su gestión académica mediante un ordenador que


adquirirá para esta actividad. El centro tiene unos 1.000 alumnos y 80 profesores e imparte
estudios universitarios. La dirección del centro desea realizar las siguientes acciones y
obtener los siguientes productos:

• Dar de alta, de baja o modificar los datos de un profesor.


• Dar de alta, de baja o modificar los datos de un alumno.
• Dar de alta, de baja o modificar los datos de una asignatura.
• Al principio del curso desea obtener un listado alfabético de profesores con las asig-
naturas que imparten, un listado alfabético de alumnos con las asignaturas en las que
estén matriculados, un listado alfabético de asignaturas y una relación de alumnos
por asignatura para entregarla a cada profesor.
• En los meses de junio y julio desea obtener las actas de cada asignatura (califica-
ciones de los alumnos por asignatura).
• A petición del alumno, debe proporcionarle un certificado académico del curso, con
las notas de las asignaturas en las que esté matriculado, o un certificado de estudios
de todo su expediente académico.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Tratamiento informático de un problema

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.

EJEMPLO 2. Análisis técnico y económico del problema de gestión de un centro docente

• Recursos humanos necesarios: un analista y un programador durante tres meses.


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• Recursos materiales necesarios: un PC con una configuración grande y una buena


impresora.
• Coste económico de personal y material: 18.000 euros.

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.

En cuanto a las restricciones de tiempo y coste, se tendrían en cuenta, si es que


existen, al evaluar la viabilidad del sistema. En nuestro caso, se indicarían las fechas en
las que se tienen que emitir los listados y el plazo máximo desde que se realiza una peti-
ción hasta que se entregue el producto a la dirección, al profesor o al alumno.

Respecto a la evaluación de la viabilidad del sistema, normalmente incluye un aná-


lisis de viabilidad (económico, técnico y legal) junto con un análisis del riesgo: riesgos
del proyecto (problemas presupuestarios, de agenda, de personal, etc.), riesgos técnicos
(problemas de diseño, implementación, mantenimiento, etc.) y riesgos del negocio (el
producto no interesa al mercado, no se sabe comercializar, etc.). Si el riesgo del sistema
es grande, su viabilidad disminuye en la misma proporción.

EJEMPLO 3. Evaluación de viabilidad del problema de gestión de un centro docente

Como consecuencia del análisis anterior, el ingeniero informático decide si el sistema es


técnicamente viable (en el caso del ejemplo sería que sí) y el cliente decide si puede asumir
ese coste y el tiempo de desarrollo necesario.

www.udima.es 89

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Si el análisis de viabilidad tiene éxito, se pasa a la siguiente tarea: asignar funciones


al sistema. Consiste en asignar funciones a cada elemento que participa en el sistema,
teniendo en cuenta que dentro del sistema se incluye el hardware, el software, las bases
de datos, las personas, etc.

EJEMPLO 4. Asignación de funciones en el problema de gestión de un centro docente

• 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

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Tratamiento informático de un problema

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

EJEMPLO 5. Diagrama de flujo de la arquitectura del problema de gestión de un centro


docente

En la figura se muestra el circuito de información del sistema de gestión académica de un


centro docente.

Petición S

Producto S
Dirección
Producto A

Producto P Petición D Producto D

Petición AV

Petición PV

Secretario
Petición P Producto PV Petición A Producto AV

Profesor Alumno

La terminología utilizada es la siguiente:

• A: petición o producto de alumno.


• AV: petición o producto de alumno, pero validado por secretaría.

.../...

www.udima.es 91

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

.../...

• D: petición o producto de dirección.


• P: petición o producto de profesor.
• PV: petición o producto de profesor, pero validado por secretaría.
• S: petición o producto de secretario.

El resultado de la definición de los requisitos del problema se recoge en un docu-


mento, denominado «Especificación del sistema», que sirve como base para la inge-
niería del hardware, del software, de las bases de datos y la ingeniería humana. Este
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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:

• Objetivos generales del sistema. Fines del sistema, funcionamiento y ren-


dimiento requerido, entradas al sistema, salidas del sistema y restricciones.
• Definición de requisitos. De software, hardware, bases de datos, personal
y otros elementos del sistema.
• Análisis técnico. Rendimiento, fiabilidad, mantenimiento, producción.
• Análisis económico. Costes de producción, costes de mantenimiento, rela-
ción coste/beneficio.
• Viabilidad del sistema. Económica y de mercado, técnica, legal.
• Especificación de la arquitectura del sistema. Diagrama de contexto de la
arquitectura, diagrama de flujo de la arquitectura, descripción de los subsistemas.

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»:

• Objetivos generales del sistema.


• Requisitos del software.
• Requisitos de las bases de datos.
• Arquitectura del sistema.

92 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Tratamiento informático de un problema

3. ANÁLISIS

Esta etapa se suele llamar «análisis de los requisitos del software»:

Análisis de los requisitos del software. Proceso de descubrimiento, refinamiento,


modelado y especificación que lleva a cabo el ingeniero del software («analista»).

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:

• Los datos de entrada del proceso.


• La funcionalidad (lo que hace).
• Los resultados de salida.

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.

EJEMPLO 6. Diagrama general de procesos del problema de gestión de un centro docente

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Seguidamente se recogen, a modo de ejemplo, dos de los procesos enumerados en la fi-


gura del ejemplo 6: el alta de un alumno (proceso 3.1) y la generación de actas (proceso 4.5).

EJEMPLO 7. Diagrama del proceso alta de alumno

En la figura se muestra la representación gráfica del proceso 3.1 (alta de alumno).

• Entradas. Datos personales y académicos del alumno, ficheros de alumnos y


asignaturas.
• Proceso. Lee desde la interfaz de usuario los datos del alumno y comprueba en el
fichero de alumnos que ese alumno existe. También comprueba en el fichero de
asignaturas que los códigos de las asignaturas en las que se matricula son correctos.
Después de todo ello, graba los datos del alumno en el fichero de alumnos.
• Salidas. Un registro del alumno en el fichero de alumnos.

.../...

94 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Tratamiento informático de un problema

.../...

3.1. Alta alumno

Datos alumnos Alumnos Asignatura


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

EJEMPLO 8. Diagrama del proceso actas

En la figura se muestra la representación gráfica del proceso 4.5 (generación de actas).

• Entradas. Nombre de la asignatura, ficheros de asignaturas, alumnos y profesorado.


• Proceso. Se lee desde pantalla el código de la asignatura y se comprueba que existe en
el fichero de asignaturas. Seguidamente, se leen todos los alumnos que tienen esa asig-
natura, se ordenan y se imprime el código, nombre y curso de la asignatura y el nombre
de cada alumno con su nota de junio y/o julio. Al finalizar, se obtiene del fichero de
profesores el nombre de aquel que imparte esta asignatura y se imprime en el listado.
• Salidas. Listado de actas.

4.5. Actas

Listado
Nombre asignatura Asignaturas Alumnos Profesores de actas

El resultado final del análisis es un documento denominado «Especificación de requi-


sitos de software o especificaciones funcionales», que suele constar de:

• 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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

turas de la información, así como el hardware, el software y las interfaces


hombre-máquina.
• Descripción funcional. Proporciona una descripción de cada función (pro-
ceso) requerida para resolver el problema (narrativa del proceso, restric-
ciones, requisitos de rendimiento y diagrama de soporte).
• Descripción del comportamiento. Describe el comportamiento del sis-
tema software mediante un diagrama de estados, con una especificación de
eventos y acciones.
• Criterios de validación. Incorpora las clases de pruebas que se deben rea-
lizar al software, los límites de rendimiento y la respuesta esperada.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• Bibliografía y apéndices. En los apéndices se presentan las tablas de datos,


la descripción detallada de los algoritmos, los diagramas, los gráficos y otro
material de interés.

4. DISEÑO

Diseño. Proceso de aplicar distintas técnicas y principios con el propósito de definir


un dispositivo, proceso o sistema con los suficientes detalles como para permitir su
realización física.

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.

4.1. DISEÑO GENERAL

El diseño general o preliminar se centra en la transformación de los requisitos de


los datos y la arquitectura del software.

Diseño general. Consiste en desarrollar una estructura funcional y modular del


sistema, definir interfaces entre los módulos y establecer las estructuras de datos.

96 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Tratamiento informático de un problema

En este punto del diseño no se consideran los aspectos procedimentales de los


módulos, ya que se contemplan como «cajas negras» que luego serán desarrollados.

El primer paso del diseño general es el diseño arquitectónico. Su objetivo es desarrollar


una estructura modular del software y representar las relaciones de control entre los
módulos. El diseño arquitectónico mezcla la estructura del programa y la de los datos y
define las interfaces que facilitan el flujo de datos entre los módulos que definen el software.

EJEMPLO 9. Diseño arquitectónico del gestor de un centro docente

En la figura se muestra el diseño arquitectónico modular del sistema de gestión académica de


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

Profesorado Alumnado Asignaturas

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.

Comprueba Comprueba Comprueba


profesor alumno asignatura

¿Qué hace el módulo principal? Se suele denominar también «módulo de control»


porque es el que inicia la ejecución del programa, preguntando al usuario qué proceso desea
realizar y pasa a ejecutar el proceso solicitado. Al finalizar la ejecución de un proceso, este
módulo principal vuelve a recibir el control del programa y a preguntar al usuario si desea
ejecutar otro módulo. Esta acción se repite hasta que ya no existen más peticiones y fina-
liza la ejecución del programa. En el diseño detallado se verá mejor su funcionamiento.

www.udima.es 97

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

EJEMPLO 10. Diseño de datos del fichero de alumnos

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:

• NAP: nombre y apellido (apellido 1, apellido 2 y nombre).


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• DIRECCIÓN: dirección del alumno (calle, número, piso y letra).


• CURSO: curso académico (llevará un * para indicar el fin del registro).
• N.º ASIG.: número de asignaturas en ese curso.
• ASIG. i: Asignatura (código de la asignatura [CAS], nota de junio [NJ] y de julio [NJL]).

NAP DIRECCIÓN ASIG. 1 ASIG. 2


N.º ASIG.
CURSO

AP1 AP2 Nombre Calle, N.º, Piso, Letra CAS NJ NJL CAS NJ NJL

4.2. DISEÑO DETALLADO

El diseño detallado se ocupa del refinamiento de la representación arquitectónica


que conduce a una estructura de datos detallada y a la representación algorítmica del
software o diseño procedimental.

Diseño detallado. Consiste en diseñar los algoritmos de cada unidad de trata-


miento o proceso y del módulo principal. También se produce el pseudocódigo de
todo el programa.

Cuando las unidades de tratamiento son complejas, conviene diseñar el algoritmo


de cada unidad mediante el sistema de pasos o con alguna de las notaciones vistas en la

98 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Tratamiento informático de un problema

unidad didáctica anterior y posteriormente pasar dicho algoritmo al pseudocódigo estruc-


turado. Pero cuando las unidades de tratamiento son simples, diseñar primero el algo-
ritmo y luego escribir el pseudocódigo resulta un proceso redundante. En estos casos de
procesos simples, se considera una buena práctica el hecho de describir directamente
el pseudocódigo estructurado que, como es lógico, también describe el algoritmo que
resuelve la unidad de tratamiento.

Seguidamente se recoge, a modo de ejemplo, el pseudocódigo de dos de los módulos


identificados en el programa de gestión académica de un centro docente: el módulo princi-
pal y el módulo encargado de mostrar todos los profesores con las asignaturas que imparten.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

EJEMPLO 11. Diseño en pseudocódigo del módulo principal

Seguidamente se muestra el pseudocódigo del módulo principal. Puede observarse como


lo que se hace es presentar un menú principal y, en función de la solicitud del usuario,
llamar a los módulos hijos para temas de profesorado, de alumnado o de asignaturas.

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

EJEMPLO 12. Diseño en pseudocódigo del módulo profesorado con asignaturas

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

El resultado final de las dos etapas de diseño es el «Documento de diseño detallado»


o «Documento de diseño final», que incorpora un diseño detallado de los datos, un diseño
de la interfaz persona-ordenador (si el programa es interactivo), la arquitectura modular
del sistema con la interfaz de los módulos y, finalmente, el diseño procedimental (pseu-
docódigo) de cada módulo. A este documento también se le incorpora una especifica-
ción de las pruebas que se deben realizar en cada módulo por separado y al integrar cada
módulo con otros módulos del sistema.

El diseño es la parte central de la ingeniería del software y merece la pena dedi-


carle el tiempo suficiente para su correcta realización.

100 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Tratamiento informático de un problema

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.

Codificación. Consiste en la creación de un programa informático utilizando un


lenguaje de programación, tomando como punto de partida el pseudocódigo resul-
tante del diseño detallado.

Codificación es, pues, la transcripción del pseudocódigo (o del algoritmo o incluso


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

del diseño) en instrucciones de un lenguaje de programación y su resultado es el código


fuente del programa informático.

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:

• El código fuente debe documentarse con la elección de identificadores (varia-


bles y etiquetas) que sean significativos (por ejemplo: dist es peor que dis-
tancia como identificador) e incorporando comentarios al principio de cada
módulo (comentarios de prólogo) que indiquen: la función del módulo; una
descripción de su interfaz y de los argumentos que tenga; una descripción
de las estructuras de datos más significativos que utilice el módulo y una
historia del módulo (autor, fecha de creación y modificación). Asimismo,
se incorporarán comentarios descriptivos en el cuerpo del módulo para des-
cribir las funciones de procesamiento.
• La forma en la que aparece el código fuente en el listado es una contribu-
ción importante a la legibilidad del mismo; por ello, el sangrado (o inden-
tado) realza las construcciones lógicas y los bloques de código. En este
sentido, se debe resaltar la importancia de seguir estándares de codifica-
ción. Muchos lenguajes de programación tienen guías de estilo oficiales,
cuyo seguimiento mejoraría la calidad del producto final y la facilidad para
realizar el mantenimiento.
• Los datos se deben declarar en aquellos lugares que proporcionan un acceso
rápido a la hora de identificarlos dentro de una sentencia. Es normal decla-

www.udima.es 101

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

rarlos al principio del módulo con un determinado orden. Como regla


general, las declaraciones deben estar lo más cerca posible del segmento
de código en el que se utilicen, que debe ser lo más breve posible.
• Las sentencias deben ser simples y fáciles de seguir, para lo cual, se deberá:
evitar el uso de comparaciones condicionales complicadas; de compara-
ciones con condiciones negativas; usar paréntesis para dar más legibilidad
a la sentencia; no utilizar sentencias de iteración con muchos anidamientos;
usar varias líneas para sentencias largas, etc.
• Las entradas/salidas deben ser codificadas cuidadosamente, ya que son
origen de múltiples errores difíciles de localizar al primer instante. Por ello
es importante: mantener un formato de entrada simple; validar todos los
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

datos de entrada; usar indicativos de fin de datos en lugar de especificar el


número de datos que leer, etc.

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

El hecho de haber diseñado un buen algoritmo y posteriormente haberlo codifi-


cado en un lenguaje de programación no significa que el programa resuelva correcta-
mente el problema. La experiencia de cualquier programador, por muy experto que sea,
lo demuestra.

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.

Pruebas. Consisten en la preparación de conjuntos de datos de entrada y sus


correspondientes salidas para verificar que el programa funciona correctamente.

102 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Tratamiento informático de un problema

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

funcionalidad y el rendimiento del sistema total.

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.

Durante la fase de «diseño» se especifican las pruebas de integración, que consisten


en comprobar que el programa se ha construido correctamente. Su objetivo es coger
cada módulo ya probado e integrarlo en el sistema software que se está desarrollando
y comprobar que globalmente funciona correctamente. El hecho de que cada módulo
funcione correctamente no presupone que juntos vayan a funcionar bien. Normalmente,
existen problemas de acoplamiento de las interfaces que hay que depurar (por ejemplo:
el número de argumentos con los que se llama a un módulo no coincide con los paráme-
tros de su interfaz, o no coincide el tipo de sus argumentos, etc.). En esta fase también
se especifican las pruebas de unidad de cada módulo.

Al finalizar la «codificación» de cada módulo se realiza la prueba de unidad, que


consiste en comprobar que el módulo funciona correctamente, es decir, que todos
los caminos de control importantes se ejecutan de acuerdo con lo especificado. Las
pruebas de unidad son de «caja blanca» y de «caja negra» (véase más adelante) y tratan
fundamentalmente:

• La interfaz del módulo, analizando que la información entra y sale correc-


tamente del módulo.
• Las estructuras de datos locales, ya que son una fuente potencial de errores.
• Los valores límite establecidos para el módulo.

www.udima.es 103

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

• Los caminos independientes de las estructuras de control, asegurando que


todas las sentencias del módulo se ejecutan por lo menos una vez.
• El tratamiento de errores, comprobando que se ejecutan y son los adecuados.

En resumen, esta etapa incorpora pruebas de unidad, de integración y de validación.


Las pruebas de «unidad» validan la eficacia funcional de cada módulo del sistema. Las
de «integración» validan la eficacia funcional de los subsistemas y de todo el sistema
software. Y las de «validación» verifican que todos los requerimientos han sido incor-
porados. Para ello es necesario desarrollar en las etapas de análisis y diseño un «plan y
procedimiento de pruebas» para cada una de estas validaciones.

Las pruebas se pueden realizar de dos formas:


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• 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.

Finalmente, debe señalarse que, en general, se considera que la implementación de


un programa incluye tanto la codificación como las pruebas:

Implementación del software. Proceso de codificación del software en un len-


guaje informático y su validación mediante pruebas de juego de ensayo o de téc-
nicas específicas.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Tratamiento informático de un problema

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.

Otro aspecto que no se menciona son las pruebas de implantación, realizadas en el


periodo de tiempo en el que el software pasa a su entorno de ejecución final. Esto puede
considerarse parte de la etapa de pruebas o de la de mantenimiento.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.

Mantenimiento. Gestión y realización de cambios en el programa para mantenerlo


actualizado mientras dure su ciclo de vida.

Existen tres tipos de mantenimiento que hay que atender:

• Mantenimiento correctivo. Consiste en corregir los errores que se pueden


detectar cuando el programa se ejecuta. Aunque el programador haya pro-
bado mucho el programa, siempre surge algún tipo de error que se ha pasado
por alto y que se detecta en la vida del programa.
• Mantenimiento perfectivo. Consiste en ampliar el programa para que haga
alguna otra cosa que al usuario le surja en el futuro. Por ejemplo, en el caso
del programa de gestión académica de un centro educativo, puede ocurrir
que la universidad desee mantener el historial detallado de cada alumno
durante su estancia en la universidad. Este tratamiento no está contemplado
y habría que programarlo. En realidad, surgen nuevos requisitos en cual-
quier sistema que se implante con éxito. Puede considerarse que la cantidad
de acciones de mantenimiento perfectivo es una medida indirecta de dicho
éxito.

www.udima.es 105

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

• Mantenimiento adaptativo. Consiste en adaptar el programa a las caracte-


rísticas del entorno externo, que pueden ser técnicas (por ejemplo, cambio
de sistema operativo) o de otro tipo (por ejemplo, paso del sistema de cré-
ditos tradicionales a los créditos europeos ECTS).

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.

No se va a profundizar en este tema del mantenimiento porque se sale del marco


de esta materia. Lo que sí interesa recordar es que, cuando se crea un programa y se
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Tratamiento informático de un problema

 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

del sistema, asignar funciones al sistema y definir el sistema.


• Análisis de los requisitos del software. Proceso de descubrimiento, refi-
namiento, modelado y especificación que lleva a cabo el ingeniero del soft-
ware («analista»).
• Diseño. Proceso de aplicar distintas técnicas y principios con el propósito de
definir un dispositivo, proceso o sistema con los suficientes detalles como
para permitir su realización física. El diseño es la parte central de la inge-
niería del software y merece la pena dedicarle el tiempo suficiente para su
correcta realización.
• Diseño general. Desarrollar una estructura funcional y modular del sistema,
definir interfaces entre los módulos y establecer las estructuras de datos.
• Diseño detallado. Diseñar los algoritmos de cada unidad de tratamiento o
proceso y del módulo principal. También se produce el pseudocódigo de
todo el programa.
• Codificación. Creación de un programa informático utilizando un lenguaje
de programación, tomando como punto de partida el pseudocódigo resul-
tante del diseño detallado.
• Pruebas. Preparación de conjuntos de datos de entrada y sus correspon-
dientes salidas para verificar que el programa funciona correctamente.
• Implementación del software. Proceso de codificación del software en un
lenguaje informático y su validación mediante pruebas de juego de ensayo
o de técnicas específicas.
• Mantenimiento. Gestión y realización de cambios en el programa para
mantenerlo actualizado mientras dure su ciclo de vida.

www.udima.es 107

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

 ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1

Describir las necesidades del cliente se realiza en la etapa de:

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

Un proceso se describe con:

a) Los datos de entrada.


b) Los resultados de salida.
c) Su funcionalidad.
d) Las tres anteriores.

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

La etapa de codificación consiste en:

108 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Tratamiento informático de un problema

a) Obtener un programa en C++.


b) Transcribir el pseudocódigo en instrucciones de un lenguaje de programación.
c) Codificar el pseudocódigo en un algoritmo.
d) Pasar el pseudocódigo a un programa ejecutable.

Enunciado 5

El mantenimiento debe ser:

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Solución 1

c) Requisitos del problema.

Solución 2

d) Las tres anteriores.

Solución 3

b) El pseudocódigo y las estructuras de los datos.


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Solución 4

b) Transcribir el pseudocódigo en instrucciones de un lenguaje de programación.

Solución 5

d) Correctivo, perfectivo y adaptativo.

 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

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Tratamiento informático de un problema

 CASO PRÁCTICO

Realizar las etapas de análisis y diseño para el siguiente problema:

Se desea desarrollar un sistema informático que realice la gestión de las llamadas


telefónicas realizadas por los clientes de un operador de telefonía móvil (Gestel). Para
ello, deberá manejar información de clientes, líneas de teléfono, tarifas, llamadas reali-
zadas, envío de mensajes y conexiones de datos:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• Cliente. Se almacena el nombre completo y el DNI.


• Línea. Se almacena el número de teléfono.
• Tarifa. Se almacena el tipo (llamada a móvil, llamada a fijo, envío de men-
sajes, conexión de datos) y el importe por unidad (euros por minuto en las
llamadas, euros por cada mensaje o euros por cada 1.000 kilobytes de infor-
mación en las conexiones de datos).
• Llamadas. Se almacena el teléfono de destino, la fecha, la hora de comienzo
y la duración de la llamada en minutos.
• Mensajes. Se almacena el teléfono destinatario, la fecha y la hora de envío.
• Conexión de datos. Se almacena la fecha, la hora de comienzo, la duración
de la conexión en minutos y la cantidad de información recibida (medida
en kilobytes).

Entre los datos anteriores se establecen las siguientes relaciones:

• 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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

L. A. Martínez Normand Tratamiento informático de un problema

total de llamadas y su duración acumulada (referidos al periodo de tiempo


recibido), el número de mensajes enviados y el número de conexiones de
datos junto con la cantidad total de información recibida en dicho periodo.
• Mostrar la información detallada de las llamadas 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 nombre completo del cliente, el número
de teléfono de la línea y todas sus llamadas, en dos grupos: primero, las lla-
madas a teléfonos móviles y después, las llamadas a teléfonos fijos. Dentro
de cada bloque, las llamadas se ordenarán por fecha, por número de telé-
fono de destino y por duración. Para cada llamada, se indicará el teléfono
de destino, la fecha, la duración y el coste. El coste se calcula a partir de la
información de tarifas existentes, multiplicando la duración de la llamada
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

por el coste por minuto.


Nota. En la definición de periodos de tiempo debe comprobarse que la fecha
inicial sea menor o igual que la fecha final. El periodo se contabiliza desde
las 00:00 de la fecha inicial hasta las 23:59 de la fecha final.
• Generar la factura de un cliente para un mes determinado, dados el DNI del
cliente y el mes. Se mostrará el nombre completo del cliente, su DNI, el
número de líneas que tiene el cliente, el coste de las llamadas de ese mes,
el coste de los mensajes de ese mes, el coste de las conexiones realizadas
y el coste total de facturación, teniendo en cuenta la acumulación de costes
de todas las líneas de ese cliente.
• Mostrar los 10 clientes con mayor facturación total en un mes determinado,
dado un mes. Los clientes se ordenarán de mayor a menor por el importe de
facturación total. Para cada cliente, se mostrará el DNI y la facturación total.
Nota. Si el sistema tiene almacenados menos de 10 clientes, se mostrarán
todos ordenados por su facturación total.

 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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

 OBJETIVOS DE LA UNIDAD
La unidad didáctica 4 presenta los siguientes conceptos:

• La programación es el proceso de planificar y desarrollar la resolución de


un problema mediante una computadora.
• El objetivo de la programación consiste en la obtención de un programa de
calidad que sea correcto, que presente claridad, que sea eficiente y que sea
portable.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• Los paradigmas de programación. Los paradigmas procedimentales u ope-


racionales se basan en una secuencia computacional que se ejecuta etapa
a etapa para resolver un problema planteado. Los paradigmas declarativos
construyen la solución mediante hechos, reglas, restricciones, ecuaciones,
transformaciones y otras propiedades que configuran la solución. Los para-
digmas demostrativos, para construir la solución, se basan en presentar solu-
ciones de problemas similares y permitir al programa que generalice una
solución a partir de estas demostraciones.
• El paradigma imperativo, perteneciente al tipo de paradigmas procedimen-
tales, se basa en que existe un programa en memoria que se va ejecutando
secuencialmente y que toma unos datos de la memoria, efectúa unos cálculos
y actualiza la memoria.
• Los lenguajes de programación sirven para escribir un programa informá-
tico que implementa un problema y que se utilizan para controlar el com-
portamiento físico y lógico de una computadora. A tal efecto, se describen
los lenguajes máquina, los lenguajes de bajo nivel y los de alto nivel.
• Finalmente, se describe sucintamente la historia de los lenguajes de
programación.

Como objetivos específicos de la unidad didáctica se pretende que el lector conozca


lo siguiente:

• Qué es la programación informática y qué pasos se precisan para construir


un programa. Construir un programa no consiste en detectar un problema,
tener una idea para resolverlo y codificarlo en el ordenador. Es necesario,

www.udima.es 117

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

después de reconocer la necesidad de crear un programa para resolver


el problema, especificar los requisitos del programa, analizarlos, diseñar el
programa, codificarlo en un lenguaje informático e instalarlo en la compu-
tadora y que funcione correctamente.
• Todos los programas no se construyen de la misma forma. Cada problema
planteado se resuelve de una forma diferente y obliga a que el programa
informático que lo resuelva tenga una estructura determinada acorde con
dicho problema. A tal efecto, existen diferentes paradigmas de programa-
ción que definen la forma de construir un programa atendiendo a las carac-
terísticas del problema. Ello es equivalente a las formas de construcción
arquitectónica de los edificios; la construcción de un rascacielos plantea
una arquitectura diferente a la de una casa o la de una nave industrial.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• Para programar existen diferentes tipos de lenguajes. Los hay a nivel de la


computadora, con codificación numérica de las instrucciones, como son los
lenguajes máquina, muy difíciles de programar. Los hay de un nivel superior,
como son los lenguajes ensambladores, cuyas instrucciones utilizan códigos
mnemotécnicos, más fáciles de programar, pero necesitan un traductor para
pasar el lenguaje ensamblador al lenguaje máquina de la computadora. Y
los hay de alto nivel, más próximos a la forma de pensar y escribir del ser
humano, pero los programas escritos en ese lenguaje necesitan, para que se
puedan ejecutar, un traductor más potente (un compilador o un intérprete).
• Los lenguajes de programación son de creación muy reciente y han sur-
gido como una torre de Babel, en diferentes campos y para diferentes fines.
Nacen los primeros lenguajes ensambladores en la década de los cuarenta,
y los primeros lenguajes de alto nivel, como los utilizados hoy en día, en
los años cincuenta. Es decir, la historia de los lenguajes de programación
es una historia de 60-70 años. El número de lenguajes que ha aparecido es
muy grande, aunque muy pocos perduran hasta nuestros días.

118 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

1. LA PROGRAMACIÓN

Habíamos visto en la unidad didáctica 1 el concepto de programación como «el


proceso de planificar y desarrollar la resolución de un problema mediante una computa-
dora». Su fin es crear un programa informático que resuelva el problema.

En un sentido amplio, este concepto de programación incluye los siguientes pasos:


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• Reconocer la necesidad de crear un programa para solucionar un pro-


blema o identificar la posibilidad de automatización de una tarea.
• Especificar los requisitos del programa. Hay que especificar claramente
qué es lo que debe hacer el programa y para qué se necesita.
• Realizar el análisis de los requisitos del programa. Se debe indicar con
precisión cómo debe realizar el programa las funciones que debe ejecutar.
Las pruebas que comprueban la validez del programa se pueden especificar
en esta fase.
• Diseñar la arquitectura del programa. Realizar un diseño detallado, espe-
cificando completamente todo el funcionamiento del programa. Este se debe
descomponer en diferentes partes de complejidad abordable.
• Implementar el programa. Codificarlo en un lenguaje de programación y
probar que funciona correctamente.
• Implantar (instalar) el programa. Poner el programa en funcionamiento
permanente.

Programación. Proceso de creación de un programa informático en el cual se diseña


una estructura, se codifica en un lenguaje de programación, se prueba, se depura y
se mantiene el código fuente del programa creado.

La programación debe perseguir la obtención de programas de calidad. Para ello se


establece una serie de factores que determinan la calidad de un programa. Algunos de
los factores de calidad más importantes son los siguientes:

www.udima.es 119

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

• Corrección. Un programa es correcto si hace lo que debe hacer, tal y como


se estableció en las fases previas a su desarrollo. Para determinar si un pro-
grama hace lo que debe, es muy importante especificar claramente qué debe
hacer el programa antes de desarrollarlo y, una vez acabado, compararlo
con lo que realmente hace.
• Claridad. Es muy importante que el programa sea lo más claro y legible
posible para facilitar así su desarrollo y posterior mantenimiento. Al elaborar
un programa se debe intentar que su estructura sea sencilla y coherente, así
como cuidar el estilo en la edición; de esta forma, se facilita el trabajo del
programador, tanto en la fase de creación como en las fases posteriores de
corrección de errores, ampliaciones, modificaciones, etc. Fases que pueden
ser realizadas incluso por otro programador, con lo cual, la claridad es aún
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

más necesaria para que otros programadores puedan continuar el trabajo


fácilmente.
• Eficiencia. Se trata de que el programa, además de realizar aquello para lo
que fue creado (es decir, que sea correcto), lo haga gestionando de la mejor
forma posible los recursos que utiliza. Normalmente, al hablar de eficiencia
de un programa se suele hacer referencia al tiempo que tarda en realizar la
tarea para la que ha sido creado y a la cantidad de memoria que necesita,
pero hay otros recursos que también pueden ser de consideración al obtener
la eficiencia de un programa dependiendo de su naturaleza (espacio en disco
que utiliza, tráfico de red que genera, etc.).
• Portabilidad. Un programa es portable cuando tiene la capacidad de poder
ejecutarse en una plataforma (computadora y sistema operativo) diferente
a aquella en la que se elaboró. La portabilidad es una característica muy
deseable para un programa, ya que permite, por ejemplo, a un programa
que ha sido desarrollado para el sistema operativo GNU/Linux que se pueda
ejecutar también en el sistema operativo Windows. Esto permite que el pro-
grama pueda llegar a más usuarios más fácilmente.

Si se quiere obtener ciertas garantías de calidad durante el desarrollo de un programa


de cierta envergadura o complejo, es conveniente seguir alguno de los modelos, ya acu-
ñados, de desarrollo de programas existentes, tales como el modelo de desarrollo estruc-
turado, el modelo de desarrollo orientado a objetos, etc. Los modelos de desarrollo de
programas los aborda una disciplina específica del campo de la informática: la inge-
niería del software.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

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

El Diccionario de la Lengua Española presenta la palabra «paradigma» como deri-


vada del latín paradigma, y esta, del griego parádeigma, y la define como: «Ejemplo o
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.

Adam Smith define el concepto de paradigma, en su libro Los poderes de la mente,


como: «Un conjunto compartido de suposiciones. Es la manera como percibimos el
mundo: agua para el pez, aire para el ave, etc. El paradigma nos explica el mundo y nos
ayuda a predecir su comportamiento».

En el contexto científico, el término «paradigma» es concebido como una forma


aceptada de resolver un problema en la ciencia, que más tarde es utilizado como modelo
para la investigación y la formación de una teoría. También, el paradigma es concebido
como un conjunto de métodos, reglas y generalizaciones utilizadas conjuntamente para
realizar el trabajo científico de investigación.

En el contexto de las ciencias de la computación, la palabra «paradigma» se asocia al


concepto de modelo de referencia conceptual para la creación de programas informáticos.

Un paradigma de programación es un modelo básico de construcción de programas


informáticos que permite producir programas conforme a unas directrices específicas,
tales como diseñar un programa mediante una secuencia de instrucciones que operan
sobre unos datos de entrada y producen unos resultados de salida, o diseñar un programa

www.udima.es 121

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

configurándolo como un conjunto de funciones y procedimientos que actúan sobre unas


estructuras de datos para resolver un problema, etc.

Para algunos, puede resultar sorprendente que existan diferentes paradigmas de


programación. La mayor parte de los programadores están familiarizados con un único
paradigma, el de la programación procedimental. No obstante, existen multitud de ellos
atendiendo a alguna peculiaridad metodológica o funcional como, por ejemplo:

• El basado en reglas, de gran aplicación en la ingeniería del conocimiento


para el desarrollo de sistemas expertos, en el que el núcleo del mismo son
las reglas de producción de tipo if-then.
• El de la programación lógica, basado en asertos y reglas lógicas, que define
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

un entorno de programación de tipo conversacional, deductivo, simbólico


y no determinista.
• El de la programación funcional, basado en formas funcionales para crear
funciones y mecanismos para aplicar los argumentos, y que define un entorno
de programación interpretativo, conversacional y aplicativo.
• El de la programación heurística, que aplica para la resolución de pro-
blemas «reglas de buena lógica» (heurísticas) que presentan visos de ser
correctas aunque no se garantiza su éxito, modelando el problema de una
forma adecuada para aplicar estas heurísticas atendiendo a su representa-
ción, estrategias de búsqueda y métodos de resolución.

Y existen otros, como el de programación paralela; el basado en restricciones; el


basado en el flujo de datos, el orientado al objeto, etc.

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.

Paradigma de programación. Colección de modelos conceptuales que, juntos,


modelan el proceso de construcción de un programa y determinan, al final, su
estructura.

122 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

La estructura conceptual de modelos está diseñada de forma que estos:

• Controlan la manera en la que pensamos cómo solucionar un problema.


Por ejemplo, en el paradigma orientado a objetos, la solución hay que bus-
carla a partir de la especificación del problema creando clases y relaciones
entre ellas, mientras que en el paradigma lógico, la solución hay que bus-
carla por medio de asertos (hechos) y reglas lógicas que se desprendan de
dicha especificación.
• Definen el modo en el que la solución se formaliza. Por ejemplo, en orien-
tación a objetos (OO), se formaliza con una colección de objetos y mensajes
que se mandan entre ellos, y en programación lógica, partiendo de unos
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

asertos y encadenando conclusiones al aplicar reglas lógicas.


• Determinan la forma correcta de los programas, incluso, si alcanzamos
la solución.

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.

Cuando un lenguaje de programación refleja bien un paradigma particular se dice


que soporta el paradigma. En la práctica, un lenguaje que soporta correctamente un para-
digma es difícil distinguirlo del propio paradigma, por lo que se identifica con él.

Finalmente, interesa no confundir lo que es un «modelo de construcción de pro-


gramas» (o paradigma de programación) con lo que es una «metodología de desarrollo
de programas».

El «modelo de construcción de programas» o «paradigma de programación» señala


la forma arquitectónica que se va a utilizar para construir el programa y para la cual
existen unos lenguajes de programación más idóneos que otros. Así, si se construye
un programa mediante hechos y reglas lógicas, parece más apropiado programarlo
en Prolog que en C o en Fortran. En cambio, si se construye un programa basado en
objetos, un lenguaje apropiado es el Java o el C++, pero no el Prolog o un lenguaje
ensamblador.

www.udima.es 123

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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».

¿Existe, pues, alguna relación entre el «modelo de construcción de un programa» (o


paradigma de programación) y la «metodología de desarrollo de un programa» (o ciclo
de vida del programa)?

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

no tendría sentido que a la hora de desarrollar un programa se utilizase una metodología


de desarrollo orientada a objetos y que el programa se construyese (se implementase)
utilizando un modelo basado en hechos y reglas o un modelo imperativo.

2.1. TIPOS DE PARADIGMAS DE PROGRAMACIÓN

Floyd describe tres categorías de paradigmas de programación:

• 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:

• Solución procedimental u operacional. Describe etapa a etapa el modo de


construir la solución. Es decir, señala cómo obtener la solución. Por ejemplo,

124 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

supongamos que queremos calcular el área cubierta por la función 3 seno(4 x)


y el eje de abcisas entre [0, π]. Obviamente, la solución analítica es la inte-
gral de la función entre los dos puntos, pero en este paradigma debemos
explicar cómo calcular dicha integral. La solución procedimental consis-
tiría en describir los pasos de cualquier algoritmo numérico; por ejemplo,
mediante la suma de trapezoides aplicados a la función en el intervalo
indicado.
• Solución declarativa. Señala las características que debe tener la solución,
sin describir cómo procesarla. Es decir, señala qué se desea obtener pero
no cómo obtenerlo. Para el caso del área de la función 3 seno(4x), en esta
solución declarativa deberíamos simplemente especificar que lo que hay
que calcular es:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

π
� 3 seno(4x) dx
0

y el lenguaje o sistema declarativo utilizado para expresarlo debe propor-


cionar un proceso automático de cálculo. Como vemos, aquí se especifica
qué hay que calcular, no cómo.
• Solución demostrativa. Es una variante de la procedimental. Especifica
la solución describiendo ejemplos y permitiendo que el sistema generalice la
solución de esos ejemplos para otros casos. Para el caso del área de la función
3 seno(4x), habría que describir ejemplos de cálculos de área parecidos, como:

Área de 1 seno(2x) = 2
Área de – 2 seno(3x) = – 2
Etc.

En estos casos, lo que se describe no es el resultado final de los ejemplos,


como se ha hecho arriba, sino cómo se ha solucionado detalladamente cada
uno de ellos, de modo que el sistema demostrativo aprenda el método o pro-
cedimiento de cómo se ha hecho y generalice una solución para casos nuevos.
Aunque la solución demostrativa es fundamentalmente procedimental, el
hecho de producir resultados muy diferentes a esta hace que sea tratada
como una categoría separada.

Seguidamente, se describen los paradigmas que incorporan cada una de estas tres
soluciones.

www.udima.es 125

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

2.1.1. Paradigmas procedimentales u operacionales

La característica fundamental de estos paradigmas es que se basan en una secuencia


computacional que se ejecuta etapa a etapa para resolver el problema. Su mayor dificultad
reside en determinar si el valor final computado es una solución correcta del problema,
por lo que se han desarrollado multitud de técnicas de verificación para probar la correc-
ción de los programas implementados con este tipo de paradigmas.

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.

Existen dos tipos fundamentales de paradigmas con efecto de lado:

• 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.

Los paradigmas procedimentales definen explícitamente la secuencia de ejecu-


ción del programa, pero esta secuencia se puede procesar en serie o en paralelo. En
este segundo caso, el procesamiento paralelo puede ser asíncrono (cooperación de pro-
cesos paralelos) o síncrono (procesos simples aplicados simultáneamente a muchos
objetos).

2.1.2. Paradigmas declarativos

En este tipo de paradigmas, un programa se construye mediante hechos, reglas, res-


tricciones, ecuaciones, transformaciones y otras propiedades derivadas del conjunto de
valores que configuran la solución.

126 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

A partir de esta información, el sistema computacional debe proporcionar la estruc-


tura de control apropiada que incluya el orden de evaluación del programa que compute
una solución. Aquí no existe la necesidad de describir las diferentes etapas que hay que
seguir para alcanzar una solución como en el caso procedimental.

Estos paradigmas permiten utilizar variables para almacenar valores intermedios,


pero no para actualizar estados de información.

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.

Otros paradigmas pertenecientes a este grupo no necesitan incorporar secuencias de


control porque utilizan otros mecanismos de control como son: el basado en formulario,
el de flujo de datos y la programación basada en restricciones.

El basado en formularios y el de flujo de datos evitan estas dificultades, fundamental-


mente, a través de las restricciones, que presentan la forma de las ecuaciones permitidas,
y con los modelos empleados de evaluación, dirigidos por dependencias existentes entre
las fórmulas. El basado en restricciones viene controlado por las restricciones impuestas
por un conjunto de ecuaciones.

2.1.3. Paradigmas demostrativos

Cuando se programa bajo un paradigma demostrativo (también llamado progra-


mación por ejemplos o por demostración), el programador no especifica procedimen-
talmente cómo construir una solución. En su lugar, presenta soluciones de problemas
similares y permite al programa que generalice una solución procedimental a partir de
estas demostraciones. Los esquemas que se siguen para generalizar tales soluciones van
desde simular una secuencia procedimental a inferir intenciones.

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

el programa aprenda y posteriormente validar el conocimiento que ha adquirido el pro-


grama presentándole juegos de ensayo de validación.

Otra solución es la programación asistida: el sistema observa acciones que el progra-


mador ejecuta, y si son similares a acciones pasadas, intentará inferir cuál es la próxima
acción que hará el programador.

Las dos principales objeciones a los sistemas de inferencia son:

• Si no se comprueban exhaustivamente, pueden producir programas erró-


neos que trabajen correctamente con los ejemplos de prueba pero que fallen
posteriormente en otros ejemplos.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• La capacidad de inferencia es tan limitada que el usuario debe guiar el pro-


ceso en la mayoría de los casos.

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.

Se puede señalar que la programación demostrativa es una solución bottom-up (de


abajo arriba), ya que se parte de ejemplos particulares y concretos y se intenta extraer
una solución general que luego se aplicará a otros problemas. Esta manera de proceder
se adapta particularmente bien a nuestra capacidad natural de pensar. Esto no es así en
la mayor parte de los otros paradigmas, en los que la resolución del problema se efectúa
aplicando modelos abstractos top-down (de arriba abajo), que parten de una solución
general que se particulariza para el problema en cuestión.

2.1.4. Secuencias de control en paradigmas

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

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.

Figura 1. Paradigmas de programación en función del control de la secuencia

Procedimental Abstracción Orden de Ecuaciones Declarativos


(órdenes con encapsulada evaluación computables (restricciones
efecto de lado) conocida arbitrarias)
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Imperativo
Orientado a objetos
Funcional
Lógico
De transformación
Basado en formularios
Flujo de datos
Basado en restricciones
Demostrativo

A continuación se presenta con detalle el paradigma imperativo, que actualmente


es el que mayor relevancia tiene en el campo de la programación.

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.

La computadora almacena una representación codificada de una computación y


ejecuta una secuencia de comandos que modifican el contenido de ese almacenamiento.
Este paradigma viene bien representado por la arquitectura Von Neumann, ya que uti-
liza este modelo de máquina para conceptualizar las soluciones: «Existe un programa en

www.udima.es 129

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

memoria que se va ejecutando secuencialmente, y que toma unos datos de la memoria,


efectúa unos cálculos y actualiza la memoria».

La programación, en el paradigma imperativo, consiste en determinar qué datos son


requeridos por el programa, asociar a esos datos unas direcciones de memoria y efectuar,
paso a paso, una secuencia de transformaciones en los datos almacenados de forma que
el estado final represente el resultado correcto.

En su forma pura, el paradigma imperativo únicamente soporta sentencias que modi-


fican la memoria y efectúan bifurcaciones condicionales e incondicionales. Incluso cuando
se añade al programa una forma simple de abstracción como es un «procedimiento»,
el modelo permanece básicamente sin cambiar. Los parámetros del procedimiento son
«alias» de las zonas de memoria, por lo que pueden alterar su valor y el procedimiento
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

puede no retornar ningún tipo de resultado. La memoria también se puede actualizar


directamente mediante referencias a variables globales.

El paradigma imperativo debe su nombre al papel dominante que desempeñan las


sentencias imperativas. Su esencia es el cálculo iterativo, paso a paso, de valores de nivel
inferior y su asignación a posiciones de memoria.

Si se analizan las características fundamentales de este tipo de paradigma, se detectan


las siguientes:

• Concepto de celda de memoria («variable») para almacenar valores. El


principal componente de la arquitectura es la memoria, compuesta por un
gran número de celdas donde se almacenan los datos. Las celdas tienen nom-
bres (concepto de variable) que las referencian, y sobre las que se producen
efectos de lado (lo veremos más
adelante) y definiciones de alias. Figura 2. Alias de una variable
Por ejemplo, en el lenguaje C/C++
podemos declarar que a la variable nombre
nombre , que corresponde a una
celda de memoria con contenido
nombre1
25, se le asigne el alias nombre1 25
mediante el siguiente conjunto de
instrucciones:

int nombre = 25;
int &nombre1 = nombre;

130 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

• Operaciones de asignación. Estrechamente ligada a la arquitectura de la


memoria se encuentra la idea de que cada valor calculado debe ser «alma-
cenado»; es decir, asignado a una celda. Esta es la razón de la importancia
de la sentencia de asignación en el paradigma imperativo. Las nociones de
celda de memoria y asignación se extienden a todos los lenguajes de pro-
gramación imperativa y fuerzan en los programadores un estilo de pensa-
miento adaptado a la arquitectura Von Neumann.
Siguiendo con el ejemplo de la figura 2, si codificamos en el lenguaje
C/C++:

nombre = nombre + nombre1;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

el contenido de la celda nombre (cuyo alias es nombre1) pasa a valer 50.


Es decir, se ha asignado a la variable nombre el valor de 50.
• Repetición. Un programa imperativo normalmente realiza su tarea ejecu-
tando repetidamente una secuencia de pasos elementales, ya que en este
modelo computacional la única forma de ejecutar algo complejo es repi-
tiendo una secuencia de instrucciones.
Por ejemplo, las sentencias C/C++, que se indican a continuación, suman el
contenido de las 10 celdas del array vector y lo almacenan en la variable
sum, que luego imprime.

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 */

A este tipo de paradigma de programación se le suele denominar también paradigma


algorítmico, porque lo que se programa es un «algoritmo» que, como se mencionó en
la unidad 2, es un «conjunto finito de reglas que crean una serie de operaciones para
resolver un tipo específico de problemas». Así, para N. Wirth, un programa imperativo
viene definido por la ecuación:

Algoritmo + Estructuras de datos = Programa

www.udima.es 131

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

No obstante, entendemos que, aunque el concepto de algoritmo encaja en otros tipos


de paradigmas, es privativo del tipo de programación procedimental en el que su carac-
terística fundamental es la secuencia computacional.

3.1. L
 ENGUAJES IMPERATIVOS ORIENTADOS A EXPRESIONES Y A
SENTENCIAS
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Atendiendo a los lenguajes imperativos, cabe clasificarlos en «orientados a expre-


siones» y «orientados a sentencias», según jueguen las expresiones o las sentencias un
papel más predominante en el lenguaje. Ambos son términos relativos, y ningún lenguaje
cuenta únicamente con expresiones o con sentencias. Se puede decir que Fortran, Algol,
Pascal, C, etc., son lenguajes orientados a expresiones, mientras que COBOL y PL/1
están orientados a sentencias. Realmente, hay dos dominios disjuntos en los lenguajes
imperativos: el de las expresiones, que es simple, regular y jerárquico, y el de las senten-
cias, que está más influenciado por las características de la máquina. Ambos dominios
suelen cohabitar en un mismo lenguaje. Las expresiones se han encontrado útiles prin-
cipalmente porque son simples y jerárquicas, y pueden combinarse uniformemente para
construir expresiones más complejas. Así pues, las expresiones no sufren influencias de la
arquitectura Von Neumann.

EJEMPLO 1. Lenguaje Pascal

Programar la frase: «Si el contenido de la variable x es mayor que el contenido de la variable


y, entonces asignar a la variable v el valor true o false, según proceda». Se codificaría
como sentencia o como expresión en el lenguaje Pascal de la siguiente forma:

a) Sentencia condicional:
if x > y then v := true else v := false;

b) Expresión condicional:
v := x > y

Es decir, que si x = 4 e y = 2, entonces v = true.

132 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

En el ejemplo se observa que la expresión es más simple, elegante e independiente


del lenguaje que la sentencia, aunque es más críptica.

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.

EJEMPLO 2. Lenguaje C/C++

Por ejemplo, si se tiene la siguiente expresión en lenguaje C/C++:

x= ++y – b * c;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

quiere decir que primero se incrementa el valor de y, seguidamente se multiplica el conte-


nido de b por c y el resultado se resta del contenido de y. Este valor se asigna a la variable x.
Es decir, si y = 99, b = 5, c = 4, v será = 80.

En este ejemplo se observa, además de la asignación del valor de la expresión a la


variable x, que la variable y se incrementa en una unidad (efecto de lado) porque lleva implí-
cita la sentencia y = y + 1. Esto no sería admisible en una expresión puramente matemática.

En resumen, se puede señalar que el paradigma imperativo se encuadra en el tipo de


programación procedimental, en el que la secuencia de control, el concepto de variable
y la operación de asignación son sus componentes fundamentales. Por otra parte, el
algoritmo es el elemento activo utilizado para definir las acciones de un programa, y las
estructuras de datos del tipo variable, vector, registro, fichero, etc., son los elementos
pasivos sobre los que actúa el algoritmo.

En el siguiente epígrafe se describen los lenguajes de programación en general, y a


partir de la unidad didáctica 5 se verá con detalle el lenguaje C/C++ procedimental que
implementa este tipo de paradigma.

4. LENGUAJES DE PROGRAMACIÓN

Lenguaje de programación. Conjunto de símbolos y reglas sintácticas y semán-


ticas que definen su estructura y el significado de sus elementos y expresiones.

www.udima.es 133

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

El lenguaje de programación se utiliza para controlar el comportamiento físico y


lógico de una computadora. Consta de un léxico, una sintaxis y una semántica:

• Léxico. Conjunto de palabras que utiliza el lenguaje. Por ejemplo, en el len-


guaje C/C++, el léxico es la lista de palabras que se pueden utilizar en el
mismo.
• Sintaxis. Conjunto de reglas que indican cómo realizar las construcciones
del lenguaje. Por ejemplo, en el lenguaje C/C++ se dice que una sentencia
de asignación está formada por una variable, un signo igual, una expresión
y un punto y coma.
• Semántica. Conjunto de reglas que permiten determinar el significado de
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

cualquier construcción del lenguaje. Por ejemplo, en lenguaje C/C++ la cons-


trucción: nombre = nombre + 2; indica que es una instrucción de asignación
que asigna a la variable numérica su contenido incrementado en 2.

Un lenguaje de programación permite a un programador especificar de manera pre-


cisa sobre qué datos debe operar una computadora, cómo deben ser almacenados o trans-
mitidos estos datos y qué acciones debe tomar en una variada gama de circunstancias.

Atendiendo a su nivel de abstracción, se pueden clasificar en: lenguajes máquina,


lenguajes de bajo nivel y lenguajes de alto nivel.

4.1. LENGUAJES MÁQUINA

Los lenguajes máquina, denominados normalmente como «lenguajes en código


máquina», están clasificados como lenguajes de primera generación. Estos están escritos
en un lenguaje directamente legible por la máquina (la computadora), ya que sus ins-
trucciones son cadenas binarias (0 y 1). Se dice que los programas escritos en forma de
ceros y unos están en lenguaje máquina porque esa es la versión del programa que la
computadora realmente lee y sigue.

La estructura del lenguaje está totalmente adaptada a los circuitos de la máquina y la


programación es tediosa porque los datos se representan, como se ha dicho, por ceros y
unos. Es un lenguaje de muy bajo nivel. El conjunto de instrucciones codificadas en binario
es capaz de relacionarse directamente con los registros y circuitería del microprocesador
de la computadora y resulta directamente ejecutable por este, sin necesidad de otros pro-
gramas intermediarios. Los datos se referencian por medio de las direcciones de memoria
donde se encuentran y las instrucciones realizan operaciones simples. Estos lenguajes están
íntimamente ligados a la CPU y por eso no son transferibles. Tienen baja portabilidad.

134 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

Es posible escribir programas directamente en lenguaje máquina, pero las instruc-


ciones son difíciles de codificar y los programas resultan largos y laboriosos de escribir
y también de corregir y depurar.

4.2. LENGUAJES DE BAJO NIVEL

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.

Algunas características que lo diferencian del lenguaje máquina son:

• En lugar de direcciones binarias, usa identificadores como «suma»,


«total», «y», etc.
• Los códigos de operación se representan por mnemotécnicos. Ejemplo de
algunos códigos mnemónicos son: STO para guardar un dato, LOA para cargar
un dato en el acumulador, ADD para sumar un dato, INP para leer un dato,
STO para guardar información, MOV para mover un dato a un registro, END
para terminar el programa, etc.
• Permite el uso de comentarios entre las líneas de instrucciones.

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

permite la obtención de un código muy eficiente, ya que, al programar en ensamblador,


se trabaja con los registros de memoria de la computadora de forma directa.

EJEMPLO 3. Lenguaje ensamblador

Ejemplo de un programa en lenguaje ensamblador, con sintaxis Intel para procesadores


x86, es el siguiente conjunto de instrucciones que, ejecutado en un sistema operativo UNIX,
equivale a la función exit(0) (que significa que finalice el programa retornando el valor 0):

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)

4.2.1. El traductor de ensamblador

Figura 3. Proceso de traducción y ejecución de un programa

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

Para que la computadora pueda ejecutar un programa escrito en lenguaje ensam-


blador es necesario traducirlo al lenguaje máquina de la propia computadora. Esto se
realiza mediante un programa traductor, llamado ensamblador.

136 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

El traductor ensamblador, mediante un proceso sencillo de análisis y generación de


código, va analizando y traduciendo instrucción a instrucción del programa escrito en len-
guaje ensamblador al lenguaje máquina de la computadora. Durante el análisis, comprueba
la existencia de errores en el código fuente; es decir, si las instrucciones están bien codifi-
cadas. Si localiza algún error, emite un mensaje de error y no genera el código máquina;
en caso contrario, obtiene como resultado el programa escrito en el lenguaje del código
de la máquina. Seguidamente, el programa traducido a código máquina se ejecuta en la
propia computadora, la cual va leyendo los datos de entrada que solicita el programa y
proporcionando como salida los resultados. Evidentemente, durante la ejecución del pro-
grama, este puede finalizar en error (por ejemplo, el programa realiza una división por
cero) o proporcionar resultados incorrectos como consecuencia de que el algoritmo que
implementa el programa no sea el correcto, es decir, no resuelva el problema planteado.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

La figura 3 describe el proceso de traducción y ejecución de un programa escrito


en lenguaje ensamblador.

4.3. LENGUAJES DE ALTO NIVEL

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.

En un lenguaje de bajo nivel, cada instrucción corresponde a una acción ejecutable


por la computadora, mientras que, en los lenguajes de alto nivel, una instrucción suele
corresponder a varias acciones.

Las características más destacables son las siguientes:

• Independencia. De la arquitectura física de la computadora. Por tanto, no


es necesario conocer el hardware específico de la máquina para escribir un
programa.
• Portabilidad. Permiten que un mismo programa se ejecute en computa-
doras de diferentes arquitecturas.

La ejecución de un programa en lenguaje de alto nivel requiere, al igual que los


lenguajes de bajo nivel, una traducción al lenguaje máquina de la computadora donde
va a ser ejecutado, pero este proceso de traducción, como veremos más adelante, es más
complejo que para el caso de los lenguajes de bajo nivel.

www.udima.es 137

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Como se ha señalado anteriormente, una sentencia en un lenguaje de alto nivel da lugar,


al ser traducida, a varias instrucciones en lenguaje máquina. Los lenguajes de alto nivel son
más fáciles de aprender que los de bajo nivel porque están formados por palabras del len-
guaje natural; en concreto, del inglés. Por ejemplo, en los lenguajes dirigidos a sentencias
como es el lenguaje COBOL, uno de los primeros lenguajes de programación de alto nivel,
la sentencia: ADD A TO B GIVING C; es muy fácil de interpretar; significa «sumar el conte-
nido de A con el de B y el resultado ponerlo en la variable C». En cambio, en los lenguajes
dirigidos a expresiones como Pascal o C, la interpretación de una expresión no siempre es
tan fácil de entender. Por otra parte, al escribir un programa en un lenguaje de alto nivel
puede dar la sensación de que podemos escribir cada instrucción libremente, semejante a
la forma de escribir frases en un lenguaje natural y que la computadora lo va a entender.
Esto no es así, y las reglas lexicográficas, sintácticas y semánticas de cada lenguaje hacen
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.

A continuación presentamos un ejemplo en lenguaje Pascal y otro en lenguaje C,


que son dos lenguajes de alto nivel.

EJEMPLO 4. Lenguaje Pascal. Programar el MCD de dos números

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

EJEMPLO 5. Lenguaje C. Programar el MCD de dos números

#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. El traductor de los lenguajes de alto nivel

La implementación de un lenguaje es la manera en la que se ejecuta un programa


para una determinada combinación de software y hardware. Existen, básicamente, dos
maneras de implementar un lenguaje de alto nivel: compilación e interpretación.

4.3.1.1. Compilación

Compilación. Proceso de traducir un programa escrito en un lenguaje de alto nivel


a código objeto (normalmente, el código máquina).

Los programas traductores que realizan esta operación se llaman compiladores.


Como consecuencia del proceso de compilación, cada instrucción del programa fuente
(escrito en el lenguaje de alto nivel) produce varias líneas de código máquina.

www.udima.es 139

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Dependiendo del lenguaje fuente utilizado, el proceso de compilación puede nece-


sitar una fase previa de preprocesado, que consiste en ejecutar «directivas» escritas dentro
del código fuente que no son instrucciones propias del lenguaje. Por ejemplo, en el len-
guaje C, la directiva #define Contador 1000, que no es una instrucción del lenguaje, está
indicando al preprocesador que sustituya cada nombre simbólico con la palabra «Con-
tador» por el número 1.000.

En general, el proceso de compilación propiamente dicho consta de las siguientes


fases básicas:

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.

La sintaxis de un lenguaje de programación es el conjunto de reglas formales que


especifican la estructura de los programas pertenecientes a dicho lenguaje. En el caso del
ejemplo anterior, suma = valor * 5, la sintaxis del lenguaje C indica que la expresión está
bien formada, porque entre los elementos básicos de una expresión existen: los identifica-
dores (suma y valor), las constantes enteras sin signo (5) y los operadores (=, *). Y entre
los operadores, con sintaxis binaria infija, se encuentran la asignación (=) y el producto (*).

C) Análisis semántico

Es la fase posterior al análisis sintáctico y la última dentro del proceso de síntesis


de un lenguaje de programación. La semántica de un lenguaje de programación es el
conjunto de reglas que especifican el significado de cualquier sentencia sintácticamente

140 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

válida. El análisis semántico de un procesador del lenguaje es la fase encargada de detectar


la validez semántica de las sentencias aceptadas por el analizador sintáctico. En el caso
del ejemplo suma = valor * 5, el análisis semántico identifica que en la dirección de
memoria asociada al identificador suma se le va a asociar el resultado del producto del
valor asociado a la dirección de memoria valor, multiplicado por 5.

Durante el análisis semántico se comprueba que se satisfacen las siguientes


condiciones:

• Que todos los identificadores que aparecen en la expresión han sido


declarados.
• Que la subexpresión a la izquierda del signo igual es semánticamente válida.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• Que al tipo de identificador valor se le puede aplicar el operador de mul-


tiplicación. Un tipo registro declarado como struct en C, por ejemplo, no
sería válido.

En el caso del ejemplo anterior, deberá inferir el tipo resultante de la multiplicación


de valor * 5 y comprobar si este tipo es compatible con el tipo del identificador suma
para llevar a cabo la asignación. Por ejemplo, si suma fuese un string y el resultado de
la multiplicación un valor real, habría un problema de asignación.

D) Generador de código objeto

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).

E) Optimización del código objeto

Su objetivo es optimizar el código objeto preservando el significado del programa.


Los factores que hay que optimizar son, básicamente: la velocidad de ejecución, el tamaño
del programa y las necesidades de memoria. Para ello, se aprovechan las características
específicas de la computadora como la asignación de registros, el uso de modos de direc-
cionamiento de la computadora, aprovechamiento de la memoria caché, etc.

También se realizan optimizaciones locales en el código, tales como:

• Ejecución en tiempo de compilación para precalcular expresiones constantes


(con constantes o variables cuyo valor no cambia). Por ejemplo: i = 12 + 23;
→ i = 35.

www.udima.es 141

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

• Reutilización de expresiones comunes. Por ejemplo: a = b + c; e = b + c →


a = b + c; e = a.
• Cambio del orden de ejecución de ciertas instrucciones, etc.

La creación de un programa ejecutable por la computadora (un típico programa .exe


para Microsoft Windows) conlleva dos pasos. El primer paso es la compilación propia-
mente dicha, que acabamos de describir, y que traduce el código fuente escrito en un len-
guaje de alto nivel a un código de bajo nivel denominado código objeto (normalmente,
el código máquina, pero no directamente ejecutable por la computadora). El segundo
paso es el enlazado (del inglés linker), en el cual se enlaza el código objeto de todos los
ficheros y subprogramas que se ha mandado compilar junto con el código objeto de las
funciones que hay en las librerías del sistema para producir un programa ejecutable en
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

esa computadora. Es decir, durante el enlazado se genera un módulo ejecutable por la


computadora. En la figura 4 se describe el proceso de compilación, enlazado y ejecución
de un programa escrito en un lenguaje de alto nivel.

Figura 4. Proceso de compilación, enlazado y ejecución de un programa

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

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

La opción más común es compilar el programa obteniendo un módulo objeto, aunque


también puede ejecutarse a través de un intérprete informático.

La interpretación es otra forma alternativa, diferente a la de la compilación, para


traducir programas escritos en un lenguaje de alto nivel. En vez de traducir el programa
fuente y grabar en forma permanente el código objeto que se produce durante la compi-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.

Un programa escrito en un lenguaje compilado posee la ventaja de no necesitar un


programa que interprete sus instrucciones para ser ejecutado una vez que ha sido compi-
lado. Además, como solo es necesario su ensamblaje (si no está ya ensamblado), la eje-
cución se vuelve más rápida. Sin embargo, no es tan flexible como un programa escrito
en lenguaje interpretado, ya que cada modificación del archivo fuente (el archivo que se
va a compilar) requiere la compilación del programa para aplicar los cambios.

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

A continuación, se presenta en el cuadro 1 una breve lista de los lenguajes de pro-


gramación más conocidos de alto nivel (compilados o interpretados):

Cuadro 1. Lenguajes de programación de alto nivel

Lenguaje Principal área de aplicación Compilado/interpretado

Ada Lenguaje de sistemas y tiempo real Lenguaje compilado

ASP Desarrollo de sitios web dinámicos Lenguaje interpretado

ASP.NET Lenguaje ASP con tecnología .NET Lenguaje interpretado


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

BASIC Programación para fines educativos Lenguaje interpretado

BeanShell Lenguaje de scripts Lenguaje interpretado

C Programación de sistema Lenguaje compilado

C++ Programación de sistema orientado a objeto Lenguaje compilado

COBOL Administración Lenguaje compilado

Fortran Cálculo Lenguaje compilado

Java Programación orientada a objetos e internet Lenguaje interpretado

JavaScript Programación orientada a internet Lenguaje interpretado

JSP Programación de sitios web dinámicos Lenguaje interpretado

HTML Programación orientada a internet Lenguaje interpretado

MATLAB Cálculos matemáticos Lenguaje interpretado

Lisp Inteligencia artificial Lenguaje intermediario

Pascal Educación Lenguaje compilado

PHP Desarrollo de sitios web dinámicos Lenguaje interpretado

Perl Procesamiento de cadenas de caracteres Lenguaje interpretado

Python Desarrollo de sitios web dinámicos Lenguaje interpretado

Ruby Desarrollo de sitios web dinámicos Lenguaje interpretado

144 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

4.4. HISTORIA DE LOS LENGUAJES DE PROGRAMACIÓN

Para finalizar el contenido temático de la unidad didáctica, vamos a hacer un breve


repaso sobre la historia y evolución de los lenguajes de programación.

En la historia de los lenguajes de programación se da la paradoja de que la teoría


formal de estos lenguajes ha sido anterior al desarrollo práctico de los mismos. Así sucede
con el cálculo lambda, desarrollado por Alonzo Church, Max HL. Solis Villareal y Ste-
phen Cole Kleene en la década de 1930, y que es considerado como uno de los primeros
lenguajes de programación del mundo, incluso pese a que se tenía intención de modelar
la computación más que ser un medio para que los programadores describieran algo-
ritmos para un sistema informático.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Es en la década de los cuarenta cuando surgen los primeros lenguajes ensambla-


dores. Como hemos comentado, la relación con el lenguaje máquina es directa; por cada
instrucción mnemotécnica existe una instrucción en código binario y viceversa. Pero la
programación era complicada y difícil, porque se acercaba mucho a la forma de operar
de las computadoras pero no al lenguaje humano.

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).

Pero realmente, el primer lenguaje de programación ampliamente conocido y exi-


toso fue Fortran, desarrollado entre 1954 y 1957 por un equipo de investigadores en
IBM liderados por John Backus. El lenguaje Fortran introdujo muchas ventajas sobre el
ensamblador e hizo más claras las operaciones básicas. La idea era hacer la programa-
ción más cercana al lenguaje natural humano. El éxito de Fortran condujo a la creación
de un comité de científicos para desarrollar un lenguaje de programación «universal»;
el resultado de su esfuerzo fue, en 1958, ALGOL 58, que unía la sintaxis de Fortran y
mejoraba la notación, pero sus especificaciones eran muy extensas, por lo que se imple-
mentó un subconjunto del mismo denominado ALGOL 60.

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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 la década de 1960, el lenguaje Simula fue desarrollado por Ole-Johan Dahl y


Kristen Nygaardy; este lenguaje fue el germen de la orientación a objetos e introdujo
también el concepto de corrutina.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.

También surge, a principios de los años setenta, dentro de la lógica de predicados,


el lenguaje Prolog (Programmation en Logique), ideado en la Universidad de Aix-Mar-
seille por los profesores Alain Colmerauer y Phillipe Rousse. Se trata de un lenguaje de
programación dirigido al campo de la inteligencia artificial.

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).

En los años ochenta, un pequeño equipo de científicos en Xerox PARC, encabe-


zado por Alan Kay, creó el lenguaje Smalltalk basado en el Simula-67. El lenguaje
implementó la programación orientada a objetos. El concepto fue revolucionario y, así,
muchos lenguajes lo fueron incorporando, como el C, que con la orientación a objetos
paso a llamarse C++.

Posteriormente, apareció el lenguaje Java totalmente orientado a objetos, que, debido


al hecho de producir un código intermedio ejecutable en la mayor parte de las compu-
tadoras, utilizando un intérprete de Java, es actualmente el lenguaje más utilizado en el
desarrollo de aplicaciones basadas en internet.

Actualmente, los lenguajes se están orientando fundamentalmente al contenido mul-


timedia, a internet y a los dispositivos móviles.

146 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

Desde los inicios de internet fueron surgiendo diferentes lenguajes estáticos de


programación para desarrollar en la web. Con ellos se daba respuesta a las tendencias y
necesidades de las plataformas y a las diferentes demandas de los usuarios. A medida
que pasó el tiempo, las tecnologías fueron desarrollándose y surgieron nuevos problemas que
solucionar. Esto dio lugar al desarrollo de lenguajes de programación para la web de
tipo dinámico que permitían interactuar con los usuarios y utilizaban sistemas de bases
de datos.

A continuación se comentan algunos lenguajes de programación para la web:

• HTML. Realmente, HTML (acrónimo en inglés de HyperText Markup


Language; en español, lenguaje de marcas hipertextuales) no es un len-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

guaje de programación para la web, sino de representación de documentos.


Desde el surgimiento de internet se han publicado sitios web gracias al
lenguaje HTML. Es un lenguaje para representación de documentos está-
ticos para el desarrollo de sitios web que ha sido desarrollado por el World
Wide Web Consortium (W3C). Los archivos pueden tener las extensiones
.htm y .html.
• JavaScript. Este es un lenguaje interpretado, que fue creado por Brendan
Eich en la empresa Netscape Communications. Tradicionalmente, se venía
utilizando en páginas web HTML para realizar tareas y operaciones en el
marco de la aplicación únicamente cliente, sin acceso a funciones del ser-
vidor. Actualmente, la mayoría de los navegadores en sus últimas versiones
interpretan código JavaScript. El código JavaScript puede ser integrado
dentro de una página web.
Para evitar incompatibilidades, el W3C diseñó un estándar denominado
DOM (en inglés, Document Object Model; en su traducción al español,
modelo de objetos del documento), que es esencialmente una interfaz
de programación de aplicaciones que proporciona un conjunto estándar de
objetos para representar documentos HTML y XML; un modelo estándar
sobre cómo pueden combinarse dichos objetos, y una interfaz estándar para
acceder a ellos y manipularlos.
• PHP. Es un lenguaje de programación utilizado para la creación de sitios
web. PHP es el acrónimo de PHP Hypertext Preprocessor (inicialmente se
llamó Personal Home Page). Surgió en 1995, desarrollado por PHP Group.
PHP es un lenguaje de script interpretado en el lado del servidor y utilizado
para la generación de páginas web dinámicas, embebidas en páginas HTML
y ejecutadas en el servidor. La mayor parte de su sintaxis ha sido tomada de

www.udima.es 147

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

C, Java y Perl con algunas características específicas. Los archivos cuentan


con la extensión .php.
• JSP. Es un lenguaje para la creación de sitios web dinámicos, acrónimo de
Java Server Pages. Está orientado a desarrollar páginas web en Java. JSP
es un lenguaje multiplataforma, creado para ejecutarse del lado del servidor.
Fue creado por Sun Microsystems y comparte ventajas similares a las de
ASP.NET. Fue desarrollado para la creación de aplicaciones web potentes.
Posee un motor de páginas basado en los servlets de Java.
• Python. Es un lenguaje de programación creado en el año 1990 por Guido
van Rossum, sucesor del lenguaje de programación ABC. Python es compa-
rado habitualmente con Perl. Los usuarios lo consideran como un lenguaje
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

más limpio para programar. Permite la creación de todo tipo de programas


incluyendo los sitios web. Su código no necesita ser compilado, sino inter-
pretado. Es un lenguaje de programación multiparadigma, lo cual fuerza a
que los programadores opten por un estilo de programación particular: pro-
gramación orientada a objetos. Programación estructurada. Programación
funcional. Programación orientada a aspectos.
• Ruby. Es un lenguaje interpretado de muy alto nivel y orientado a objetos.
Desarrollado en el 1993 por el programador japonés Yukihiro «Matz» Mat-
sumoto. Su sintaxis está inspirada en Phyton, Perl. Ruby es un lenguaje
dinámico para una programación orientada a objetos rápida y sencilla. Se
distribuye bajo licencia de software libre (opensource).

Interesa destacar que en los últimos tiempos la evolución de la programación web


está más centrada en el desarrollo de frameworks cada vez más especializados que en la
creación de nuevos lenguajes.

148 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

 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

• Paradigma de programación. Modelo básico de construcción de programas


informáticos. Los paradigmas de programación son estilos de construcción
de programas que definen la estructura interna que va a tener el programa
y que será en función del tipo de problema que se quiere resolver.
• Lenguaje de programación. Conjunto de símbolos y reglas sintácticas y
semánticas que determinan la estructura y el significado de los elementos y
expresiones, de modo que definen un lenguaje para escribir programas en una
computadora. Estos lenguajes pueden estar escritos en el propio lenguaje de la
máquina, en un lenguaje simbólico próximo a la máquina, como puede ser un
lenguaje ensamblador, o en un lenguaje simbólico de más alto nivel próximo al
ser humano, como puede ser el C/C++ que se verá en las siguientes unidades.

 ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1

Para construir un programa, ¿qué tareas hay que desarrollar?

a) Estudiar el problema, diseñar el programa e implantarlo en el ordenador.


b) Reconocer que el problema se puede programar, especificar los requisitos
del problema, analizarlos, diseñar el programa, codificarlo en un lenguaje
de programación, ponerlo en funcionamiento.

www.udima.es 149

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

c) Estudiar si el problema se puede programar, analizar los requisitos del pro-


blema, implementar el programa e implantarlo.
d) Estudiar si el problema se puede programar, especificar qué es lo que debe
hacer el programa, analizar los requisitos del programa, diseñar la arqui-
tectura del programa, implementar el programa e implantarlo.

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

Hemos diseñado un programa, a partir del conocimiento experto de un médico, que,


dados los síntomas de un paciente, pronostica su enfermedad. ¿En qué tipo de paradigma
se encuadraría este programa? ¿Y por qué?

Enunciado 4

Utilizando la técnica del paradigma demostrativo, explicar brevemente cómo cons-


truiría un programa que jugara, por ejemplo, a las damas.

Enunciado 5

¿Cuál de las siguientes afirmaciones es correcta?

a) El lenguaje ensamblador está más próximo a la máquina, por lo que es sen-


cillo trabajar con él, pero necesita un traductor a código máquina.
b) El lenguaje de alto nivel es más potente que el ensamblador pero no utiliza
todos los recursos del lenguaje ensamblador. Hay operaciones que solo se
pueden hacer en el lenguaje ensamblador.
c) El lenguaje de alto nivel es más potente que el ensamblador pero necesita
un proceso de compilación para obtener el código máquina.
d) El lenguaje ensamblador es más eficiente que el de alto nivel y permite pro-
gramar en un tiempo razonable cualquier tipo de problema.

150 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

Solución 1

d) Estudiar si el problema se puede programar, especificar qué es lo que debe


hacer el programa, analizar los requisitos del programa, diseñar la arqui-
tectura del programa, implementar el programa e implantarlo.

Solución 2

Se utilizaría un paradigma procedimental u operacional, bien el paradigma impe-


rativo o el orientado a objetos. El lenguaje Lisp no es apropiado para este tipo de pro-
blemas; es propio de la programación declarativa y del campo de la inteligencia artificial.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Aquí sería apropiado el lenguaje C/C++.

Solución 3

Se encuadraría en el paradigma declarativo porque, para construir este programa,


habría que diseñar hechos (por ejemplo, el paciente tiene más de 65 años, el paciente no
está vacunado de la gripe) y reglas lógicas, en las que, a partir de unos hechos, se infieran
otros (por ejemplo, si el paciente tiene fiebre, mal estado, le lloran los ojos y está cons-
tipado, la probabilidad más alta es que tenga gripe).

Solución 4

Se plantearían varios juegos de ensayo de partidas de damas con diferentes finales


para uno y otro jugador, en las que se ganara y se perdiera. Con estos juegos de ensayo se
construiría un programa que aprendiera de estas partidas a conocer cuál es el movimiento
más prometedor en cada jugada. Posteriormente, se validaría el programa realizando
otros juegos de ensayo de partidas de damas para ver cómo se comporta el programa. Si
los resultados son los esperados, se daría por finalizado el programa. En caso contrario,
se tendría que depurar.

Solución 5

b) El lenguaje de alto nivel es más potente que el ensamblador pero no utiliza


todos los recursos del lenguaje ensamblador. Hay operaciones que solo se
pueden hacer en el lenguaje ensamblador.

www.udima.es 151

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

3. Analizar las características generales del lenguaje de programación lógica


Prolog o del lenguaje funcional Lisp. Resumirlas en una página.
4. En las cinco unidades didácticas siguientes se va a estudiar el lenguaje C/
C++ en su componente procedimental, no en la orientada a objetos. Ana-
lice ahora las características de un lenguaje procedimental como Pascal para
poder posteriormente descubrir las diferencias que existen con el C/C++.
Resumirlas en una página.
5. Buscar información que permita decidir cuáles serían los lenguajes de progra-
mación más apropiados para realizar: aplicaciones para gestión de oficinas,
complejos cálculos científicos, un sistema experto en medicina, un simulador
de vuelo, manipulación de bases de datos y control de un robot industrial.

 REFERENCIAS BIBLIOGRÁFICAS
Básica

Alonso, F. y Segovia, F. J. Entornos y metodologías de programación. Madrid: Paraninfo, 1995.


Ambler, A. L.; Burnett, M. M. y Zimmerman, B. A. Operational versus Definitional: A Perspective on Pro-
gramming Paradigms. IEEE Computer, 1992.
«Aplicación web». Wikipedia. Disponible en <http://es.wikipedia.org/wiki/Aplicaci%C3%B3n_web#
Lenguajes_de_programaci.C3.B3n>.

152 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

F. Alonso y D. Lizcano La programación y los lenguajes informáticos

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

Powered by TCPDF (www.tcpdf.org)


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Powered by TCPDF (www.tcpdf.org)


Sumario │

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

palabras reservadas y los comentarios en este lenguaje.

Al finalizar el estudio de esta unidad didáctica, el lector debe:

• Conocer cómo surgió el lenguaje C++ y quién fue su principal inventor.


• Entender las características generales de C++.
• Conocer cuáles son los elementos básicos del lenguaje C++.
• Conocer los aspectos generales de las funciones y de la función principal.
• Saber cuál es la estructura general de un programa C++.
• Conocer las palabras reservadas del lenguaje.
• Conocer las dos formas de escribir comentarios en C++.

156 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El lenguaje imperativo C++

1. INTRODUCCIÓN

C++ es un lenguaje de programación relativamente moderno en continuo crecimiento


y desarrollo. Al igual que el lenguaje C, C++ no está ligado a ningún sistema operativo en
particular ni a ninguna arquitectura concreta. Surge como resultado del trabajo de Bjarne
Stroustrup en los Laboratorios Bell de AT&T.

Es un lenguaje orientado a objetos multipropósito de programación general basado


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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:

• Una mejora del lenguaje C.


• Un soporte para la abstracción de datos, tanto para tipos de datos como para
funciones.
• Un soporte para la programación orientada a objetos, ofreciendo capaci-
dades de encapsulación de datos, herencia y polimorfismo o sobrecarga.

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++.

A lo largo de las restantes unidades didácticas se van a describir las características


básicas del C++ y se proporcionará una visión global de este lenguaje de programación
en lo que respecta a la programación imperativa (sin mencionar los temas relacionados
con la orientación a objetos, como las clases, y características avanzadas).

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

El lenguaje C++ tiene básicamente su origen en el lenguaje de programación C. A su


vez, una gran parte del lenguaje C proviene del lenguaje BCPL (diseñado en 1967 por
Martin Richards) a través del lenguaje B escrito en 1970. C fue desarrollado por los
mismos técnicos que crearon el sistema operativo UNIX. Ken Thompson realizó varias
versiones del UNIX, escribiéndolo finalmente en un lenguaje que denominó B. Otro pro-
gramador, Dennis Ritchie, modificó con profundidad el B y creó en 1973 otro lenguaje
al que llamó C, en el que se volvió a escribir el UNIX.

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 1981, se modifica el lenguaje C mediante la inclusión de clases y se crea el len-


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

guaje denominado C con clases.

En 1984, el C con clases es rediseñado y extendido incorporando, principalmente,


funciones virtuales y la sobrecarga de operadores. Se comienza a utilizar el C++ inter-
namente en AT&T, fruto del trabajo de Bjarne Stroustrup.

En 1985, se pone a disposición de las universidades Cfront Release E, un traductor


de código C++ a C que podía posteriormente ser compilado con un compilador de C.
Bjarne Stroustrup escribe el libro The C++ Programming Language. En el mismo año
se da libre acceso al AT&T C++ Translator 1.0.

En 1986, se licencia a otros vendedores el AT&T C++ Translator 1.1, que incorpora
punteros a miembros y la palabra protected.

En 1987, el AT&T C++ Translator 1.2 amplía las posibilidades de la sobrecarga.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El lenguaje imperativo C++

En 1997, se publica la tercera edición del libro The C++ Programming Language,
de Bjarne Stroustrup.

En 1998, se aprobó el estándar internacional ISO/ANSI del lenguaje C++ (Informa-


tion Technology-Programming Languages-C++, ANSI/ISO/IEC 14882:1998), aunque
una corrección técnica fue aprobada en 2003. El estándar con la corrección técnica fue
también publicado en 2003 por Bjarne Stroustrup conjuntamente con el British Standards
Institute en el libro The C++ Standard: Incorporating Technical Corrigendum N.º 1.
Posteriormente, ISO ha seguido publicando revisiones del estándar en 2011 y 2014.

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

3. CARACTERÍSTICAS GENERALES DE C++

A continuación se resumen brevemente las principales características del len-


guaje C++:

• Cuenta con un núcleo de pequeño tamaño (tiene menos de 75 palabras


reservadas frente a otros lenguajes como COBOL, que tiene alrededor de
400) y, por tanto, es más fácil de aprender.
• Facilita una rápida ejecución de los programas. Debido a su relativo
bajo nivel y a que los compiladores suelen optimizar bastante bien el código
generado.
• Es muy flexible. Permite generar un código compacto y eficiente.
• Es transportable. Un programa escrito en C++ para una determinada arqui-
tectura de ordenador puede ser transportado a ordenadores de otro tipo sin
necesidad de realizar grandes modificaciones en el código, siempre y cuando
no se haya desarrollado código específico para un tipo de arquitectura con-
creta y se haya seguido el estándar del lenguaje sin usar librerías propieta-
rias del compilador.
• Es estructurado. Posee sentencias de control de flujo (selección, iteración,
funciones, etc.) y permite definir tipos de datos estructurados.
• Posibilidad de realizar programación modular. Dividiendo los programas
en varios ficheros más manejables, para después enlazarlos juntos en un
único fichero ejecutable.

www.udima.es 159

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

• Posibilidad de manejar punteros y memoria dinámica. De forma que


permite al programador un importante control a bajo nivel de la memoria,
así como controlar eficientemente su uso. No obstante, el uso incontrolado
de punteros puede resultar peligroso para programadores inexpertos o si
no se presta suficiente atención al código desarrollado. El uso de caracte-
rísticas de bajo nivel, aunque permitido, no resulta aconsejable a menos
que sea estrictamente necesario para resolver un determinado problema.
• Es de formato libre. Es decir, puede escribirse con la forma o estilo propio
del programador, con varias sentencias por línea, líneas en blanco, espacios
donde se desee, comentarios, etc. Por tanto, el lenguaje ofrece total libertad
al programador en la forma de escribir los programas. Sin embargo, hay
que manejar esta libertad con un especial cuidado, respetando una cierta
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

homogeneidad y dotando de claridad al código para evitar que el programa


desarrollado resulte indescifrable incluso para el propio autor. Por tanto,
para facilitar posteriormente su comprensión, resulta conveniente distri-
buir el código de una forma clara y estructurada.
Además, para los programadores en C, el lenguaje C++ puede ayudarles
a desarrollar nuevos programas más rápidamente (reutilizando fragmentos
de código escrito en C), crear nuevos tipos de manera más sencilla, realizar
una gestión de memoria más transparente y fácil, desarrollar programas con
menos errores (debido a la sintaxis un poco más estricta y las comproba-
ciones de tipos) y utilizar el mecanismo de la ocultación de la información
para obtener programas más robustos.

4. ELEMENTOS BÁSICOS DE C++

En este epígrafe se van a comentar los elementos principales de un programa C++


haciendo referencia a las unidades didácticas en las que se estudiarán con más detalle.

Antes de comenzar, es necesario mencionar que C++ es un lenguaje que se carac-


teriza por ser case-sensitive, es decir, se diferencia entre mayúsculas y minúsculas en
los nombres de variables, tipos, funciones, etc. Por tanto, las palabras siguientes se con-
sideran tres palabras distintas:

nombre Nombre NOMBRE

160 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El lenguaje imperativo C++

El elemento básico de C++ es la sentencia y se verá detenidamente en la unidad


didáctica 7.

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.

Algunos ejemplos de sentencias son las siguientes:

• x= 8; (se asigna el valor 8 a la variable x).


• imprime (i + 1); (se llama a la función imprime enviándole como dato el
valor de i + 1).

Las sentencias se ejecutan secuencialmente, según aparecen en el fichero del pro-


grama fuente, una detrás de otra. Existen sentencias especiales en el lenguaje, deno-
minadas «sentencias de control de flujo», que permiten repetir la ejecución de ciertas
sentencias o ejecutar solamente algunas sentencias basándose en una determinada con-
dición. Este tipo de sentencias de control de flujo se estudiarán en la unidad didáctica 7.

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

int a;
float b;

Bloque. Conjunto de varias, una o ninguna declaraciones o sentencias (en cualquier


orden) encerradas entre llaves: { }.

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;]
}

Uno de los elementos más potentes de C++ es la función (que se estudiará en la


unidad didáctica 8).

Función. Fragmento de programa que, dados unos parámetros de entrada, realiza


una determinada acción y devuelve el correspondiente resultado.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El lenguaje imperativo C++

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

5. ESTRUCTURA DE UN PROGRAMA C++

Las partes lógicas de un programa son, en general, las siguientes (aunque no


necesariamente tienen que aparecer siempre en este mismo orden ni agrupadas de esta
manera):

• Directivas de preprocesador. El preprocesado es una tarea que se realiza


previamente a la compilación propiamente dicha; el preprocesador se estu-
diará en la unidad didáctica 10.
• Tipos de datos. Tipos permiten representar distintos datos para contener
informaciones diferentes; los tipos de datos básicos se estudiarán en la uni-
dad didáctica 6 y los tipos avanzados de datos se estudiarán en la unidad
didáctica 9.
• Datos globales. Datos que serán visibles a todas las funciones.
• Declaración de funciones o prototipos. Las funciones se estudiarán dete-
nidamente en la unidad didáctica 8.
• Programa principal (main). Función especial que se ejecuta al ejecutar el
programa.
• Definición de funciones. Se especifica qué es lo que hará cada función; se
verá en la unidad didáctica 8.

www.udima.es 163

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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 cada uno de esos ficheros se agrupan declaraciones y funciones. Además, en todo


programa, uno de los ficheros deberá contener la definición de la función main.

En el caso de un programa con varios ficheros, suelen existir dos ficheros por cada
módulo:

• El primero de ellos se denomina fichero de cabecera (suele tener extensión .h)


y contiene la declaración de todos los tipos, variables y funciones del módulo.
• El segundo de ellos se denomina fichero de implementación (suele tener
extensión .cpp o .cc) y en estos ficheros se escribe la definición de las fun-
ciones (se especifica su código).

A continuación se va a mostrar un ejemplo completo con tres ficheros: un módulo


(ficheros cuad.h y cuad.cpp), que contiene una función que calcula el cuadrado de un
número, y el programa principal (fichero princ.cpp), que contiene la función main y que
se encarga de pedir al usuario un número y escribir su cuadrado en pantalla.

164 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El lenguaje imperativo C++

• Fichero cuad.h. Lo único que contiene la cabecera del primer módulo es la


declaración de la función Cuadrado, que recibe un número real y devuelve
otro real:

// Función que devuelve el cuadrado de un número
float Cuadrado(float); // prototipo de la función

• Fichero cuad.cpp. El fichero de implementación del primer módulo incluye


su fichero de cabecera y después muestra la codificación de la función
Cuadrado:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

#include "cuad.h"
// Implementación de Cuadrado
float Cuadrado(float n)
{
return n * n;
}

• Fichero princ.cpp. El fichero que contiene el programa principal incluye


la cabecera del otro módulo y se encarga de la interacción con el usuario:

#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;
}

El proceso de compilación de un programa en C++ pasa por las siguientes fases:

• 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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

• Compilación. Cada fichero .cpp de un programa se compila por separado


y se genera un fichero en código objeto (extensión .obj o .o).
• Montado (linking) o enlazado. Se juntan todos los ficheros objeto y se
incorporan las funciones de librería utilizadas para construir el programa
ejecutable.

La figura 1 resume este proceso de compilación.

Figura 1. Procesado de compilación de C++


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

� File1.o File2.o File3.o File4.o


File7.o
MONTADO


Ejecutable

6. PALABRAS RESERVADAS DE C++

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El lenguaje imperativo C++

Cuadro 1. Conjunto de palabras reservadas

asm auto bool break case

catch char class const const_cast

continue default delete do double

dynamic_cast else enum explicit export

extern false float for friend

goto if inline int long


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

mutable namespace new operator private

protected public register reinterpret_cast return

short signed sizeof static static_cast

struct switch template this throw

true try typedef typeid typename

union unsigned using virtual void

volatile wchar_t while

Cuadro 2. Palabras reservadas como representaciones alternativas de algunos operadores

and and_eq bitand bitor compl not

not_eq or or_eq xor xor_eq

En los cuadros 1 y 2 se muestra el conjunto de palabras reservadas del lenguaje. Las


palabras del cuadro 2 son representaciones alternativas de ciertos operadores que tam-
bién son reservadas y, por tanto, no se pueden usar con otro significado. A lo largo de
las distintas unidades didácticas se verá el significado de muchas de ellas. Como puede
observarse, todas las palabras reservadas del lenguaje van escritas en minúsculas. Para
facilitar su identificación, en los ejemplos de código C++ se representarán en negrita.

www.udima.es 167

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

7. COMENTARIOS EN C++

Los comentarios de un lenguaje de programación se suelen utilizar para dar una


explicación, en lenguaje natural, de qué es lo que realiza un fragmento de código, por
qué se ha escrito así, qué significado tiene, etc. Es decir, los comentarios son necesa-
rios para aclarar el significado del código fuente, para aumentar su legibilidad y, por
tanto, son ignorados por el compilador que, directamente, se los saltará sin hacer nada
con ellos. En C++ se pueden colocar comentarios en cualquier parte del código en el que
pueda ir un espacio. Hay dos formas o notaciones para indicar un comentario:

• Comentarios de bloque (también llamados comentarios estilo C). Se


indica un bloque de comentarios identificando su principio con los carac-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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 */

• Comentarios de línea (también llamados comentarios estilo C++). Se


indica un comentario de línea identificando su principio mediante los carac-
teres //. El comentario acaba cuando finaliza la línea, por lo que no existen
unos caracteres específicos para indicar el final del comentario. El comen-
tario de línea puede ocupar toda la línea o solo parte de ella (en este caso,
situándolo tras código C++).

// 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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El lenguaje imperativo C++

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.

Además, muchas veces se puede evitar un comentario si se utilizan nombres lo sufi-


cientemente significativos a la hora de declarar una variable. En lugar de declarar una
variable c, sería más explicativo declarar la variable contador.

www.udima.es 169

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

tipos de datos y funciones.


• Un programa en C++ consta de directivas de preprocesador, tipos de
datos, datos globales, declaraciones y definiciones de funciones.
• Todo programa debe tener una función especial denominada main. Esta
función es la que se ejecutará cuando lo haga el programa.
• C++ permite la programación modular, colocando las declaraciones en
ficheros de cabecera y el código fuente en ficheros de implementación.
• C++ dispone de un conjunto de menos de 75 palabras reservadas que solo
pueden utilizarse para lo que han sido diseñadas.
• C++ tiene dos tipos de comentarios: comentario de bloque (con /* y */)
y comentario de línea (con //).

 ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1

¿A quién se considera el padre del lenguaje C++?

a) Kernighan y Ritchie.
b) Bjarne Stroustrup.

170 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El lenguaje imperativo C++

c) Ken Thompson.
d) ANSI.

Enunciado 2

¿Cuáles de los siguientes lenguajes tienen un núcleo común con C++?

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?

a) Permite declarar variables.


b) Es cualquier instrucción ejecutable.
c) Las sentencias acaban en punto y coma.
d) Las asignaciones y las llamadas a una función son ejemplos de sentencias.

Enunciado 4

¿Cuáles son las partes de un programa C++?

a) Declaraciones, sentencias y funciones.


b) Preprocesador, declaraciones de tipos de datos, de datos globales y de fun-
ciones y definición de funciones (una de ellas llamada main).

www.udima.es 171

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

c) Un programa está compuesto por varias funciones; una de ellas es la fun-


ción main.
d) Un programa está compuesto por un fichero de cabecera y un fichero de
implementación.

Enunciado 5

¿Cuál de las siguientes frases en relación con las palabras reservadas es falsa?

a) Una palabra reservada no se puede usar como nombre de variable o función.


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

b) El lenguaje C++ tiene menos de 75 palabras reservadas.


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.
d) Algunas de las palabras reservadas de C++ son: if, while, and, int, void,
private, new, for, else, break, const.

172 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El lenguaje imperativo C++

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

a) Permite declarar variables.

Solución 4

c) Un programa está compuesto por varias funciones; una de ellas es la fun-


ción main.

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

3. De todas las características generales de C++ explicadas en el epígrafe 3 de


esta unidad, seleccionar las dos que se consideren más importantes y justi-
ficar la decisión.
4. Comparar las palabras reservadas de C++ con las de otro lenguaje de pro-
gramación e indicar qué palabras de C++ también se encuentran en ese otro
lenguaje.
5. Buscar en internet un fragmento de programa sencillo en C++ (entre 50 y
200 líneas de código) e identificar todos los comentarios que aparecen, indi-
cando de qué tipo son y si están adecuadamente realizados.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

 REFERENCIAS BIBLIOGRÁFICAS
Básica

Alonso, F. et al. Programación sin secretos. Madrid: Cultural, 1999.


C++ FAQ. Disponible en <https://isocpp.org/faq>.
Ellis, M. A. y Stroustrup, B. The Annotated C++ Reference Manual. Addison-Wesley, 1991.
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

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

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

4. Tipos básicos de datos


4.1. Tipo entero
4.2. Modificadores de tipo
4.3. Tipo real
4.4. Tipo carácter
4.5. Tipo lógico
4.6. Tipo vacío

www.udima.es 175

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

5.5. Operadores y expresiones de asignación


5.6. Operadores y expresiones sobre bits
5.6.1. Operador complemento a uno
5.6.2. Operadores lógicos de bits
5.6.3. Operadores de desplazamiento
5.6.4. Operadores de asignación con manipulación de bits
5.7. Operadores y expresiones para el manejo de punteros
5.7.1. Operador dirección
5.7.2. Operador indirección
5.8. Otros operadores
5.8.1. Operadores paréntesis
5.8.2. Operador condicional
5.8.3. Operadores signo
5.8.4. Operadores de incremento y decremento
5.8.5. Operador tamaño
5.8.6. Operador de conversión de tipos
5.8.7. Operador coma
5.8.8. Operadores de acceso a miembros
5.8.9. Operador de acceso a vectores
5.8.10. Operador de alcance
5.8.11. Operadores «new» y «delete»

Conceptos básicos
Actividades de autocomprobación
Actividades de repaso
Referencias bibliográficas

176 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

 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

Al finalizar el estudio de esta unidad didáctica, el lector debe:

• Conocer el concepto de constante y cuáles son los tipos de constantes de


los que dispone el lenguaje.
• Conocer el concepto de variable y aprender cómo se puede declarar una
variable.
• Aprender los tipos elementales del lenguaje.
• Conocer los distintos operadores que tiene C++, su funcionamiento y su
uso.
• Conocer cómo utilizar cada uno de los operadores.
• Conocer la precedencia y asociatividad de los operadores.

www.udima.es 177

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.).

En primer lugar, se explicarán en esta unidad didáctica los operandos, centrándose


principalmente en las constantes (enteras, reales, carácter, cadena, etc.) y las variables
(declaración y uso). Seguidamente, se explicarán los tipos básicos de datos existentes en
el lenguaje, de tal forma que cada variable ha de pertenecer a un tipo dado. Finalmente,
se detallará el funcionamiento de los operadores.

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.

Constantes. Permiten la representación de aquellos valores que nunca van a variar


a lo largo de la ejecución del programa (de ahí su nombre).

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

Seguidamente se van a estudiar todos ellos, conjuntamente con las distintas nota-
ciones existentes en las que se puede representar cada tipo de constante.

2.1. CONSTANTES ENTERAS

En un programa pueden aparecer diferentes tipos de números para representar dis-


tintos valores necesarios para la lógica de dicho programa. El primer gran grupo de
números lo forman los números enteros (es decir, números sin parte decimal).

Pueden encontrarse multitud de ejemplos de constantes enteras habituales:


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• El año del Descubrimiento de América: 1492.


• El número de bytes existentes en un kilobyte: 1.024.
• El número de cromosomas de un ser humano: 46.
• El número de meses de un año: 12.
• El número de metros que hay en un kilómetro: 1.000.

La manera más habitual de representar el valor de una constante entera es la misma


forma en la que se representan en la vida cotidiana, es decir, mediante una secuencia
de dígitos que van desde el 0 al 9. Esta manera de representar los números enteros se
denomina decimal, puesto que se basa en diez dígitos; o dicho de otra forma, porque se
representan los valores en base 10.

El significado de un valor en base 10 es como sigue. El valor verdadero de cada


dígito se obtiene según la posición que ocupa dentro del número. Este valor se cal-
cula contando su posición empezando por la derecha, siendo la primera posición cero.
Seguidamente, el valor del dígito se multiplica por 10 (la base) elevado a la potencia
indicada por su posición dentro del número. Finalmente, se suman todos los valores así
obtenidos y se consigue el valor del número.

Así, el valor del número 8.642 se obtiene de la siguiente forma:

2 * 100 + 4 * 101 + 6 * 102 + 8 * 103 =


2 * 1 + 4 * 10 + 6 * 100 + 8 * 1.000 =
2 + 40 + 600 + 8.000 = 8.642

www.udima.es 179

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

Seguidamente, se escriben algunos ejemplos de constantes enteras decimales:

1492  0  1  48  666  12345  10  2009  88  10000  1024

Como se observa, en el lenguaje C++ (como en la mayoría de los lenguajes de pro-


gramación) no se pueden utilizar los puntos de millar (pues el punto tiene otro significado
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

distinto, como se verá posteriormente, basado en la notación inglesa de los números).

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.

Una constante entera también puede ir precedida de un signo (el operador - o el


operador +). En dichos casos, entonces se considera un número negativo o positivo, res-
pectivamente. Evidentemente, un número con el signo + es equivalente a dicho número
sin ningún operador (es decir, que escribir +5 es lo mismo que escribir 5).

Algunos ejemplos de constantes enteras decimales con signo serían:

+1492  -0  -1 +48 -666 +12345 -10 2009  -10000 +1024 

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

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).

En la notación octal, en la cual la base utilizada es 8 (en lugar de usar la base 10


de la notación decimal), se utilizan únicamente ocho dígitos, desde el 0 hasta el 7, para
representar los números.

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.

A continuación se muestran algunos ejemplos de constantes enteras octales:

02724  -01  0  +060  -01232  030071  -012  +03731  023420  02000

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

La última de las notaciones de las que dispone C++ es la notación hexadecimal,


en la cual la base utilizada es 16 (en lugar de usar la base 10 de la notación decimal o
la base 8 de la notación octal). Se utilizan dieciséis dígitos, los dígitos desde el 0 hasta
el 9 y los dígitos hexadecimales desde la A hasta la F (tanto en minúsculas como en
mayúsculas), para representar los números. Estos nuevos dígitos hexadecimales tienen
el siguiente valor:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

A B C D E F

10 11 12 13 14 15

La forma para obtener el valor de una constante entera hexadecimal es análoga a


las vistas para las notaciones decimal y octal, excepto en que se usa la base 16 en vez
de la base 10 u 8. De esta manera, cada dígito se multiplica por la base (16) elevada a la
potencia indicada por la posición que ocupa dicho dígito dentro del número empezando
por 0 desde la derecha. Por ejemplo, el valor decimal del número hexadecimal 21C2 se
podría calcular de la siguiente manera:

2 * 160 + C * 161 + 1 * 162 + 2 * 163 =


2 * 1 + 12 * 16 + 1 * 256 + 2 * 4.096 =
2 + 192 + 256 + 8.192 = 8.642

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).

En C++, si se desea representar un número en notación hexadecimal, hay que uti-


lizar obligatoriamente como prefijo el dígito cero seguido de una letra equis (0x). Es
decir, todas las constantes enteras que comiencen por un cero y una equis serán números
en notación hexadecimal y, por tanto, podrán emplearse los dígitos entre el 0 y el 9 y
entre la A y la F. De igual forma, también los números hexadecimales pueden ir prece-
didos de un signo.

182 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

A continuación se muestran algunos ejemplos de constantes enteras hexadecimales:

0x5D4  -0x1  0x0  +0x30  -0x29a  0x3039  -0xA  +0x7D9  0x2710  0x400

Como ya se ha comentado, con estas tres notaciones se pueden representar números


enteros según las limitaciones o rangos impuestos por el entorno de desarrollo (normal-
mente, por el compilador). Como estas limitaciones pueden dificultar la elaboración de
ciertos programas que necesitan emplear números mayores, el lenguaje C++ ofrece dos
modificadores que pueden utilizarse con los números enteros y permiten obtener nuevos
tipos de constantes enteras: enteros sin signo, enteros de alta precisión y enteros sin signo
de alta precisión. Estos tipos se pueden aplicar a un entero en cualquiera de las tres nota-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

ciones estudiadas anteriormente.

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.

A continuación se muestran algunos ejemplos de constantes enteras sin 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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

A continuación se muestran algunos ejemplos de constantes enteras de alta precisión:

-0xFE65D4L  1L  0l  9344730L  0x29aL 


-12345L  10L  2009l  10000000L  -40000L

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.

Finalmente, mediante la combinación conjunta de ambos sufijos en una misma


constante, puede obtenerse una constante entera de alta precisión sin signo. Siguiendo
con el ejemplo anterior, si el compilador usara 4 bytes para representar los enteros de
alta precisión sin signo, los valores posibles de este tipo de constantes irían desde el 0
hasta el 4.294.967.295 (es decir, 232 – 1).

A continuación se muestran algunos ejemplos de constantes enteras de alta preci-


sión sin signo (nótese que los sufijos U y L pueden colocarse en cualquier orden):

0xFE65D4LU  1UL  0lu  9344730uL  0x29aLu


12345uL  10Ul  2009lu  10000000LU  40000Lu

2.2. CONSTANTES REALES

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:

• El valor de la constante π: 3,1415926.


• El número de Avogadro: 6,0221367 * 1023.

184 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

• La fuerza de gravedad de la Tierra: 9,8066.


• El número de centímetros que mide una pulgada: 2,54.
• La masa del electrón: 9,1093897 * 10-31.

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.

Seguidamente, se escriben algunos ejemplos de constantes reales:

3.1415926  -9.8066  2.54  0.0


0.1  .5  35.95  50.  +98.76

La segunda de las notaciones para representar números reales es la notación cientí-


fica, que permite representar números muy grandes o números muy pequeños utilizando
para ello potencias de 10 (tanto positivas como negativas). Para representar un número
real en notación científica, en el lenguaje C++ se escribe el número poniendo la parte
entera, un punto, la parte decimal, una letra E (mayúscula o minúscula, que representa la
potencia de 10), un signo opcional y un número entero (que representa el exponente de
10). Al igual que en la otra notación, bien la parte entera, bien la parte decimal, puede
omitirse; e incluso, al omitir la parte decimal también puede omitirse el punto. Asi-
mismo, el número real puede ir precedido de un signo, tanto positivo como negativo.

Seguidamente, se escriben algunos ejemplos de constantes reales en notación


científica:

.31415926e-1 (0,31415926 * 10-1 = 3,1415926)  -6.023E23 (6,023 * 1023)


-.24680E3 (– 0,2468642 * 103 = – 246,8642)  5e15 (5 * 1015 = 5000000000000000,0)
+1.5e-9 (1.5 * 10-9 = 0,0000000015)  9.e-1234 (9 * 10-1234)

www.udima.es 185

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Por omisión, el rango de valores de las constantes reales (independientemente de su


notación) se denomina en C++ como double, y los compiladores suelen utilizar una pre-
cisión de los valores lo suficientemente elevada para la mayor parte de las operaciones
necesarias. No obstante, el lenguaje dispone de dos modificadores que permiten alterar
la precisión de los números reales, al igual que ocurría con las constantes enteras.

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).

Seguidamente, se escriben algunos ejemplos de constantes reales con baja precisión:


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

3.1415926f  -9.80665F  2.54f  0.0f  -0.1F  .5F  50.f 


+98.7626e-1f  6.023E23F  -.246E3f  5e11f  +1.5e-9f

Y, finalmente, el último modificador utilizado en C++ sobre los números reales es el


sufijo L (tanto mayúscula como minúscula), que constituye una indicación al compilador
para que use números con mayor precisión, es decir, que se amplíe aún más el rango de
valores posibles. Con este modificador, el tipo de real obtenido se denomina long double.

Seguidamente, se escriben algunos ejemplos de constantes reales con alta precisión:

3.1415926l  -9.80665L  2.54L  0.0L  0.1l


+98.76126e-1L  -6.023E23L  5e2468L  +1.5e-2222L

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.

2.3. CONSTANTES LÓGICAS

C++ dispone también de constantes lógicas, que permiten representar un valor de


certeza o falsedad. Estas constantes se escriben mediante las palabras reservadas true

186 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

(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.

En cualquier caso, principalmente por mejorar la claridad y legibilidad del código


fuente, se recomienda fervientemente utilizar las constantes lógicas en vez de utilizar
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

constantes numéricas cuando se quiera expresar un valor lógico.

2.4. CONSTANTES CARÁCTER

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).

El carácter barra inversa \ (back-slash) se utiliza para introducir una «secuencia de


escape» que permite la representación de estos caracteres no visuales y caracteres espe-

www.udima.es 187

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

Algunas de las secuencias de escape más habituales son las siguientes:

• '\n': cambio de línea.


• '\r': retorno de carro.
• '\t': tabulador horizontal.
• '\v': tabulador vertical.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• '\f': salto de página.


• '\b': retroceso de un espacio.
• '\a': alarma o campana.
• '\0': carácter nulo o NULL.
• '\"': comillas dobles.
• '\'': comilla simple.
• '\\': barra inversa.
• '\%': tanto por ciento.
• '\xdd': carácter cuyo código sea el número indicado en hexadecimal.
• '\ddd': carácter cuyo código sea el número indicado en octal.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

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.

2.5. CONSTANTES CADENAS DE CARACTERES

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.

Un ejemplo de cadena de caracteres lo constituye la cadena "¡Hola, mundo!". En


C++, las cadenas pueden contener cualquier carácter en cualquier cantidad; incluso, pueden
contener caracteres representados mediante las secuencias de escape vistas en el epígrafe
anterior. Por ejemplo, si se quisiera incluir un tabulador antes de la cadena anterior y hacer
que posteriormente se saltara de línea, la cadena quedaría: "\t¡Hola, mundo!\n". Asi-
mismo, si se quisiera incluir otras secuencias de escape, se introducirían de manera análoga,
por ejemplo, para incluir las comillas: "Esta es mi \"primera\" cadena".

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"

La figura siguiente muestra la representación en memoria de la cadena anterior:

C a d e n a c o n 2 5 c a r a c t e r e s /0

De la misma forma, la cadena "\t¡Hola, mundo!\n" consta de 16 caracteres


(recuérdese que las secuencias de escape representan un único carácter) y la cadena
"Esta es mi \"primera\" cadena" tiene 28 caracteres.

www.udima.es 189

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

Finalmente, dada la cadena "Hora\t\"Día\"\n11:45\t11/2/66", si se imprimie-


ra en pantalla, el resultado sería: la palabra Hora, un tabulador, la palabra Día encerrada
entre comillas, un salto de línea, unos números, un tabulador y otros números. Más o
menos, en pantalla podría quedar:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Hora "Día"
11:45 11/2/66

Al escribir una cadena en el fichero fuente, no se puede dividir en varias líneas. Si se


quisiera escribir utilizando varias líneas, se puede realizar cerrando la cadena en cada línea
y añadiendo una barra inversa (sin ningún otro elemento detrás) de la siguiente forma:

"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

En todo programa escrito en C++, además de las constantes, pueden encontrarse


otros tipos de elementos que resultan necesarios para realizar la implementación de un
algoritmo. El primero de estos elementos son las variables.

Variable. Tipo de identificador. Todos los identificadores reciben un nombre que


define el programador.

190 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

Una variable puede almacenar distintos valores correspondientes a un determinado


tipo de datos. Posteriormente, dicho valor se podrá consultar o modificar mediante los
distintos operadores que ofrece el lenguaje y que se estudiarán posteriormente en esta
misma unidad didáctica.

3.1. NOMBRES DE VARIABLES

Antes de utilizar una variable (o, en general, cualquier identificador) es necesario


haberla declarado previamente. Solamente puede existir una declaración para una mis-
ma variable en un ámbito del programa. Para declarar una variable es necesario especifi-
car el tipo de datos que va a almacenar y después bautizar dicha variable con el nombre
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

que decida el usuario. Es recomendable que el nombre elegido ayude a identificar la


información que almacena la variable.

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:

contador  frecuencia  a1b2c3d4e5f6g  limite5  IVA16  iva16


iva_16  _Entero  velocidad_angular
_matriculas_de_vehiculos_europeos_  i, _i, _i_, i_  contador
factorial  PrecioFinalEstimadoParaLaCompraDeCombustible

De la misma manera, no son nombres de variables válidos los siguientes: 4u (empieza


por un dígito), año (contiene una eñe), valor-inicial (tiene un guion), precio$ (tiene
un símbolo de dólar).

Como ya se ha comentado, C++ es un lenguaje en el que se diferencian las mayúsculas


de las minúsculas y lo mismo ocurre con los nombres de las variables. Un nombre de variable
escrito con mayúsculas se considera distinto al nombre de una variable escrito con minús-
culas. De esta manera, las siguientes son todas variables distintas y, por tanto, se pueden
usar en un mismo programa con fines diferentes: cont, Cont, conT, ConT, cONt, CoNt, etc.

www.udima.es 191

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

3.2. DECLARACIONES

La sintaxis para declarar una variable es la siguiente:

tipo nombre_variable;

En una declaración, el tipo se refiere a cualquiera de los tipos de datos (enteros,


carácter, cadenas, reales, etc.) del lenguaje (en el epígrafe 4 se verán los tipos de datos
básicos y en la unidad didáctica 9 se verán los tipos de datos avanzados) o los tipos defi-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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:

tipo variable1, variable2, variable3;

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:

tipo nombre_variable = valor;


tipo nombre_variable (valor);

192 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

En esta definición, valor constituye el valor con el que se quiere inicializar la


variable. A partir de ese instante se dice que la variable tiene o contiene ese valor, pero
podrá ser modificado posteriormente a lo largo del programa en cualquier momento. Si
se quiere inicializar diversas variables, la notación es similar, colocando un valor por
cada variable que se desee definir. Así:

tipo variable1 = valor1, variable2, variable3 = valor3;

En este caso, la variable1 se inicializaría con el valor1, la variable2 quedaría


sin inicializar y la variable3 tendría como valor inicial el valor3. En el caso de que una
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.

3.4. IDENTIFICADORES CONSTANTES

Por último, también se permite definir un tipo especial de nombre o identificador,


que son los identificadores constantes. Los identificadores constantes se diferencian de
las variables en que estas pueden modificarse mientras que los identificadores constantes
no se pueden cambiar. La notación para definir un nombre constante es:

const tipo nombre_constante = valor;

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.

4. TIPOS BÁSICOS DE DATOS

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

Fundamentalmente, los tipos básicos coinciden prácticamente con las constantes


vistas al principio de la unidad didáctica. Los tipos básicos de C++ permiten representar
números enteros, números reales, caracteres y valores lógicos. Para hacer referencia a
cada uno de estos tipos, se utiliza una palabra reservada del lenguaje.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

4.1. TIPO ENTERO

El tipo de datos entero se puede representar mediante la palabra int (abreviatura


del inglés integer). El tipo entero, por tanto, puede representar los valores enteros. De
esta forma, se podrá declarar una variable entera y también inicializarla con el valor de
una constante entera (como puede verse, también se pueden definir variables mediante
expresiones con operadores, que se verán en el epígrafe 5) de la siguiente forma:

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 */

4.2. MODIFICADORES DE TIPO

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:

• Entero de poca precisión: short.


• Entero de gran precisión: long.

194 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

• Entero sin signo: unsigned.


• Entero con signo: signed.

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:

tamaño short ≤ tamaño int ≤ tamaño long

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.

Algunos ejemplos de declaraciones y definiciones adicionales son:

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Además de todos estos modificadores que se aplican sobre identificadores enteros


(y alguno sobre los reales, como se verá en el siguiente epígrafe), C++ dispone de
otro modificador: el modificador volatile, que, colocado delante de una definición
o declaración de un identificador, constituye una indicación al compilador para que
no realice ningún tipo de optimización con dicho identificador, puesto que su valor
puede ser modificado (por otro proceso) de forma que no pueda ser detectado por el
compilador. También suele utilizarse cuando el programa en C++ dispone de algún
módulo en otro lenguaje o en ensamblador que puede hacer uso de una determinada
variable en este caso.

4.3. TIPO REAL


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

4.4. TIPO CARÁCTER

El tipo de datos para almacenar un carácter se representa mediante la palabra reser-


vada char. De esta forma, la siguiente línea declara dos variables de tipo carácter, una
inicializada con el carácter '1' y la otra, con el carácter nulo:

char digito= '1', car= 0;
/* car se inicializa con el valor del código ASCII de '\0' */

Debe recordarse que se puede utilizar cualquier forma de representación de los


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

caracteres para definir una variable de tipo carácter:

char a= 'a', salto= '\n', tab= '\007', letra, D= 68, digito;

4.5. TIPO LÓGICO

El tipo lógico o boolean también tiene su forma de representación en C++ (aunque


no existía en C). La palabra reservada para declarar un tipo lógico es bool. Hay que
recordar también que en C++ el cero se toma como falso y cualquier valor distinto de
cero, como verdadero, independientemente de su tipo. Es decir, tanto el entero 0, como
el real 0.0, como el carácter '\0' se considera que valen falso y, por ejemplo, el entero
-5, el real 0.5 o el carácter '›' se consideran verdaderos a todos los efectos cuando se
necesite un valor lógico. Algunos ejemplos de identificadores lógicos serían:

bool final, terminado= true, seguir= 5, pagado= false;
// seguir es una variable lógica inicializada a verdadero
const bool verdadero= true, falso= false;

4.6. TIPO VACÍO

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

Un puntero, básicamente, es un tipo de datos que apunta a un dato. Es decir, cuando


se declara una variable como puntero a entero, lo que almacena dicha variable es la direc-
ción de memoria donde está el valor entero. Su declaración es de la siguiente forma:

tipo * var;

Por ejemplo, se puede declarar un puntero a entero de la siguiente forma:

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

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;

Las referencias deben siempre inicializarse. Posteriormente no pueden cambiarse;


cualquier asignación cambia el objeto al que se refiere. Este uso de las referencias, sin
embargo, no es generalmente útil. La verdadera utilidad de las referencias se demuestra
al emplearlas como argumentos de las funciones o como valor de retorno de una función.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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).

4.9. DECLARACIONES EN BLOQUES

En C, las declaraciones debían ir al comienzo de los bloques, delante de todas


las sentencias. En cambio, en C++ las declaraciones se tratan como sentencias y, por
tanto, pueden aparecer en cualquier parte del bloque; incluso, tras otras sentencias. En
el siguiente fragmento de programa pueden verse distintas declaraciones y definiciones
de variables en distintos puntos de un programa:

#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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

Sin embargo, por claridad, no debe abusarse de esta facilidad y es recomendable


realizar las declaraciones al principio de los bloques.

4.10. CONVERSIONES DE TIPOS

En lo referente a los distintos tipos básicos, a diferencia de otros lenguajes de pro-


gramación, el lenguaje C++ permite que se mezclen tipos al realizar operaciones. La polí-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

tica seguida, en términos generales, consiste en convertir el dato de menor precisión en el


de mayor precisión para realizar la operación y para devolver el resultado. El orden
en el que se aplican estas conversiones automáticas de tipos viene dado por las siguientes
reglas, que deben aplicarse en el orden en el que vienen enunciadas:

1. char, unsigned char y short se convierten a int siempre para operar.


2. unsigned short se convierte a unsigned int siempre.
3. float se convierte a double siempre.
4. si un operando es long double, el otro se convierte a long double.
5. si un operando es double, el otro se convierte a double.
6. si un operando es float, el otro se convierte a float.
7. si un operando es unsigned long, el otro se convierte a unsigned long.
8. si un operando es long, el otro se convierte a long.
9. si un operando es unsigned, el otro se convierte a unsigned.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

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.

No obstante, como buena práctica de programación no resulta conveniente abusar


de estas conversiones automáticas de tipo y se recomienda intentar realizar manual-
mente las conversiones utilizando el operador correspondiente (que se estudiará en el
siguiente epígrafe).
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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++.

5.1. OPERADORES Y EXPRESIONES

5.1.1. Operador, operando y expresión

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Si dentro de este mismo programa se deseara copiar el valor de una variable en


otra, se necesitaría un operador (=) que exprese esta operación. El programa tendría la
siguiente estructura:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

variable1 operador_de_copia variable2

Operando. Datos sobre los que actúa un operador.

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.

5.1.2. Operadores unarios, binarios y ternarios

En el lenguaje C++ existen varias clases de operadores que se diferencian en el


número de operandos que tiene el operador. Estos tipos de operadores son:

• Operadores unarios o monarios. Los operadores que pertenecen a esta


clase poseen un solo operando, con el fin de producir un nuevo valor. Estos
operadores suelen preceder a su único operando (se usan como prefijo),

202 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

aunque algunos operadores unarios se escriben detrás de su operando (se


usan como sufijo). Por ejemplo, son operadores unarios:

-743
x ++
sizeof (x) 

• Operadores binarios. Los operadores incluidos en esta clase actúan sobre


dos operandos. Estos operadores suelen aparecer infijos, es decir, es fre-
cuente que se escriban entre los dos operandos sobre los que actúan. Segui-
damente, se centrará esta idea con algunos ejemplos de operadores binarios:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

a/b
3 <= X
h && u
7 - 9
t > 2

• Operadores ternarios. Los operadores incluidos en esta clase tienen tres


operandos. C++ dispone de un único operador ternario. Un ejemplo de este
tipo de operador es:

a ? f : g 

5.2. PRECEDENCIA Y ASOCIATIVIDAD DE OPERADORES

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Que un operador tenga asociatividad de izquierda a derecha debe interpretarse como


que se deben agrupar en este orden. De esta manera, en la expresión a + b + c se calcu-
lará en primer lugar a + b y, a su resultado, se le sumará el valor de c. Esto es así porque
el + tiene asociatividad de izquierda a derecha.

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

:: Modificador de visibilidad o alcance


-> Referencia al miembro de una estructura mediante un puntero
. Referencia al miembro de una estructura
() Llamada a una función
[] Referencia a un vector

Asociatividad de derecha a izquierda

* 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

.* Referencia a un puntero a un miembro de una estructura


->* Referencia a un puntero a un miembro de una estructura a través de un puntero
a dicha estructura

* Producto
/ División
% Módulo o resto de la división

.../...

204 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

.../...

+ Suma
- Resta

<< Desplazamiento de bits a la izquierda


>> Desplazamiento de bits a la derecha

< Menor que


> Mayor que
<= Menor o igual que
>= Mayor o igual que
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

== Comparador de igualdad (es igual)


!= Comparador de desigualdad (es distinto)

& Y (AND) de bits

^ O exclusivo (XOR) de bits

| O (OR) de bits

&& Y (AND) lógico

|| O (OR) lógico

Asociatividad de derecha a izquierda

cond? exp1: exp2 Condicional. Si se cumple la condición cond, devuelve exp1; en caso contrario,


exp2

Asociatividad de derecha a izquierda

= 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

/= Divide el primer operando entre el segundo y asigna el resultado al primero


%= Extrae el módulo de dividir el primer operando entre el segundo y asigna el
resultado al primero
>>= Desplaza hacia la derecha el primer operando tantos bits como indique el se-
gundo operando, asignando el resultado al primer operando
.../...

www.udima.es 205

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

, Operador coma. Ejecuta el operando de la izquierda, ejecuta el de la derecha y


devuelve el resultado de esta última ejecución

El programador puede alterar el orden de evaluación de una expresión mediante la


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

utilización de los paréntesis.

De esta manera, la expresión (a + b) * c calculará en primer lugar la suma y


después el producto. Asimismo, en la expresión a + (b + c) primero se evaluará
b + c para a continuación sumarle el valor de a.

5.3. OPERADORES Y EXPRESIONES ARITMÉTICAS

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

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

no se realizará, sino que se proporcionará un resultado de tipo real.

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Expresión Resultado

a + b 14.5

a - b 10.5

a * b 25.0

a / b 6.25

Finalmente, considérese que a y b fueran variables de tipo carácter que representan


los caracteres 'P' y 'T', respectivamente. Si se desea aplicar a estas variables los ope-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

será equivalente a:

(a + ((b * c) / d)) - (e * f)

Teniendo en cuenta la prioridad y la asociatividad, las operaciones se realizarán en


el siguiente orden:

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 )

5.4. OPERADORES Y EXPRESIONES RELACIONALES Y LÓGICAS

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.

En el lenguaje C++ existen seis operadores relacionales:

Operador Significado

< menor que

> mayor que

<= menor o igual que

>= mayor o igual que

== igual que

!= distinto que

www.udima.es 209

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

El resultado de la comparación efectuada por este tipo de operadores tiene como


resultado un valor entero que se interpreta como lógico. Si la comparación es verdadera,
el resultado es un 1 (verdadero) y si la comparación es falsa, el resultado es un 0 (falso).
Por ejemplo, supóngase que a y b son dos variables enteras con valores asignados 1 y 3,
respectivamente. Si se usan estas variables con los operadores relacionales, se obtienen
los siguientes resultados:

Expresión Resultado Interpretació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

La precedencia de estos operadores presenta también dos grupos diferenciados. Los


operadores «igual que» y «distinto que» tienen una precedencia menor que el resto de
los operadores relacionales. Sin embargo, la asociatividad es para todos igual; se evalúan
siempre de izquierda a derecha. De esta manera, una expresión como:

a < b == c > d

se agrupará como:

(a < b) == (c > d)

Además de los operadores relacionales, en el lenguaje C++ existen tres operadores


lógicos que también se usan para construir expresiones lógicas. Estos son:

210 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

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:

Expresión Resultado Interpretación

(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

En los resultados se observa que la primera expresión toma un valor verdadero


porque los dos operandos son ciertos (la variable h es mayor que 6 y la variable c es
igual a 'w'). En la segunda expresión, al ser el primero de los operandos verdadero
(h vuelve a ser mayor que 6), la expresión es también cierta. La tercera expresión es
falsa, ya que el segundo operando es falso (la variable h no es mayor que 100). Y final-
mente, se ve que el interior del paréntesis de la cuarta expresión es verdadero porque el
primer operando ya es verdadero (la variable c no es igual al carácter 'o'); como toda
la expresión está negada, el resultado final es falso.

www.udima.es 211

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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)

En este caso, si a es verdadero, se ejecutará la llamada a la función f. Pero cuando


a sea falso, dicha función no se ejecutará.

Cada uno de los operadores lógicos pertenece a un grupo de precedencia. La nega-


ción lógica tiene la mayor precedencia, y la «y lógica» tiene mayor precedencia que la
«o lógica». En cambio, la asociatividad de los dos operadores binarios es la misma, se
evalúa de izquierda a derecha, mientras que el operador de negación tiene asociatividad
de derecha a izquierda.

5.5. OPERADORES Y EXPRESIONES DE ASIGNACIÓN

Existen varios operadores de asignación en el lenguaje C++. Se utilizan para for-


mar expresiones de asignación en las que el valor de una expresión se asigna a un identi-

212 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

ficador. El operador de asignación más usado es el operador =. Por ejemplo, supónganse


las siguientes expresiones de asignación:

a= 3
x= z 
delta= 0.001 
area= longitud + anchura

En la primera expresión de asignación se asigna a la variable a el valor 3 y en la


segunda se consigue que el valor de la variable z sea asignado a la variable x. En la ter-
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

cera expresión, el valor 0.001 se le asigna a la variable delta. En el último ejemplo, se


asigna a una variable el resultado de otra expresión (una expresión aritmética).

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Como se ve en los resultados, tanto en la primera expresión como en la segunda y


en la tercera se produce un truncamiento al almacenar valores de tipo real en una variable
de tipo entero. Las dos siguientes expresiones no presentan ninguna pérdida al hacer las
operaciones de asignación ya que se usa el valor entero de las constantes carácter 'x'
y '0'. Por último, las dos últimas expresiones se han usado para poner de manifiesto la
pérdida de información producida al usar la división entera.

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

En estos casos, como la asociatividad es de derecha a izquierda, las asignaciones se


efectúan de derecha a izquierda. Es decir, la asignación múltiple anterior es equivalente a:

id1= (id2= (id3= expresión))

214 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

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

Esta expresión sería equivalente a la siguiente:

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

opl += op2 opl = opl + op2

opl -= op2 opl = opl ‒ op2

opl *= op2 opl = opl * op2

opl /= op2 opl = opl/op2

opl %= op2 opl = opl % op2

www.udima.es 215

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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:

Expresión Resultado Interpretación

x += 5 10 x=x+5

f -= g 8.75 f=f–g

z *= x - 3 14 z = z * (x – 3)
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

f /= 3 1.8333333 f = f/3

x %= z - 2 0 x = x % (z – 2)

5.6. OPERADORES Y EXPRESIONES SOBRE BITS

El valor de una variable de un programa se suele almacenar en la memoria del orde-


nador como una secuencia de bits, es decir, como una cadena de ceros y unos. Algunos
programas requieren la manipulación directa de estos bits para poder realizar las funciones
que se necesitan. Cuando se programa en otros lenguajes, normalmente, se requiere pro-
gramar esas operaciones en lenguaje ensamblador o máquina. Sin embargo, el lenguaje
C++ dispone de varios operadores especiales que realizan fácil y eficientemente estas
operaciones sobre los bits. Estos operadores de bits se pueden dividir en cuatro catego-
rías generales: el operador de complemento a uno, los operadores lógicos de bits, los
operadores de desplazamiento y los operadores de asignación con manipulación de bits.
A continuación se analizará cada categoría.

5.6.1. Operador complemento a uno

El operador de complemento a uno (~) invierte los bits de su operando, es decir,


los unos se transforman en ceros y los ceros en unos. Hay que resaltar que es un ope-
rador que actúa como prefijo. Además, el operando tiene que ser obligatoriamente de
tipo entero. Por último, hay que recordar que este operador posee una asociatividad
de derecha a izquierda.

216 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

Por ejemplo, considérese la constante hexadecimal 0x07ff. El patrón correspondiente


de bits es 0000 0111 1111 1111. El complemento a uno de esta secuencia de bits es 1111
1000 0000 0000, que corresponde a la constante hexadecimal 0xf800. Por lo tanto, se
observa que el valor de la expresión ~0x07ff es 0xf800.

5.6.2. Operadores lógicos de bits

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

Se puede verificar la validez de estas expresiones expandiendo cada uno de los


patrones de bits de la siguiente manera:

www.udima.es 217

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

a == 0110 1101 1011 0111 == 0x6DB7


b == 1010 0111 0010 0110 == 0xA726
a & b == 0010 0101 0010 0110 == 0x2526
a ^ b == 1100 1010 1001 0001 == 0xCA91
a | b == 1110 1111 1011 0111 == 0xEFB7

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

5.6.3. Operadores de desplazamiento

El lenguaje C++ tiene dos operadores de desplazamiento de bits: el operador de


desplazamiento a la izquierda (<<) y el de desplazamiento a la derecha (>>). Cada
uno de estos operadores requiere dos operandos: el primero, de tipo entero, representa
el patrón de bits que hay que desplazar, y el segundo, de tipo entero sin signo, indica el
número de desplazamientos que hay que realizar (que no puede exceder del número de
bits del primer operando).

El operador de desplazamiento a la izquierda produce que los bits en el primer ope-


rando sean desplazados a la izquierda el número de posiciones indicado por el segundo
operando. Los bits más a la izquierda se perderán. Las posiciones derechas que quedan
vacantes se rellenan con ceros.

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:

a == 0110 1101 1011 0111 == 0x6DB7


a << 6 == 0110 1101 1100 0000 == 0x6DC0

El operador de desplazamiento a la derecha produce que los bits en el primer ope-


rando sean desplazados a la derecha el número de posiciones indicadas por el segundo
operando. Los bits más a la derecha se perderán. Las posiciones a la izquierda vacantes
se rellenarán con ceros en caso de que el número sea positivo. En caso de que el número

218 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

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:

a == 0110 1101 1011 0111 == 0x6DB7


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

a >> 6 == 0000 0001 1011 0110 == 0x6DC0

En C++ se ha introducido un nuevo uso (no presente en el lenguaje C) para estos


operadores binarios en el manejo de canales (streams) en entrada/salida, como se des-
cribirá en la siguiente unidad didáctica:

El operador >> se emplea para realizar la entrada y el operador << para la salida:

canal_de_entrada >> variable;
canal_de_salida << expresión;

Ambos operadores devuelven el primer operando, es decir, el canal, con lo que


pueden asociarse en cascada:

cout << x << y << z;  // imprime en pantalla las tres variables

5.6.4. Operadores de asignación con manipulación de bits

En el lenguaje C++ existen también los siguientes operadores de asignación que


incluyen operaciones con bits (con un funcionamiento equivalente al visto para los ope-
radores aritméticos de asignación):

www.udima.es 219

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Operador Significado

opl &= op2 opl = opl & op2

opl |= op2 opl = opl | op2

opl ^= op2 opl = opl * op2

opl <<= op2 opl = opl << op2

opl >>= op2 opl = opl >> op2


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Estos operadores combinan las operaciones de bits con la operación de asignación.


El operando de la izquierda suele ser una variable de tipo entero, mientras que el de la
derecha se interpreta como una expresión de bits. El valor de la operación de bits se asig-
nará al operando de la izquierda. Los operadores de asignación a nivel de bits pertenecen
al mismo grupo de precedencia. Su asociatividad es de derecha a izquierda.

5.7. OPERADORES Y EXPRESIONES PARA EL MANEJO DE PUNTEROS

Puntero. Variable que representa la posición en memoria de otra variable o de un valor.

Es decir, es una variable que contiene la dirección de la memoria donde se encuentra


dicha variable o valor. Aunque este tema se tratará más adelante, a continuación se van a
estudiar algunos de los operadores y expresiones que se emplean con este tipo de variables.

5.7.1. Operador dirección

El operador dirección (&) es un operador unario encargado de proporcionar la


dirección de memoria donde se encuentra almacenado el valor del operando al que se le
aplica. Se emplea principalmente para asignar direcciones a las variables de tipo puntero.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

memoria donde se encuentra almacenado el valor de v, se necesitaría usar una expresión


con dicho operador dirección, empleado de la siguiente manera: p= &v. A partir de este
momento p contendrá la posición de memoria donde se encuentra el valor de v, es decir,
la variable p «apuntará» a la posición de memoria de la variable v. De esta manera, si se
modifica el valor de v, también quedará modificado el valor al que apunta p (dado que
es exactamente el mismo).

5.7.2. Operador indirección

El operador indirección (*) es un operador unario que se emplea para acceder al


valor contenido en la posición de memoria que contiene el operando al que se le aplica.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Su principal uso es para consultar el valor que tiene la posición de memoria contenida
en una variable de tipo puntero.

Por ejemplo, continuando con el ejemplo anterior, si se deseara acceder al valor


contenido en la variable v mediante el puntero p, se necesitaría el operador indirección
de la siguiente forma (la variable h es una variable cualquiera del mismo tipo que la
variable v): h= *p. Al usar en la expresión este operador, se accede al valor de la posi-
ción de memoria que está asignada a la variable p.

5.8. OTROS OPERADORES

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.

5.8.1. Operadores paréntesis

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

A continuación se ven algunos ejemplos:

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

5.8.2. Operador condicional

En el lenguaje C++ se pueden realizar operaciones condicionales gracias al opera-


dor condicional (? :), que es un operador ternario. Una expresión que hace uso del ope-
rador condicional se llama expresión condicional. Una expresión condicional se escribe
de la forma siguiente:

expresión1 ? expresión2 : expresión3 

Su significado es el siguiente: cuando se evalúa una expresión condicional, expresión1


es analizada primero. Si es verdadera, entonces se evalúa la expresión2 y este es el valor
de la expresión condicional. Sin embargo, si expresión1 es falsa, entonces es analizada
la expresión3 y este es el valor de la expresión condicional. Por ejemplo, en la expresión
condicional que se muestra a continuación, supóngase que a y b son variables enteras:

x= (a > b) ? a : b

En esta expresión, primeramente se analiza la expresión (a > b). Si es verdadera (el


valor de a es mayor que b), el valor de toda la expresión condicional es a. En caso con-
trario, el valor de toda la expresión condicional es b. Dicho de otra forma, esta expre-
sión condicional devuelve el máximo valor de las dos variables y lo almacena en x.
Por supuesto, cualquiera de los operandos puede ser a su vez otra expresión, al igual que
ocurre con el resto de operadores.

222 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

5.8.3. Operadores signo

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

5.8.4. Operadores de incremento y decremento

El operador de incremento (++) y el operador de decremento (--) son dos opera-


dores unarios que se utilizan muy frecuentemente en el lenguaje C++ (y, de hecho, el
nombre del lenguaje proviene de uno de estos operadores). El operador de incremento
hace que su operando se incremente en una unidad, mientras que el operador de decre-
mento hace que su operando se decremente en uno. El operando para ambos operadores
debe ser una variable con valor numérico.

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.

Se puede utilizar cada uno de los operadores de incremento y decremento de dos


formas distintas, dependiendo de dónde se escriba el operador, antes o después del ope-
rando. Si el operador precede al operando (por ejemplo, ++x), el valor del operando se
modificará antes de que se utilice con otro propósito; es decir, la expresión devuelve el
valor del operando incrementado. Sin embargo, si el operador sigue al operando (por
ejemplo, x++), entonces el valor del operando se modifica después de que haya sido uti-
lizado; es decir, la expresión devuelve el valor del operando sin incrementar.

www.udima.es 223

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

5.8.5. Operador tamaño

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

El resultado de estas operaciones es el número en bytes que ocupa la variable dentro


de la memoria del ordenador en el que se ejecutan, por lo que puede variar de uno a otro
y entre compiladores.

224 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

5.8.6. Operador de conversión de tipos

En el lenguaje C++, si se desea, se puede convertir el valor resultante de una expre-


sión a un tipo de datos diferente. Por ejemplo, si se suman dos números enteros, el valor
resultante de esta suma (que es otro entero) se puede convertir a un número real (float).
Para que se pueda hacer esto, la expresión debe ir precedida de un operador denominado
operador de conversión de tipos u operador cast.

Este operador posee dos formatos equivalentes: el primero es (tipo) expresión


y el segundo es tipo (expresión). Por ejemplo, supóngase que x es una variable en-
tera cuyo valor es 7, y f, una variable real con valor asignado de 8.5. La expresión
(x + f) % 4 no es válida porque el primer operando es un real en vez de un entero. Para
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

solucionarlo, se aplica este operador para transformar el primer operando en un número


entero y la operación de módulo ya es válida, con lo que se obtiene un resultado de 3.
Esto se escribiría de una de las dos formas siguientes:

((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.

5.8.7. Operador coma

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Primero se modificará la variable x y luego la y. La expresión coma devuelve el


resultado de esta última asignación, que es un 8. Finalmente, hay que mencionar que este
es el operador con menor prioridad de todos los operadores del lenguaje.

5.8.8. Operadores de acceso a miembros

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 (.).

Las expresiones con este operador poseen el siguiente formato:

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

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.

El primer operando debe ser un objeto de un registro T (para .*) o un puntero


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.

5.8.9. Operador de acceso a vectores

El lenguaje C++ permite declarar vectores y matrices. Para acceder a un elemento,


se debe utilizar el operador corchete ([]). Es un operador binario que lleva la variable
de tipo vector y, entre los corchetes, el índice del elemento al que se quiere acceder. Por
ejemplo, si v es un vector, la expresión v[5] accederá al elemento cuyo índice es 5 (es
decir, el sexto elemento del vector, dado que el primero tiene como índice un cero); la
expresión v[i + 1] accederá al elemento que se encuentre en la posición i + 2.

5.8.10. Operador de alcance

El operador de alcance (::) permite modificar la visibilidad o ámbito del elemento


sobre el que se aplica (un concepto que se estudiará más detenidamente en la unidad
didáctica 8) y posibilita el acceso a variables globales o a determinados miembros de
registros que sin él no sería posible. Su utilización más habitual consiste en emplearlo
para definir miembros de registros fuera del propio registro.

int i= 5;
int f (int i)

www.udima.es 227

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

5.8.11. Operadores «new» y «delete»

Estos nuevos operadores ofrecen asignación y liberación dinámica de memoria.


Sustituyen a las funciones de la librería que se usaban en C: malloc, free, etc.

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.

A continuación del tipo puede colocarse un inicializador entre paréntesis:

int *p= new int (0);
/* p apunta a una zona de memoria reservada que contiene un 0 */

228 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

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;

Para liberar un vector, la sintaxis correcta es:

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

• Los nombres de los identificadores tienen unas normas de escritura.


• Las variables tienen que ser declaradas antes de usarlas y pueden ser
inicializadas.
• El lenguaje dispone de una serie de tipos de datos básicos: enteros, reales,
carácter, lógico y vacío.
• C++ ofrece un rico conjunto de operadores.
• Los operadores tienen una precedencia y una asociatividad que es nece-
sario conocer para escribir expresiones de manera adecuada.

 ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1

¿Cuál de los siguientes grupos de constantes están bien escritas en C++?

a) 865,  'zx',  true


b) .1e-1,  '\0',  0xFEA
c) 0xG,  -6,  '0'
d) -9u,  "hola",  9.9f

230 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

Enunciado 2

¿Cuál de las siguientes declaraciones es correcta en C++?

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

¿Cuál de las siguientes expresiones devuelve un valor de falso?

a) a= false, b= !a
b) a && !a
c) ((a == b) && (b != 0)) ? a : 8
d) a |= 0xFF

Enunciado 4

¿Cuál de las siguientes expresiones es incorrecta?

a) i += sizeof (int)
b) x= y= (a == b) ? 10 : b
c) v= (a += 1, a & 2)
d) a + b= 5

Enunciado 5

¿Cuál de las siguientes afirmaciones es verdadera?

www.udima.es 231

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Expresiones

Solución 1

b) .1e-1,  '\0',  0xFEA


d) -9u,  "hola",  9.9f

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

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.

 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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

2. Escribir una secuencia de expresiones que permitan intercambiar entre sí


los valores de dos variables de tipo carácter. Deberán también definirse las
variables necesarias.
3. Declarar e inicializar tres variables enteras. Seguidamente, escribir las expre-
siones correspondientes para calcular su suma, su producto, la media arit-
mética y la suma de sus cuadrados.
4. Escribir una expresión que permita determinar si el valor de la variable x
es un número par de tres o cinco dígitos.
5. Escribir las constantes necesarias para representar el día de hoy, el nombre
del mes actual, el año actual y la inicial del día de la semana de hoy. Escribir
los enteros también como constantes octales y hexadecimales. Escribir los
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

enteros también como números reales en las dos notaciones (normal y


científica).

 REFERENCIAS BIBLIOGRÁFICAS
Básica

Alonso, F. et al. Programación sin secretos. Madrid: Cultural, 1999.


C++ FAQ. Disponible en <https://isocpp.org/faq>.
Ellis, M. A. y Stroustrup, B. The Annotated C++ Reference Manual. Addison-Wesley, 1991.
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

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

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

3. Sentencias de control de flujo


3.1. Estructura secuencial
3.2. Sentencias condicionales
3.2.1. Sentencia «if»
3.2.2. Sentencia «if-else»
3.2.3. Sentencia «switch»
3.3. Sentencias repetitivas
3.3.1. Sentencia «while»
3.3.2. Sentencia «for»
3.3.3. Sentencia «do-while»
3.4. Sentencias de salto
3.4.1. Sentencia «break»
3.4.2. Sentencia «continue»

www.udima.es 235

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Sentencias y entrada/salida básica

 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.

Un ejemplo de lo que es una sentencia se encuentra continuamente en la vida real


cuando se prepara una receta de cocina. En una receta se encuentran a menudo frases
del tipo: «Cortar en rodajas las patatas...», «Freír durante 15 minutos las patatas...», etc.
Son acciones simples y definidas que conducen, una detrás de otra, a la elaboración de
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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).

Las instrucciones de entrada/salida permiten al programa en C++ interactuar con el


mundo exterior, intercambiando datos e información para realizar su labor.

Al finalizar el estudio de esta unidad didáctica, el lector debe:

• Conocer los distintos tipos de sentencias de C++.


• Saber cómo utilizar cada tipo de sentencia.
• Comprender el funcionamiento de las sentencias condicionales y saber uti-
lizarlas para seleccionar qué parte del código debe ejecutarse.
• Comprender el funcionamiento de las sentencias repetitivas y saber utili-
zarlas para permitir repetir la ejecución iterativa de un grupo de sentencias.
• Conocer las sentencias de salto.
• Conocer las instrucciones básicas de entrada/salida.

www.udima.es 237

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

bloque se ejecuta como si fuese una única sentencia.

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

Asignación. Esta operación permite guardar un valor en una variable.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Sentencias y entrada/salida básica

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.

Por ejemplo, si se quiere calcular el valor de la longitud de una circunferencia para


distintos radios se puede hacer:

LongitudCircunferencia= 3.1416 * 2 * radio;

Conforme la variable radio cambie de valor en el programa, se podrán calcular


varias longitudes utilizando la misma sentencia. Evidentemente, en la ejecución de un
programa se calculará la expresión aritmética con el contenido que en ese momento tenga
la variable radio y el resultado se almacenará en la variable LongitudCircunferencia.

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Incluso, como se ha mencionado en la introducción, cualquier expresión puede con-


vertirse en una sentencia añadiendo el punto y coma final. No obstante, algunas expre-
siones no tendrán sentido ni utilidad como sentencias, dado que solo calculan un valor que
devuelven; en este caso, el valor devuelto no es utilizado y, por tanto, se perdería. Pero
otras expresiones pueden modificar el valor de alguna variable y estas son las que se pueden
usar como sentencias independientes. Algún ejemplo de sentencias de este tipo sería:

• Sentencias sin utilidad:

a + b;
c && d;
(a != b) ? a : b;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• Sentencias con utilidad:

a /= 10;
x++;
i= j= k= '\0';

2.2. LLAMADA A FUNCIONES

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Sentencias y entrada/salida básica

A veces, es necesario realizar operaciones matemáticas más complejas. Para ello, el


lenguaje de programación C++ ofrece una librería matemática muy extensa. En la librería
matemática se puede encontrar multitud de funciones ya programadas en C++ por los
desarrolladores del compilador que pueden facilitar la resolución de problemas matemá-
ticos. Para poder utilizar estas funciones, se tienen que importar en los programas las
librerías que las contengan. Esto se realiza poniendo al principio del programa la direc-
tiva include y el nombre del fichero de cabecera de la librería (que usualmente tiene la
extensión .h). Algunas de las librerías que suelen contener funciones matemáticas útiles
son stdlib.h o math.h. Para conocer a fondo estas funciones, resulta imprescindible leer
la documentación del compilador y sus librerías. Algunas de las funciones más típicas
que pueden encontrarse incluyen las siguientes funciones (se indica el tipo que devuelve
la función, el nombre de la función y los operandos de la función):
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• Valor absoluto: int abs (int).


• Seno: double sin (double).
• Coseno: double cos (double).
• Exponencial (e elevado al operando): double exp (double).
• Logaritmo neperiano: double log (double).
• Potencia (el primer operando elevado al segundo): double pow (double,
double).
• Raíz cuadrada: double sqrt (double).

Algunos ejemplos de uso de estas funciones serían:

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

2.3. SENTENCIA «RETURN»

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

La sintaxis de esta sentencia es la siguiente:

return [expresión];

Como puede verse, la expresión es opcional. Normalmente, cuando una función es de


tipo void, la sentencia return no puede llevar expresión. En cambio, si la función tiene
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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 */
}

2.4. SENTENCIA VACÍA

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.

La sintaxis de esta sentencia es simplemente un punto y coma:

242 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Sentencias y entrada/salida básica

3. SENTENCIAS DE CONTROL DE FLUJO

Un ordenador convencional solo es capaz de ejecutar las sentencias de un programa


una a una.

Flujo de control. Orden en el que se ejecutan las sentencias.

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

3.1. ESTRUCTURA SECUENCIAL

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);

3.2. SENTENCIAS CONDICIONALES

En ocasiones, se deben resolver problemas que dependen de ciertas condiciones. En


esta situación se debe indicar al ordenador en qué casos el flujo de control debe ir por un
camino u otro. Para esto se usarán las estructuras de control alternativas o condicionales.

3.2.1. Sentencia «if»

La estructura condicional más sencilla es la sentencia if (también denominada IF-


THEN). Se utiliza para incluir en el programa un bloque de sentencias que solo deben

www.udima.es 243

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

ejecutarse bajo determinadas condiciones y, si no se cumplen estas condiciones, deben


ser saltadas.

En el lenguaje C++, la sintaxis de la sentencia if es la siguiente:

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;
}

El funcionamiento de la estructura condicional es el siguiente: en primer lugar, se evalúa


la condición. Si resulta distinto a cero (verdadero), entonces se ejecuta la sentencia o
las sentencias (esta parte del código se conoce con el nombre de parte then). En caso de
que la condición sea falsa, se pasa a ejecutar la sentencia que vaya tras el if. Por ejemplo:

if (a > b)
a= b - 10;

En este caso, si a resulta ser superior a b, se ejecutará la asignación; en otro caso,


dicha asignación no se ejecutará. De la misma manera, en el siguiente ejemplo se ejecutará
el bloque delimitado por las llaves solamente si la condición del if se evalúa como cierta:

if ((x == 5) && !fin)
{
x--;
fin= funcion ();
}

244 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Sentencias y entrada/salida básica

3.2.2. Sentencia «if-else»

Una variante de la estructura condicional if es la sentencia if-else. Se utiliza para


incluir en el programa sentencias que solo deben ejecutarse bajo determinadas condi-
ciones y, si no se cumplen estas condiciones, deben ejecutarse otras sentencias.

En el lenguaje C++, la sintaxis de la sentencia if-else es la siguiente:

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;
}

El funcionamiento de la estructura condicional es el siguiente: en primer lugar, se


evalúa la condición. Si resulta distinto a cero (verdadero), entonces se ejecuta la sen-
tencia1 o las sentencias1. En caso de que la condición sea falsa, se pasa a ejecutar la
sentencia2 o las sentencias2. Por ejemplo:

if (a > b)
max= a;
else
max= b;

www.udima.es 245

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

En este caso, si a resulta ser superior a b, se almacenará a en max; en otro caso, se


almacenará b en max. De la misma manera, en el siguiente ejemplo se ejecutará el bloque
delimitado por las llaves solamente si la condición del if se evalúa como cierta; en caso
contrario, se ejecutará la asignación de la parte else:

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;
}

3.2.3. Sentencia «switch»

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Sentencias y entrada/salida básica

case et1: sentencias1;
...
case etn: sentenciasn;
[default: sentencias;]
}

Al ejecutar el switch, se evalúa la expresión y se busca el resultado de dicha


evaluación en alguna de las instrucciones case (es decir, se compara con et1, et2, …,
etn). Si se encuentra, se pasan a ejecutar las sentencias asociadas a dicho case y todas
las siguientes hasta el final del bloque. Si no se ha encontrado el valor, se ejecutan las
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

sentencias del default (si existe). La expresión debe devolver un valor que sea de
tipo int o char.

Las etiquetas de las instrucciones case deben ser obligatoriamente constantes de


tipo entero o carácter. Es importante darse cuenta de que las etiquetas case son los posi-
bles puntos de entrada a la estructura y, una vez que se ha verificado cualquiera de ellos,
se ejecutarán todas las sentencias que aparezcan en la estructura, tanto las que están
asociadas a la etiqueta con la que coincide la expresión como todas las asociadas a las
etiquetas posteriores. Esto puede conducir fácilmente a errores. Supóngase el siguiente
ejemplo, donde la variable dia contendrá el número del día de la semana:

switch (dia)
{
case 1: lunes();
case 2: martes();
case 3: miercoles();
case 4: jueves();
case 5: viernes();
default: fiesta();
}

Aparentemente puede pensarse que si dia fuera 4, se ejecutaría únicamente la fun-


ción jueves. En cambio, no ocurre así; de hecho, se ejecutarán las funciones jueves,
viernes y fiesta.

No obstante, C++ permite evitar este comportamiento haciendo uso de la sentencia


break, que se explicará más adelante.

www.udima.es 247

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Si en una sentencia switch no se encuentra coincidencia con ninguno de los valores


especificados en las etiquetas case, se ejecutan las sentencias que aparecen tras la
palabra clave default. Esta sentencia es opcional (por eso se indica entre corchetes).
Si no se pone una sentencia default y el resultado de evaluar la expresión no coincide
con ninguno de los valores especificados en las etiquetas case, no se ejecutará nada, y
el flujo de control pasará a la sentencia que aparezca inmediatamente detrás de la sen-
tencia switch.

3.3. SENTENCIAS REPETITIVAS

En ocasiones, para resolver un determinado problema, se necesita ejecutar una o


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.

En términos generales, una estructura repetitiva se compone de una sentencia o bloque


de sentencias y de una condición que determina el número de veces que se debe repetir
la ejecución del bloque de sentencias. Según el tipo de estructura, la condición puede ser
evaluada antes de la ejecución, para determinar si se puede proceder a ella o no, o después
de la ejecución, para determinar si se debe volver al principio del bloque o seguir adelante.

3.3.1. Sentencia «while»

La primera sentencia repetitiva que se va a estudiar es la sentencia while, que en


español significa «mientras». Esta sentencia consiste en un bucle con condición de entrada,
es decir, que se debe cumplir primero la condición para poder ejecutar sus sentencias.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Sentencias y entrada/salida básica

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;
}

Cuando se utiliza la sentencia while es importante no olvidar que, al menos, una


de las sentencias incluidas en el bloque que se repite debe tener la posibilidad de modi-
ficar la condición para que el bucle pueda finalizar. En el ejemplo anterior, se trata de la
sentencia de asignación a i que, al incrementar el valor de la variable, hace que llegue
un momento en el que la condición (i < DIM) ya no se cumpla más.

Si no se toman estas precauciones, el bucle seguiría ejecutándose una y otra vez


de forma indefinida sin parar jamás. Este es un error bastante frecuente y hay que tener
cuidado para evitarlo y comprobar cada vez que se escribe un bucle while que llegará
un momento en el que la condición de entrada se haga falsa.

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

3.3.2. Sentencia «for»

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:

for (inicialización; condición; actualización)


{
sentencias;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

for (inicialización; condición; actualización)


sentencia;

El funcionamiento de esta sentencia es el siguiente: al llegar a este bucle, lo primero


que se hace es ejecutar la inicialización; seguidamente se ejecutan las sentencias si
la condición es verdadera (diferente de cero), se realiza la actualización y se vuelve
a comprobar la condición. Este proceso se repite hasta que la condición sea falsa. Tanto
la parte de inicialización como la de actualización pueden dejarse vacías si así se
desea. Si se deja vacía la condición, se asumirá que esta es siempre verdadera.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Sentencias y entrada/salida básica

Seguidamente, se verá algún ejemplo sencillo de utilización de esta sentencia:

for (ascii= 32; ascii < 128; ascii++)
escribe (ascii);

Este bucle inicializa primero la variable ascii a 32 (el equivalente al carácter


espacio). Seguidamente, como ascii es inferior a 128, se pasa a ejecutar su sentencia,
que llama a la función escribe. Posteriormente, se incrementa en una unidad la variable
ascii y se vuelve a comprobar la condición. La ejecución de la función escribe, por
tanto, se repetirá hasta que la variable ascii alcance el valor de 128, momento en que
finalizará la ejecución del bucle for.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

3.3.3. Sentencia «do-while»

La última sentencia repetitiva es el bucle do-while. Se trata de un bucle con condición


de salida, es decir, que el bucle se ejecuta hasta que cierta condición se cumpla, lo cual
implica que sus sentencias se ejecutarán al menos una vez.

La sintaxis en el lenguaje C++ tiene dos variantes, dependiendo de si contiene una


sentencia o varias:

do
sentencia;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

while (condición);

do {
sentencias;
} while (condición);

No obstante, por claridad en el código y para evitar confusiones con la sentencia


while, se recomienda usar siempre las llaves dispuestas, además, tal como se ha indicado.

Al llegar a esta instrucción se ejecutan las sentencias y seguidamente se evalúa


la condición. Si resulta verdadera, se ejecutan de nuevo las sentencias, hasta que sea
falsa la condición.

A continuación se muestra un par de ejemplos de uso de esta sentencia. En el


primer ejemplo, se ejecuta inicialmente la asignación y la llamada a la función para
posteriormente comprobar la condición. Si esta resulta ser cierta, se repite la ejecución
de la asignación y la llamada a la función. La ejecución finalizará cuando la condición
no se cumpla.

do {
i= i + 1;
calcular_probabilidad (i);
} while (i < MAXIMO);

252 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Sentencias y entrada/salida básica

En el siguiente ejemplo se tiene un bucle que va leyendo caracteres hasta que se


haya leído un salto de línea:

do
car= leer_caracter ();
while (car != '\n');

3.4. SENTENCIAS DE SALTO


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

En este epígrafe se va a estudiar un par de sentencias especiales cuya ejecución


modifica el flujo normal de control de un programa haciendo que salte desde el punto en
el que se encuentra a otro punto.

3.4.1. Sentencia «break»

La primera de las sentencias de salto que se va a estudiar es la sentencia break. Su


sintaxis es muy sencilla:

break;

La sentencia break solamente puede usarse en el interior de las sentencias for,


while, do-while o switch.

Esta sentencia fuerza el flujo de control a salir de la sentencia iterativa o condicio-


nal en la que se encuentra el break, independientemente de que se cumplan o no las
condiciones de salida de la misma.

En el primer caso, cuando aparece en una estructura repetitiva, la iteración finaliza


y el flujo de control prosigue en la sentencia inmediatamente posterior a la estructura.

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Sentencias y entrada/salida básica

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

3.4.2. Sentencia «continue»

La segunda sentencia de salto, bastante menos utilizada que la anterior, es la sen-


tencia continue. Su sintaxis es también muy sencilla:

continue;

Cuando se ejecuta, fuerza la finalización de la iteración en curso, y el control vuelve


al inicio del bucle. Dicho de otra forma, esta sentencia fuerza a volver a evaluar la condi-
ción del bucle en el que se encuentre. Se puede utilizar únicamente en las sentencias repe-
titivas, es decir, en los bucles while, do-while y for (en este caso se salta a la parte de
actualización).

En el siguiente ejemplo se hace uso de esta sentencia:

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Las operaciones de entrada/salida constituyen el conjunto de operaciones que permiten


la comunicación entre el programa y el exterior, tanto en lo relativo a la entrada de datos al
programa desde dispositivos externos (disco, ratón, teclado, etc.) o del usuario, como a la
salida de datos para el usuario o hacia dispositivos externos (pantalla, disco, impresora, etc.).

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 ha creado un conjunto de nuevas librerías para realizar las operaciones


de entrada/salida. Estas librerías sustituyen a la librería de entrada/salida estándar de C
(stdio.h), aunque esta puede seguir utilizándose en los programas en C++. Al igual que en
C, como se ha dicho, las funciones de entrada/salida no forman parte del lenguaje C++.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Sentencias y entrada/salida básica

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

Este ejemplo imprimirá en pantalla la cadena Resultado : z=, seguido del valor


de la expresión x * y, seguido de un salto de línea.

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).

Manipulador Acción producida

dec base decimal

hex base hexadecimal

oct base octal

endl inserta '\n' y vacía el canal

Su utilización es sencilla:

cout << hex << v << endl;
// Muestra v en hexadecimal y salta de línea

www.udima.es 257

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

La entrada a través de un canal se indica con el operador de extracción (>>) que


se encuentra sobrecargado para las operaciones de entrada. Recibe, como primer ope-
rando, un canal de entrada y, como segundo, la variable donde se quiere almacenar la
información leída. Además, dado que es asociativo por la izquierda y que devuelve una
referencia al primer operando, puede encadenarse:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Sentencias y entrada/salida básica

 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

• Las sentencias condicionales son if, if-else y switch.


• Las sentencias repetitivas incluyen las sentencias while, for y do-while.
• Las sentencias de salto son break y continue.
• Las librerías de entrada/salida que proporcionan los compiladores de C++
incluyen diversas funciones útiles y de fácil manejo para que un programa
pueda interactuar e intercambiar datos con el exterior.

 ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1

La sentencia while es:

a) Una sentencia condicional.


b) Una sentencia que permite ejecutar una sentencia de asignación un número
indeterminado de veces.
c) Una sentencia que define un bucle con condición de entrada.
d) Una estructura que permite ejecutar una o más veces un grupo de sentencias.

www.udima.es 259

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Enunciado 2

La sentencia switch es:

a) Una sentencia repetitiva múltiple.


b) Una sentencia en la que se definen etiquetas de cualquier tipo para poder
saltar a ellas.
c) Una sentencia de selección múltiple.
d) Una sentencia que debe llevar una sentencia break en cada etiqueta case.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Enunciado 3

En la sentencia do-while, la condición:

a) Se evalúa después de la ejecución del bloque de sentencias y, si resulta ser


falsa, se finaliza la ejecución del bucle.
b) Se evalúa después de la ejecución del bloque de sentencias y, si resulta ser
cierta, se finaliza la ejecución del bucle.
c) Se evalúa antes de la ejecución del bloque de sentencias y, si resulta ser
falsa, se finaliza la ejecución del bucle.
d) Se evalúa antes de la ejecución del bloque de sentencias y, si resulta ser
cierta, se finaliza la ejecución del bucle.

Enunciado 4

La sentencia break:

a) Permite romper la ejecución de una función.


b) Se puede usar únicamente en la sentencia switch y permite evitar que se
ejecuten varias ramas case.
c) Produce un salto a la condición de un bucle.
d) Realiza un salto a la sentencia siguiente a la de la sentencia de control de
flujo en la que se encuentra.

260 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Sentencias y entrada/salida básica

Enunciado 5

¿Cuál de las siguientes frases en relación con las instrucciones de entrada/salida


es falsa?

a) El lenguaje C++ no dispone de instrucciones de entrada/salida; estas ins-


trucciones vienen dadas por librerías del compilador.
b) La sentencia cin >> a >> b; permite leer de la entrada estándar dos datos
y almacenarlos en las variables a y b.
c) Mediante la instrucción cout << a << 888; se copia el valor 888 en la
variable a y después se imprime por pantalla.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

d) La librería estándar de entrada/salida permite leer o escribir datos de dis-


tintos tipos.

www.udima.es 261

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Solución 1

c) Una sentencia que define un bucle con condición de entrada.

Solución 2

c) Una sentencia de selección múltiple.

Solución 3

a) Se evalúa después de la ejecución del bloque de sentencias y, si resulta ser


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

falsa, se finaliza la ejecución del bucle.

Solución 4

d) Realiza un salto a la sentencia siguiente a la de la sentencia de control de


flujo en la que se encuentra.

Solución 5

c) Mediante la instrucción cout << a << 888; se copia el valor 888 en la


variable a y después se imprime por pantalla.

 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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Sentencias y entrada/salida básica

3. Escribir un fragmento de programa que imprima el triángulo de Floyd con un


número dado de filas completas. El triángulo de Floyd contiene los números
naturales correlativos, estando uno en la primera fila, dos en la segunda y
así sucesivamente. Por ejemplo, el triángulo de Floyd con cuatro filas com-
pletas es:

1
2 3
4 5 6
7 8 9 10
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

4. Escribir tres fragmentos de código que permitan calcular el factorial de


un número que deberá leerse del teclado. Cada fragmento usará una de las
tres sentencias repetitivas. Se recuerda que el factorial de un número n es:
n! == n * n-1 * n-2 * … * 2 * 1.
5. Escribir un fragmento de código que pida un día, un mes y un año por el
teclado y diga si la fecha obtenida es correcta. Deberá comprobarse que
el número de días es válido según el mes introducido. Habrá que tener en
cuenta también si el año es bisiesto para saber los días de febrero. Un año
es bisiesto si su valor es múltiplo de 4 y no es múltiplo de 100, excepto que
sea múltiplo de 400.
6. Escribir un fragmento de código que imprima por pantalla los 100 primeros
números primos.

 REFERENCIAS BIBLIOGRÁFICAS
Básica

Alonso, F. et al. Programación sin secretos. Madrid: Cultural, 1999.


C++ FAQ. Disponible en <https://isocpp.org/faq>.
Ellis, M. A. y Stroustrup, B. The Annotated C++ Reference Manual. Addison-Wesley, 1991.

www.udima.es 263

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

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.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

264 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

4.4. Variables estáticas


4.4.1. Variables globales estáticas
4.4.2. Variables locales estáticas
4.5. Resumen del modo de almacenamiento de variables

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Funciones

 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

Al finalizar el estudio de esta unidad didáctica, el lector debe:

• Saber declarar y definir funciones en C++.


• Comprender las distintas formas de pasar parámetros a las funciones.
• Conocer los conceptos de alcance y visibilidad, y saber utilizarlos en los
programas.
• Entender el concepto de recursividad.
• Saber crear funciones recursivas para resolver determinados problemas.
• Conocer el concepto de sobrecarga de funciones y saber aplicarlo.

www.udima.es 267

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

más sencillas de implementar.

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.

En esta unidad didáctica se van a estudiar las funciones, su declaración y definición y


sus principales características. Además, se mencionará el tema del ámbito de los identifi-
cadores, que está íntimamente ligado a las funciones. La unidad didáctica finalizará expli-
cando el concepto de recursividad, las funciones sobrecargadas y las funciones en línea.

2. FUNCIONES EN C++

2.1. DECLARACIÓN DE FUNCIONES

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:

[tipo] nombre_función ([parámetros]);

268 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Funciones

Estos elementos tienen el siguiente significado:

• El primero es el tipo que precede al nombre de la función. Este puede ser


cualquier tipo básico (int, float, etc.) o complejo (struct, union, etc.).
Asimismo, una función puede devolver un puntero a cualquier tipo básico o
complejo. Incluso, este tipo puede ser void, que, como se estudió a la hora de
ver los tipos básicos, se corresponde con el tipo vacío, es decir, nada. Usar el
tipo void significa que la función no devuelve ningún valor; esta es la forma
en la que C++ implementa los procedimientos. Es opcional escribir este tipo,
de tal manera que, si no se indica ninguno, se entenderá que es entera.
• El segundo componente básico es el nombre de la función. Gracias a este,
se podrá usar la función. El nombre debe seguir las normas de escritura de
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

los identificadores explicadas en la unidad didáctica 6.


• El tercer componente son los parámetros que se pasan a la función. Per-
miten enviar información a la función para que esta realice su trabajo. Los
parámetros son optativos; una función puede no recibir ningún parámetro,
en cuyo caso se especificaría, en lugar de los parámetros, la palabra reser-
vada void. Para indicar los parámetros es suficiente con indicar su tipo. Si se
necesita poner más de un parámetro, habrá que separarlos mediante comas y
especificando para cada uno su tipo. Opcionalmente, también se puede añadir
un nombre de identificador tras cada tipo de parámetro.

De esta manera, un prototipo de una función podría ser el siguiente:

int max (int, int);

Esta función se denomina max; recibe dos parámetros enteros y devuelve un entero.

De todas formas, el mejor lugar para escribir los prototipos de funciones no es en


el propio fichero del programa, sino en lo que se conoce como ficheros de cabecera. En
estos ficheros, que habitualmente tienen extensión .h, es donde se sitúan las declaraciones
de prototipos. Separar las definiciones de prototipos tiene la ventaja de permitir reuti-
lizar la misma función en varios ficheros de forma más sencilla; solo hay que codificar
la función en un fichero .cpp y su prototipo en un fichero .h separado.

Opcionalmente, puede evitarse declarar una función si directamente se define antes


de su uso, aunque la recomendación es escribir siempre los prototipos de todas las fun-
ciones en su correspondiente fichero de cabecera.

www.udima.es 269

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

2.2. DEFINICIÓN DE FUNCIONES

En C++, una función se define del siguiente modo:

[tipo] nombre_función ([tipos parámetros]) bloque

Por lo tanto, una función se define mediante cuatro componentes básicos:

• El primero es el tipo que precede al nombre de la función.


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• El segundo componente básico es el nombre de la función.


• El tercer componente son los parámetros que se pasan a la función. Hay
que indicar el tipo de cada parámetro y su nombre.
• Por último, se detalla el bloque de la función, que contiene el código. El
código de una función puede incluir la declaración de variables locales de
la función y cualquier tipo de sentencias.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Funciones

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);

Es importante destacar que el tipo de retorno declarado en una función debe


ser compatible con el tipo de los valores devueltos mediante sentencias return. De no ser
así, el compilador emitirá un error de concordancia de tipos.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.

Cuando se ejecuta un programa desde el sistema operativo, es posible pasarle varios


parámetros como, por ejemplo, en:

SORT VALORES.DAT -r

Este programa SORT recibe un fichero para ordenar (VALORES.DAT) y una opción
de ordenado (-r).

El paso de parámetros se realiza a través de dos variables, que normalmente reciben


el nombre de argc y argv, y que se declaran así:

void main (int argc, char *argv[])
{
/* código de la función principal */
}

www.udima.es 271

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

El primer parámetro, argc, es un entero que contiene el número de argumentos con


los que se ha ejecutado la llamada al programa, incluido el nombre de dicho programa.

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).

En el ejemplo antes puesto, los valores de estas variables serían:

• argc: 3
• argv[0]: SORT.EXE
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• argv[1]: VALORES.DAT
• argv[2]: 
-r

2.3. FUNCIONES DE LIBRERÍA

Con el fin de facilitar el trabajo de los programadores, los compiladores de C++


proporcionan muchas funciones predefinidas. A estas funciones se les denomina común-
mente «funciones de librería».

El origen de estas funciones se remonta a la construcción de los primeros compila-


dores del lenguaje C. En principio, la propia definición del lenguaje era suficiente para,
sin ninguna ayuda, realizar cualquier tipo de programa. Sin embargo, existía un serio
inconveniente, sobre todo derivado de las funciones de entrada/salida. Para implementar
estas funciones, el programador debía, al principio, acceder al hardware de la máquina y
programarlo adecuadamente. Esto no sería un problema si todas las máquinas realizasen
la entrada/salida de igual forma, pero desgraciadamente no es así.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Funciones

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.

2.4. FUNCIONES EN LÍNEA

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:

• Ahorran tiempo de ejecución, pues se elimina realmente el tiempo de pro-


ceso de llamada y de retorno de la función.
• Aumentan el tamaño del código.
• Tienen total semántica de función (no tienen los efectos laterales de las
macros del preprocesador).

Por tanto, la sintaxis de declaración de una función en línea es la siguiente:

inline [tipo] nombre_función ([parámetros]);

Seguidamente, puede verse un ejemplo de definición de una función en línea:

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

Sin embargo, el compilador puede negarse a expandir la función en línea si lo con-


sidera conveniente. Esto puede ocurrir si, por ejemplo:

• La función es demasiado grande.


• La función es recursiva.
• La función es llamada antes de su definición.
• Se invoca a la función más de una vez en una misma expresión.
• La función contiene un bucle o un switch.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.

3.1. PARÁMETROS FORMALES

Parámetros formales. Son los que aparecen en la definición de una función.

De esta manera, en el ejemplo siguiente, ya conocido, se muestra la función max:

274 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Funciones

int max (int a, int b)
{
if (a > b)
return a;
return b;
}

En este caso, a y b son parámetros formales de la función max. El nombre de paráme-


tros formales viene dado porque tanto a como b permiten especificar el funcionamiento
de una función formalmente, es decir, sin hacer referencia al valor que toman en ningún
momento dichos parámetros. La única restricción que se realiza, durante la ejecución de
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

la función, es la definición del tipo que deben adoptar dichos parámetros.

3.2. PARÁMETROS ACTUALES

Parámetros actuales. Son los que aparecen en la llamada a una función.

De esta manera, en el ejemplo siguiente se muestran llamadas a la función max:

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

En cambio, no es correcto utilizar una función con distinto número de parámetros


o tipos no compatibles (a menos que se proporcionen parámetros formales por omisión,
tal como se verá más adelante). De esta manera, las siguientes sentencias son erróneas,
y el compilador emitirá el correspondiente mensaje de error:

a= max (1, 2, 3); // demasiados parámetros actuales
b= max ("hola", 9); // primer parámetro actual no compatible

3.3. PASO DE PARÁMETROS POR VALOR

Hasta ahora, en todos los ejemplos y explicaciones vistas, siempre se ha comentado


que el valor del parámetro actual se copia en el parámetro formal. A este modo de pasar
el parámetro se le denomina «paso de parámetro por valor», precisamente porque lo que
se envía a la función es únicamente el valor del parámetro. Una consecuencia de este
método de paso es que si dentro de la función se modifica el valor del parámetro formal,
el parámetro actual no se verá afectado y conservará siempre su valor original. De esta
manera, supóngase que se tiene la siguiente función:

void swap (int x, int y)
{
int t;
t= x;
x= y;
y= t;
}

276 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Funciones

Esta función podría ser llamada de la siguiente manera:

int a= 3, b= 7;
swap (a, b);
cout << a << b; // imprime 3 y 7

Puede verse como, aunque dentro de la función se intercambian los valores de x e


y entre sí, esta modificación no afecta a los parámetros actuales; es decir, a y b siguen
conservando sus valores.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

3.4. PASO DE PARÁMETROS POR REFERENCIA

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Y la llamada, que sería exactamente igual, provocaría un cambio en los valores de


los parámetros actuales:

int a= 3, b= 7;
swap (a, b);
cout << a << b; // imprime 7 y 3

Obsérvese que el cuerpo de la función es exactamente el mismo que antes; es decir,


el paso por referencia solamente aparece indicado en la cabecera de la declaración. Una
pequeña diferencia en el uso de parámetros por referencia estriba en que no se pueden
enviar constantes ni expresiones sin dirección (por ejemplo, una operación aritmética o
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.).

3.5. PASO POR DIRECCIÓN

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Funciones

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);

Si dentro de la función se intenta modificar el parámetro, el compilador generará


un error advirtiendo de la situación.

El paso de parámetros por referencia también puede usarse para evitar pasar grandes
cantidades de datos a una función.

3.6. PARÁMETROS POR OMISIÓ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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

nidos si se omiten al realizar la llamada; para ello se indica, en la cabecera de la función,


mediante un signo igual seguido del valor por omisión. Por ejemplo, la siguiente función
tiene dos valores por omisió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

La siguiente función también tiene dos argumentos por omisión:

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Funciones

4. ALCANCE Y VISIBILIDAD

Los términos «alcance» y «visibilidad», en C++, se considerarán sinónimos. Este


epígrafe tratará de explicar la importancia del alcance en los lenguajes de programación
en general y la forma en que se implementa en C++. En primer lugar, se realizará una
definición del concepto de alcance para pasar, a continuación, a estudiar los conceptos
de variable local y variable global, así como las características particulares que C++
permite. El concepto de variable local es, como se verá, muy importante para la progra-
mación estructurada, ya que permite técnicas de programación como la recursividad,
que se estudiará posteriormente. También se estudiará el concepto de variable estática.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

4.1. DEFINICIÓN DE ALCANCE

Alcance o visibilidad. Zona de código fuente (el «ámbito») donde puede utilizarse
una variable dada.

Cada lenguaje de programación tiene una implementación de este concepto, aunque


todos de forma muy similar. Centrándose en el lenguaje C++, el alcance se implementa
de tal forma que una variable puede ser utilizada desde el momento de su declaración
hasta el final del bloque en el que se encuentra declarada.

En el siguiente fragmento de programa se muestran diversas variables y se indica,


para cada una, hasta dónde llega su visibilidad:

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

4.2. VARIABLES LOCALES

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).

Un caso especial lo constituye el bucle for. En la cabecera de esta sentencia, en la


parte destinada a la inicialización, se permite declarar variables. Aunque realmente esta
declaración está situada fuera del bloque del for, el lenguaje considera que se pretende
utilizar dentro del for, por lo que su visibilidad se limita al bloque de sentencias del for.

En el siguiente ejemplo se ve un par de funciones con sus variables locales


declaradas:

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Funciones

{
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

tienen nada que ver la una con la otra.

Pero en el caso de que en un bloque anidado dentro de otro bloque se declarara


una variable que ya existía en el bloque más exterior, la declaración interior se dice que
«oculta» a la exterior, de tal manera que cualquier referencia a esa variable se entenderá
que corresponde al bloque interior. Este funcionamiento puede ser alterado utilizando el
operador de alcance (::). El siguiente ejemplo muestra estas situaciones:

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

4.3. VARIABLES GLOBALES

Variable global. Toda variable declarada fuera de cualquier bloque y que, por tanto,
puede ser utilizada dentro de cualquier bloque.

www.udima.es 283

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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).

4.3.1. Variables globales del fichero


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.

El ejemplo siguiente muestra el uso de variables locales y globales en un único


fichero:

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Funciones

No obstante, en realidad, una variable así declarada no solo es global al fichero,


sino que puede ser global a todo el programa (como se verá en el epígrafe 4.3.2.) si en
los otros ficheros se indica adecuadamente. Si se quiere que sea global estrictamente al
fichero, y solo al fichero, deberá definirse como variable estática, tal como se verá en el
epígrafe 4.4.1.

4.3.2. Variables globales del programa

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Si en el segundo fichero no se pusiera la palabra extern, se entendería que pi es


otra variable global perteneciente únicamente a dicho fichero.

4.4. VARIABLES ESTÁTICAS

El concepto de variables estáticas puede aplicarse a variables globales o a variables


locales, pero con distinto significado.

4.4.1. Variables globales estáticas

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Funciones

De esta manera, si en el ejemplo del epígrafe 4.3.2 se hubiera escrito:

static float pi= 3.1416;

El fichero principal.c habría provocado un error de compilación, puesto que pi no


sería visible fuera del fichero círculo.c, y, por tanto, no se podría utilizar en ningún otro
fichero.

4.4.2. Variables locales estáticas


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

4.5. RESUMEN DEL MODO DE ALMACENAMIENTO DE VARIABLES

Como se ha visto en esta unidad, existen distintos modos de almacenamiento de


las variables, dependiendo del alcance y lugar de declaración. Para indicar los distintos
modos, hay que anteponer al tipo de variable una determinada palabra reservada en la
declaració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

Automático [auto] Temporal Local

Registro register Temporal Local Dentro de las funciones

Estático static Permanente Local

Externo [extern] Permanente Global


Fuera de las funciones
Global estático static Permanente Fichero

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:

• El modo automático. En realidad, es el que se ha venido utilizando en todas


las declaraciones de variables locales, pues es el modo por defecto de una
variable. Se puede destacar que es una variable con modo automático utili-
zando la palabra auto, aunque, entre hacerlo y no hacerlo, no cambia nada
(salvo para puntualizarlo de cara al lector humano). Por tanto, el compilador
ubicará dicha variable donde considere oportuno (podría ser memoria, la
pila, un registro, etc.).
• El modo registro. Se utiliza por los programadores en ciertas variables que
tienen un uso intenso o exhaustivo dentro de una función. Este modo cons-
tituye una petición al compilador para que intente ubicar la variable en un

288 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Funciones

registro del microprocesador en lugar de ubicarla en memoria. Si el com-


pilador puede hacerlo (dependerá de muchos factores como, por ejemplo,
que existan registros disponibles), entonces la consulta y modificación de
dicha variable se realizará mucho más eficientemente, ya que el acceso a
un registro es mucho más rápido que el acceso a memoria.

El siguiente ejemplo muestra cómo se podría usar este modo:

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

La recursividad es una técnica de programación conocida desde los albores de la


computación, pero solo implementada en los lenguajes de programación, a medida que
estos introdujeron los conceptos de función y variable local. La recursión es simplemente
el hecho de que una función se invoque a sí misma.

Existen dos componentes muy importantes en cualquier función recursiva:

• El paso recursivo. Llamada que la función se hace a sí misma.


• El caso base. Permite detener la secuencia de llamadas, finalizar la función
y devolver un valor.

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Una función secuencial o iterativa es normalmente más eficaz que su equivalente


recursiva, pero, a veces, un algoritmo se expresa más elegantemente de forma recur-
siva, y hallar su equivalente secuencial puede, en muchos casos, ser un difícil trabajo.
La recursividad es un concepto que afecta a las funciones.

El ejemplo clásico de función recursiva es la función que calcula el factorial de un


número:

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
}

La recursividad es posible gracias a la existencia de funciones y a la existencia de


variables y parámetros locales. Efectivamente, en cada llamada recursiva a factorial
se tiene un nuevo parámetro n que es distinto al de la anterior llamada.

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.

El modo de funcionamiento es como sigue: cuando se inicia la función factorial,


por ejemplo, para calcular el factorial de 3 (invocando a factorial (3)), se realizan
los siguientes pasos:

1. Se comprueba si el parámetro n es igual a 0. Como n vale 3, se pasa al else,


que para evaluar la expresión llama a factorial (2).
2. Se invoca a factorial (2). Ahora, se comprueba si n es igual a 0. Como
vale 2, se pasa al else, que para evaluar la expresión llama a factorial (1).
3. Se invoca a factorial (1). Ahora, se comprueba si n es igual a 0. Como
vale 1, se pasa al else, que para evaluar la expresión llama a factorial (0).
4. Se invoca a factorial (0). Ahora, se comprueba si n es igual a 0. Como
efectivamente vale 0, se pasa al then, que finaliza esta llamada devolviendo
un 1.

290 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Funciones

5. El control vuelve a la ejecución de factorial (1). Como ya se tiene que


factorial (0) es 1, se puede multiplicar por n (cuyo valor es 1) y finali-
zar retornando un 1.
6. El control vuelve a la ejecución de factorial (2). Como ya se tiene que
factorial (1) es 1, se puede multiplicar por n (cuyo valor es 2) y finali-
zar retornando un 2.
7. El control vuelve a la ejecución de factorial (3). Como ya se tiene que
factorial (2) es 2, se puede multiplicar por n (cuyo valor es 3) y finali-
zar retornando un 6.

Toda función recursiva tiene su equivalente no recursivo. A una función que no es


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

recursiva se le denomina «secuencial» o «iterativa». Se puede escribir el equivalente


no recursivo de la función factorial de la siguiente forma, mediante un bucle iterativo:

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))?

Lo más probable es que el ordenador quedara bloqueado porque nunca se llegaría


al caso base (en el caso de la función recursiva) o nunca se cumpliría la condición de
finalización del bucle for (en el caso de la función secuencial).

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.

Para arreglar la función recursiva y protegerla ante valores incorrectos de su pará-


metro puede escribirse de la siguiente manera, haciendo que devuelva un valor negativo
(un hecho bastante habitual entre los programadores C++):

www.udima.es 291

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Sobrecarga de funciones. Tipo de polimorfismo (un concepto de la orientación a


objetos) que consiste en la capacidad de que un elemento adopte diferentes formas.

Ello posibilita definir distintas funciones sobrecargadas con el mismo nombre, de


tal manera que puedan realizar tareas diferentes y que se referencie a la función apro-
piada según sus parámetros.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Funciones

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)

Puede observarse en las llamadas cómo se llama a la función apropiada basándose


en el número y tipo de los argumentos.

Evidentemente, solo deberían sobrecargarse funciones que conceptualmente rea-


licen la misma operación o una operación semejante.

www.udima.es 293

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

dependiendo del lugar de declaración, serán visibles desde unas funciones


u otras. Es fundamental saber distinguir los identificadores locales, los glo-
bales de fichero y los globales de programa. Además, es importante conocer
cómo utilizar los distintos modos de almacenamiento de las variables.
• La recursividad es una potente herramienta para escribir funciones con-
cisas en ciertas ocasiones. Es imprescindible comprender perfectamente
el funcionamiento de la recursividad y ser capaz de desarrollar funciones
recursivas.
• Las funciones pueden sobrecargarse para funcionar de distinta forma depen-
diendo de los parámetros que se reciban, por lo que es necesario conocer
cómo funciona la sobrecarga de las funciones en C++.

 ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1

¿Cuáles son los modos de paso de parámetros en C++?

a) Por valor.
b) Por valor y por referencia.

294 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Funciones

c) Por valor, por referencia y por dirección.


d) Por valor, por referencia, por dirección y por nombre.

Enunciado 2

Según la visibilidad de las variables, ¿cuántos tipos de variables hay en C++?

a) Variables locales y no locales.


b) Variables locales y globales.
c) Variables globales.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

d) Variables locales, globales de fichero y globales de programa.

Enunciado 3

¿Qué es una función recursiva?

a) Una función que no tiene variables locales.


b) Una función que se llama a sí misma.
c) Una función que según los parámetros recibidos puede ejecutar un cuerpo
u otro.
d) Una función muy concisa que evita perder el tiempo de llamada y retorno.

Enunciado 4

¿Qué es la sobrecarga de funciones?

a) Una posibilidad que tienen las funciones de recibir parámetros de tamaño


muy grande de tal manera que, al pasarlos por dirección, no se pierde tiempo
en el envío del parámetro.
b) Una posibilidad que tienen las funciones de ser utilizadas desde distintos
ficheros.
c) Una posibilidad que permite definir distintas funciones con el mismo nombre
pero distintos parámetros.
d) Una posibilidad que permite a una función no devolver ningún valor.

www.udima.es 295

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Enunciado 5

¿Cuál de las siguientes formas es adecuada para declarar la función principal?

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Funciones

Solución 1

c) Por valor, por referencia y por dirección.

Solución 2

d) Variables locales, globales de fichero y globales de programa.

Solución 3

b) Una función que se llama a sí misma.


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Alonso, F. et al. Programación sin secretos. Madrid: Cultural, 1999.


C++ FAQ. Disponible en <https://isocpp.org/faq>.
Ellis, M. A. y Stroustrup, B. The Annotated C++ Reference Manual. Addison-Wesley, 1991.
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

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

5.2. Declaración de estructuras


5.3. Inicialización de estructuras
5.4. Uso de estructuras
5.5. Campos de bits
5.6. Concepto de unión
5.7. Inicialización de uniones
5.8. Uso de uniones

6. Definiciones de tipos
7. Tipos enumerados
7.1. Concepto de tipo enumerado
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

7.2. Declaración de tipos


7.3. Uso de tipos enumerados

Conceptos básicos
Actividades de autocomprobación
Actividades de repaso
Referencias bibliográficas

300 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

 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.

Al finalizar el estudio de esta unidad didáctica, el lector debe:


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• Conocer el concepto de vector y matriz, cómo declararlos en C++ y cómo


pueden utilizarse.
• Entender el funcionamiento de un puntero y ser capaz de manejarlo con
soltura.
• Comprender las distintas formas de utilizar cadenas de caracteres.
• Conocer el concepto de estructura y unión y saber cómo se declaran y se
usan.
• Saber crear nuevos tipos de datos con la palabra typedef.
• Entender la utilidad de los tipos enumerados y saber declararlos y usarlos.

www.udima.es 301

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

Por ejemplo, la secuencia {1, 2, 4, 8, 16} es un vector de cinco enteros, de manera


que el primer elemento vale 1, el segundo 2, el tercero 4, y así sucesivamente. Los vec-
tores se utilizan cuando se quiere guardar colecciones de datos del mismo tipo e interesa
poder acceder rápidamente a cada uno de los elementos del vector.

Por ejemplo, si se quiere analizar un cuestionario de 10 preguntas, y cada pregunta


tiene tres respuestas válidas (a, b y c), entonces se pueden representar las respuestas de
una persona mediante un vector de 10 caracteres. Así, la secuencia {'b', 'a', 'c',
'c', 'a', 'b', 'c', 'c', 'a', 'b'} indica que una persona ha respondido b a la pri-
mera pregunta, a, a la segunda; c, a la tercera, etc.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

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:

• Declaración de un vector x de 25 enteros: int x[25];


• Declaración de un vector que representa las 10 respuestas de un cuestio-
nario: char respuestas [10];
• Declaración de un vector de 100 números reales: float r[100];

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

no se admiten expresiones en las que aparezca alguna variable.

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};

El compilador de C++ controla los elementos que aparecen en la inicialización, de tal


manera que si hay menos elementos que el tamaño del vector, entonces los elementos que
no tienen un valor de inicialización quedan sin inicializar; por el contrario, si se ponen más
elementos en la inicialización que en el vector, el compilador genera un mensaje de error.
Por ejemplo, en la declaración siguiente solo se inicializan los dos primeros elementos de
un vector, por lo que los elementos tercero y cuarto tendrán un valor desconocido:

float z[4]= {0.3, 9.0};

En cambio, el ejemplo siguiente muestra un código erróneo, pues se inicializan más


elementos de los que tiene el vector, lo cual provocará un error al compilar:

short int mal[3]= {0, 1, 2, 3}; // Error

www.udima.es 303

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Una ventaja adicional que posibilita la inicialización de vectores es que permite


que se declaren vectores sin indicar explícitamente el tamaño, de manera que este
queda definido por la cantidad de valores de la inicialización. En el ejemplo siguiente
se muestra una declaración de un vector de 10 caracteres en el que el tamaño del vector
no se ha especificado (es importante indicar que esta sintaxis solo es válida si se ini-
cializa el vector):

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

La operación principal que se puede realizar con un vector es acceder a un elemento


concreto a partir de su posición (que se denomina «índice»). Para ello, se usa el nombre
del vector seguido del índice entre corchetes. Este índice puede ser cualquier expresión
de C++ que pueda devolver un resultado entero.

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'

Una precaución fundamental que debe verificar el programador es no salirse del


rango de índices válidos para el vector. El compilador de C++ no va a comprobar si
el índice, al acceder a los elementos de un vector, está dentro de los límites; es plena-
mente responsabilidad del programador, y no hacerlo suele ser una fuente habitual de
errores.

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Las matrices se utilizan cuando se quiere almacenar una colección de elementos


del mismo tipo, de forma que se pueda acceder a los elementos mediante varios criterios
simultáneos. Por ejemplo, en un entorno de cuestionarios, si tuviéramos 50 personas que
han contestado 20 preguntas, se podría definir una matriz de 50 filas (las personas) y 20
columnas (las preguntas).

Conceptualmente se puede pensar en las matrices como «vectores de vectores». Es


decir, la matriz de números enteros que hemos visto puede entenderse como un vector
de cuatro elementos (las filas), cada uno de los cuales es, a su vez, un vector con otros
tres elementos (las columnas).

La declaración de matrices es similar a la de vectores (y hace uso de la idea de entender


las matrices como vectores de vectores), solo que en este caso habrá que indicar los tamaños
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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];

Por tanto, con esta declaración, se tendrán los siguientes elementos:

/* m[0][0], m[1][0], m[0][1], m[1][1], m[0][2], m[1][2] */

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

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};

Cuando se ejecuta esta declaración, se va rellenando la matriz por filas: primero la


fila con índice cero, luego la de índice uno, etc. Para rellenar cada fila, se van cogiendo
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

De esta forma, el elemento mat[1][2] == 7 (corresponde a la segunda fila, tercera


columna). La inicialización anterior puede escribirse también colocando entre llaves cada
una de las filas de la matriz. De hecho, esta es la forma recomendada de hacerlo con cla-
ridad. Entonces, el ejemplo anterior quedaría como sigue:

int mat[3][4]= {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};

En una inicialización no es obligatorio colocar todos los valores. Si se omite alguno,


los últimos elementos de la matriz quedarán sin rellenar (tendrán valores aleatorios). En
el caso de realizar la inicialización por filas, quedarán sin rellenar los últimos elementos
de la fila o las últimas filas. Los siguientes ejemplos muestran distintos casos:

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

La siguiente figura ilustra cómo se inicializaría cada una de las matrices:

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

mat1 mat2 mat3

La inicialización no se restringe a matrices bidimensionales, sino que puede aplicarse


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

a las tridimensionales y, en general, a matrices con cualquier número de dimensiones.

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'}};

Un ejemplo de utilización de una matriz sería el siguiente fragmento de programa,


que crea la matriz dibujada anteriormente (que representa en cada fila una operación XOR
entre el elemento de la primera columna y el elemento de la segunda columna y deja el
resultado en el elemento de la tercera columna):

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

La definición de x deja la matriz así:

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

principio del epígrafe.

2.3. REPRESENTACIÓN INTERNA DE VECTORES Y MATRICES

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.

En el caso de las matrices, también se almacenan de forma que se ocupan posiciones


de memoria contiguas. Para ello, los elementos se ordenan «por filas» (es decir, primero
todos los elementos de la primera fila; después, todos los elementos de la segunda fila, y
así sucesivamente), igual que ocurre en el caso de la inicialización. El espacio de memoria
ocupado por una matriz será el resultado de multiplicar todos los tamaños de todas las
dimensiones y el tamaño de cada elemento.

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

nombre y la dirección de memoria es almacenada en una tabla de símbolos durante la com-


pilación. Así, para la declaración int Numero; se obtendría una situación como la refle-
jada en la siguiente figura (suponiendo que los enteros ocupan 4 bytes). Al no haberse
inicializado la variable en la declaración, el contenido de las posiciones de memoria
correspondiente tiene valor desconocido.

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

Cuando se quiere leer o cambiar el valor de una variable, en realidad, el compilador


ha traducido el nombre de la variable en su dirección de memoria, por lo que se realiza la
operación de lectura o escritura correspondiente usando exclusivamente dicha dirección.

Tras la declaración de esta variable, se procede a realizar la siguiente operación de


asignación: Numero = 5;. Esta operación fuerza a que en las posiciones de memoria 103
a 106 se introduzca la representación binaria correspondiente al 5. El resultado de esta
operación se muestra en la siguiente figura.

100
101 Nombre Dir Tam
102
103 Numero 103 4
104
5
105
106
107

310 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

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.

3.1. DECLARACIÓN DE PUNTEROS

Para declarar un puntero se utiliza el símbolo * entre el tipo y el nombre de la


variable. Por ejemplo, la siguiente sentencia declara un puntero a enteros; es decir, el
valor de Puntero es la dirección de un número entero:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

int *Puntero; /* Declara un puntero a un número entero */

En lenguaje C++ se pueden declarar punteros de cualquier tipo (básico o complejo).


Así, se pueden declarar punteros a números reales, punteros a caracteres (o cadenas de
caracteres), punteros a vectores, punteros a estructuras, etc. Incluso se pueden declarar
punteros a punteros. Por ejemplo:

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.

La notación que se emplea para declarar un puntero es la siguiente:

tipo *ptr;

www.udima.es 311

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

3.2. OPERADOR PUNTERO Y DIRECCIÓN

Como ya se ha comentado, los punteros contienen direcciones de memoria y para


obtener esta dirección hay varios mecanismos. Uno de ellos consiste en la utilización
del operador dirección (&) que, aplicado a una variable, permite obtener la dirección de
memoria en la que esta se encuentra almacenada.

312 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

Si estando en la situación especificada en la última figura se procede con la sen-


tencia Puntero= &Numero;, la memoria quedaría como se muestra en la siguiente
figura. El operador dirección se encarga de obtener la dirección asociada a la variable
Numero y, por medio del operador de asignación, se procede a establecer el valor de
Puntero.

100
101 Nombre Dir Tam
102
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

103 Numero 103 4


104 Puntero 110 4
5
105
106
107
108
109
110
111
103
112
113
114

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.

El compilador determina el número de bytes y cómo guardar la información en fun-


ción del tipo asociado al puntero. Este operador solo se puede utilizar con variables de
tipo puntero, ya que para acceder o modificar la información es preciso conocer el tipo
del puntero. Así, por ejemplo, el siguiente fragmento de código daría como resultado la
información representada en la figura mostrada a continuación:

www.udima.es 313

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

3.3. ASIGNACIÓN Y LIBERACIÓN DE MEMORIA DINÁMICA

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.

Otra forma de inicializar un puntero es mediante la asignación de una nueva posi-


ción de memoria dinámica que esté libre. Para ello, existe el operador new. Se encarga
de reservar la memoria necesaria para albergar el tipo de dato especificado. Tras realizar
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

dicha reserva, retorna la dirección de memoria en la que empieza el bloque.

El formato para realizar la solicitud de memoria es:

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;

Entonces, la memoria quedaría de la siguiente forma (suponiendo que el inicio del


bloque reservado por new empieza en 99):

www.udima.es 315

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

En este caso se ha reservado memoria para un entero y se ha inicializado con el


valor 3. Esto mismo se puede realizar en una única sentencia utilizando una variante del
operador new con la siguiente sintaxis:

new tipo (expresión)

En este caso, en la dirección apuntada se coloca el valor de la expresión. En el


caso anterior, sería:

int *Puntero2= new int (3);

Si en este estado se realizan las operaciones:

*Puntero= *Puntero2;
*Puntero2= 3 * 4;

316 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

Se procede a modificar el valor de la información contenida en la posición 103


de memoria (variable Numero), pasando a contener un 3. La segunda operación altera
el contenido de la posición de memoria 99 con un 12 , dando lugar a la situación
siguiente:

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

104 Puntero 2 114 4


3
105
106
107
108
109
110
111
103
112
113
114
105
99
106
107

Si después de estas operaciones se procede a realizar las siguientes operaciones:

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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;

Lo que hace este operador es introducir una referencia en la tabla de bloques de


memoria vacía para indicar que la memoria apuntada por el puntero ahora está disponible.
No modifica el contenido de dicha memoria. Así, por ejemplo, tras la operación delete
Puntero2;, la memoria queda exactamente igual que se mostraba en la figura anterior. La
única diferencia estriba en que se ha marcado el bloque como vacío, pero tanto las refe-
rencias como el valor persisten. El valor ubicado en la posición 99 persistirá mientras el
bloque de memoria no sea asignado de nuevo o se utilice por el sistema operativo. Como
medida de precaución, algunos programadores en C++ han establecido como convención
que resulta adecuado que tras cada operación delete se proceda a actualizar el puntero con
el valor NULL, con el fin de posibilitar determinar cuándo un puntero hace referencia a una
posición de memoria válida y cuándo no. Además, el establecer el puntero a NULL facilita
la detección de errores, dado que, si se intenta usar un puntero con valor NULL, se producirá
un error. En cambio, el uso de un puntero desactualizado suele funcionar temporalmente

318 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

bien, pero, posteriormente, el programa suele empezar a comportarse de forma extraña; o


incluso se podría producir un error ulterior que dificultaría la identificación del verdadero
error. Otra ventaja adicional es que, si por una confusión del programador se intenta liberar
un puntero nulo, no habrá ningún problema porque no hará nada. Así, por ejemplo, tras la
operación anterior, se procede a realizar las siguientes asignaciones:

Puntero= NULL;
Puntero2= NULL;

El estado resultante es el que se muestra a continuación:


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

En el siguiente epígrafe se estudiará la aritmética de punteros, que permitirá, entre


otras cosas, recorrer este espacio de memoria.

3.4. ARITMÉTICA DE PUNTEROS

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

De esta manera, sumando o restando valores a un puntero (con cualquiera de los


operadores del lenguaje que realizan esta operación), se puede recorrer toda la zona de
memoria a la que apunta un puntero y consultar o modificar cada uno de los valores.
Es muy habitual utilizar un segundo puntero para recorrer la memoria, conservando en
el primer puntero la dirección original obtenida por new para poder liberarla de manera
segura con el delete, una vez finalizada la ejecución del código. Por ejemplo:

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;

3.5. PUNTEROS Y VECTORES

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 */

Como la declaración de un vector y un puntero son equivalentes, también se puede


usar la notación de punteros para acceder a un elemento de un vector y la notación de
vectores para acceder a una posición apuntada por un puntero. Las siguientes expresiones
son equivalentes entre sí (en el sentido de que representan el mismo dato del vector):

*(ptra + i)   a[i]   ptra[i]   *(a + i)

www.udima.es 321

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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:

• Se puede hacer: ptra = a; ptra++;


• No se puede hacer: a = ptra; a++;

El siguiente par de declaraciones son equivalentes:

char s[5];  char *t;
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

La diferencia se encuentra en que, de la primera forma, el compilador reserva


espacio en memoria para almacenar un vector de cinco caracteres, mientras que de
la segunda, simplemente es un puntero a caracteres. Las asignaciones siguientes son
equivalentes (suponiendo, en el caso de s como puntero, que se ha obtenido memoria
dinámica suficiente):

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 */

El operador de asignación aplicado sobre constantes de cadenas de caracteres, en


realidad, asigna direcciones, no contenidos.

Las siguientes columnas son equivalentes entre sí:

int array[10]; int array[10]; int array[10];


i n t  * p t r =  a r r a y ; int *ptr; int *ptr;
ptr= array; ptr= &array[0];

322 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

Se pueden realizar declaraciones más complejas. Así, para declarar un vector de


punteros a caracteres, se haría:

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

Cadena de caracteres. Secuencia de caracteres con una terminación especial que


permite que el lenguaje C++ sepa dónde finaliza.

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.

En realidad, una cadena de caracteres se puede entender como un vector de caracteres.


O visto desde otro punto de vista, una cadena de caracteres se puede entender como un pun-
tero a caracteres. En ambos casos, tienen que cumplir una condición especial: al final de la
cadena está presente el carácter con valor '\0', que actúa como delimitador de la cadena.

www.udima.es 323

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

4.1. DECLARACIÓN DE CADENAS DE CARACTERES

Las cadenas de caracteres se pueden declarar como vectores de caracteres, teniendo


en cuenta que tendrán que ser de tamaño suficiente para incluir el texto y el carácter de
terminación. Por ejemplo:

char s[20];

Declara una cadena que puede almacenar un máximo de 20 caracteres (incluido el


carácter nulo del final). También se puede declarar una cadena de caracteres como un
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

puntero a caracteres. De hecho, esta es más habitual. Por ejemplo:

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).

Una tercera forma de declarar cadenas de caracteres, y la más recomendable, es


emplear el tipo de datos string, por lo que la declaración se realizaría:

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

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',};

En el caso de la inicialización de variables de tipo string, existen más posibili-


dades de inicialización que se estudiarán en la unidad didáctica 10.

4.3. USO DE CADENAS DE CARACTERES

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"

Cuando se declara una cadena como un puntero a caracteres, se puede cambiar


rápidamente su valor mediante una asignación directa:

char *cadena= "Hola";
cadena= "Adiós"; /* 
ahora cadena apunta a otra posición de memoria
donde está "Adiós" */

www.udima.es 325

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Esta asignación de cadenas de caracteres solo funciona si se ha declarado como


puntero y no si se ha declarado como vector. Como se vio en el epígrafe de punteros,
hay que tener en cuenta que una asignación copia realmente la dirección, no el con-
tenido. Por tanto, una secuencia como la siguiente no producirá el efecto que podría
esperarse:

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

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:

string str1, str2;


str1= "Hola";
str2= str1;

www.udima.es 327

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

5. ESTRUCTURAS Y UNIONES

5.1. CONCEPTO DE ESTRUCTURA

Estructura (también conocida como registro). Agrupación de datos relacionados


entre sí, pero que pueden ser de tipos distintos, al revés de lo que ocurría con los
vectores y las matrices, en los que todos los elementos deben ser del mismo tipo.

Un ejemplo típico de estructura es la definición de una ficha personal que almacene


los datos personales de una persona. Esta ficha puede definirse como una estructura con
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.

5.2. DECLARACIÓN DE ESTRUCTURAS

Para declarar una estructura se utiliza la palabra reservada struct de la siguiente


manera:

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

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;

En general, esta última forma es poco útil, salvo en casos contados.

5.3. INICIALIZACIÓN DE ESTRUCTURAS

Las variables de tipo estructura también se pueden inicializar en lenguaje C++


usando una notación muy parecida a la de vectores. Lo que hay que hacer es poner entre
llaves los valores iniciales de cada uno de los campos de la estructura. Por ejemplo, para

www.udima.es 329

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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}};

5.4. USO DE ESTRUCTURAS

A la hora de manejar estructuras se puede acceder a cualquiera de sus campos. Para


ello se utiliza el operador . con la siguiente sintaxis:

variable.campo

Por ejemplo, si se quiere acceder e imprimir el nombre de la variable yo, definida


más arriba, se escribiría lo siguiente:

cout << yo.nombre;

Al acceder a un campo de una estructura, se puede leer o modificar su valor uti-


lizando cualquier operación válida con datos del tipo del campo correspondiente. Por
ejemplo, se puede cambiar el valor del campo numero:

yo.numero= 4422188;

330 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

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";

En C++ también se pueden definir punteros a estructuras y se puede usar la aritmé-


tica de punteros, como se ha visto en un epígrafe anterior. Por ejemplo:

DNI *persona, alumnos;
persona= &yo;
alumnos= new DNI [200];
/* puntero a los datos de 200 alumnos */

Usando la notación habitual de punteros, para acceder a un campo de la estructura


a través del puntero habría que obtener primero el contenido del puntero (que es una
estructura) y luego acceder al campo deseado usando el operador .:

cout << (*persona).nombre;

Los paréntesis son necesarios debido a las prioridades de los operadores * y ..


Como la notación anterior es bastante enrevesada, se ha definido en el lenguaje C++
un operador de acceso a campos de estructuras cuando se usan punteros. Ese ope-

www.udima.es 331

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

5.5. CAMPOS DE BITS

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.

Si se tiene que construir un programa en el que se necesita almacenar un entero (cuyo


valor estará entre el 0 y el 3), 5 variables lógicas (con valores 0 o 1) y un entero para

332 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

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

De esta manera, la estructura Campos ocupará al menos 12 bits (el compilador


completará los bits indicados para llenar un número adecuado de bytes según su
arquitectura).

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.

5.6. CONCEPTO DE UNIÓN

Uniones. Tipo especial de organización de datos similar a una estructura. Permiten


representar varios campos distintos, pero compartiendo la misma zona de memoria,
de forma que en cada instante dado solo uno de los campos tiene información
válida.

www.udima.es 333

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Este tipo de datos se utiliza, fundamentalmente, cuando se desea hacer programas


que utilicen poca memoria y existen datos que no se usan al mismo tiempo. En este caso,
se pueden meter todos esos datos en una unión y usar en cada momento solo el campo
que corresponda.

Para declarar uniones se utiliza la palabra reservada union. La sintaxis es exacta-


mente igual que para las estructuras:

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).

La declaración de variables de tipo unión se realiza de la misma forma que en el


caso de estructuras: en una declaración aparte (en este caso, se puede omitir la palabra
union), después de la llave cerrada de la declaración del tipo o declarando una unión sin

334 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

nombre. Por ejemplo, para declarar una variable de la unión anterior bastaría con escribir
una de las siguientes declaraciones:

union Almacen var;


Almacen var;

5.7. INICIALIZACIÓN DE UNIONES

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

la sintaxis de inicialización correspondiente al tipo de datos de ese campo. Por ejemplo,


en el caso de la unión que acaba de verse, sería:

Almacen var= {3.14};

Si en la declaración de los campos de la unión se hubiera colocado primero el entero,


entonces la inicialización debe hacerse con un entero:

Almacen var= {3};

5.8. USO DE UNIONES

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.

Por ejemplo, se puede dar valor al campo entero de la unión:

var.i= 8;

www.udima.es 335

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Si ahora se intenta acceder al campo real r de la misma variable, lo que ocurre es


que se va a intentar interpretar como si el entero fuera un número real. El resultado no
será 8, ya que la representación interna de los números reales es muy distinta de la de
los números enteros y, por tanto, el resultado que se obtendrá dependerá del compilador
y ordenador que se esté utilizando.

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:

typedef tipo nuevo_tipo;

El resultado de typedef es que se define un nuevo tipo denominado nuevo_tipo,


que es un sinónimo de la declaración de tipo utilizada.

336 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

Por ejemplo, se podrían declarar los siguientes tipos:

typedef float real;


typedef unsigned int natural;

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:

typedef float Matriz [20][50];


Matriz m, n;
m[2][5]= n[5][2];

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.

Muy concisamente, se va a explicar que pueden mezclarse los distintos tipos de


declaración. Si se desea usar vectores, punteros o funciones, es necesario utilizar los
modificadores que ya se han estudiado de manera individual. Es decir, los modificadores
que se pueden usar son:

• []: vector.
• (): función.
• * : puntero.

www.udima.es 337

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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:

• Tienen mayor prioridad cuanto más próximos estén al nombre de la variable.


• El * tiene la menor prioridad y los [] la mayor.
• Pueden utilizarse paréntesis para modificar las prioridades.

Así, por ejemplo, la siguiente declaración:

int (*f[5])();
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

declara un vector de cinco punteros a funciones enteras.

7. TIPOS ENUMERADOS

7.1. CONCEPTO DE TIPO ENUMERADO

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.

7.2. DECLARACIÓN DE TIPOS

La sintaxis para declarar un tipo enumerado es la siguiente:

enum [nombre]
{
valores, ...
} [variable];

338 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

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.

Se utilizan cuando se precisa representar un dominio en el que el número de elementos


es finito y, generalmente, de tamaño reducido. Por ejemplo, se puede utilizar un enumerado
para representar los días de la semana, los meses del año, los tipos de monedas o billetes,
etc. Entonces, la definición del tipo de datos para representar los días de la semana sería:
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

enum Dias {lunes, martes, miercoles, jueves, viernes, sabado, domingo};

7.3. USO DE TIPOS ENUMERADOS

En cualquier lenguaje de programación, las operaciones básicas que pueden apli-


carse a variables de tipos enumerados son dos: asignarle un valor y comparar si su valor
es igual a otro. Por ejemplo, en el caso de los días de la semana, si se desea indicar que
el día de hoy es jueves y, en ese caso, indicar que mañana será viernes, sería:

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

Como ya se ha comentado, los compiladores de C++ asignan un valor numérico


creciente a cada uno de los identificadores de la enumeración y, por omisión, este valor
empieza en cero. Sin embargo, es posible indicar que empiece en un valor distinto e
incluso variar el valor de uno de los elementos mediante una asignación de un valor
entero al valor. Si se asigna un valor entero a un valor del enumerado, el valor del
siguiente elemento se incrementará en una unidad. De esta manera, se podría declarar
el siguiente tipo:

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:

enum Pares {cero, ocho= 8, seis= 6, cuatro= 4, dos= 2};

340 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

 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

para todo programa.


• Las estructuras y uniones de C++ permiten agrupar bajo un mismo nombre
datos de distinto tipo; cada uno de esos datos recibe un nombre, que es el
que deberá utilizarse para acceder a él.
• Para simplificar el uso de tipos de datos complejos, C++ permite bauti-
zarlos con un nombre sencillo.
• Cuando se necesita usar unos valores entre los que existe alguna relación
de orden o, simplemente, por aclarar la escritura del código, C++ ofrece el
tipo enumerado.

 ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1

Dada la declaración int v[500][300];, ¿cuál de las siguientes sentencias es la


única que no contiene ningún tipo de error?

a) v[5, 20]= 0;
b) v[5][1]=3, v[v[5][1]]['5']= 0;

www.udima.es 341

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

c) for (int i= 1; i <= 500; i++) v[i][0]= 0;
d) v["hola"][5]= 0;

Enunciado 2

¿Cuál de las siguientes definiciones es incorrecta?

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

¿Cuál de las siguientes afirmaciones es falsa?

a) Las estructuras permiten agrupar datos de cualquier tipo.


b) Una estructura es exactamente igual que una unión, salvo que la unión no
puede almacenar varios valores a la vez.
c) Se pueden crear punteros a estructuras y, en este caso, se usa un operador
distinto para acceder a los campos.
d) Las estructuras siempre tienen que tener un nombre.

Enunciado 4

¿Cuál de las siguientes declaraciones es incorrecta?

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

Enunciado 5

¿Cuál de las siguientes declaraciones es incorrecta?

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

d) Las estructuras siempre tienen que tener un nombre.


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro Tipos avanzados de datos

el número de matrícula (un entero), el número de asignaturas matriculadas,


el nombre y calificación (un número real) de cada asignatura y el curso en
el que está matriculado (los cursos posibles son: primero, segundo, tercero,
avanzado y recuperación). Si está en uno de los tres cursos primeros, deberá
almacenarse también el número de años que lleva cursando dicho curso. Si
está en un curso avanzado o de recuperación, deberá almacenarse la nota
media obtenida hasta la fecha (un número real).
4. Escribir un programa que pida los datos de 10 alumnos, almacenándolos en
un vector de la estructura definida en el ejercicio 3. Después deberá impri-
mirse un listado con todos los datos de los alumnos ordenados por número
de matrícula.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

Alonso, F. et al. Programación sin secretos. Madrid: Cultural, 1999.


C++ FAQ. Disponible en <https://isocpp.org/faq>.
Ellis, M. A. y Stroustrup, B. The Annotated C++ Reference Manual. Addison-Wesley, 1991.
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

Deitel, H. M. y Deitel, P. J. C++ How to Program. 7.ª ed. Prentice Hall, 2009.

www.udima.es 345

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

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.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

346 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

3.5. Librería cctype


3.5.1. Clasificación
3.5.2. Manipulación
3.6. Errores
3.7. Librerías limits.h y float.h
3.8. Librería STL

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

 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

Al finalizar el estudio de esta unidad didáctica, el lector debe:

• Conocer las directivas del preprocesador de C++.


• Saber utilizar las distintas directivas del preprocesador para definir nombres
y macros, incluir ficheros y realizar compilaciones condicionales.
• Conocer algunas de las librerías de C++.
• Conocer algunas de las principales funciones de las distintas librerías.
• Conocer las principales operaciones de entrada/salida.

www.udima.es 349

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

que dota al programador de unas ayudas adicionales.

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++

El preprocesador de C++ es una herramienta que incluyen todos los compiladores


de C++. Realiza un recorrido previo al código fuente de los programas. Las principales
funcionalidades del preprocesador son las siguientes:

• Definir nombres simbólicos (como constantes). Proporcionan mayor legi-


bilidad a los programas.
• Definir macros. Permiten escribir menos funciones.
• Incluir texto de otros ficheros. Fundamentalmente, para permitir la divi-
sión de un programa en módulos.
• Definir la compilación condicional. De forma que algunas partes del pro-
grama solo se compilen en determinadas condiciones.

Las órdenes al preprocesador se realizan mediante directivas de preprocesador. Toda


directiva del preprocesador comienza con el carácter de almohadilla (#), colocado en la
primera columna del código, y va seguido de una palabra y del resto de datos que nece-

350 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

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.

2.1. NOMBRES SIMBÓLICOS Y MACROS

La directiva que permite definir nombres simbólicos y macros es define. Un nom-


bre simbólico permite asignar un nombre a un determinado elemento del lenguaje.
Cuando el preprocesador está actuando y se encuentra con un nombre simbólico, lo
sustituye por el elemento definido.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

El resultado de esta directiva es que el preprocesador sustituirá la palabra PI por


su valor (3.141592) en todos los sitios en los que aparezca. Por ejemplo, si se escribe
la siguiente sentencia:

x= 2 * PI * radio;

www.udima.es 351

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Otros ejemplos de nombres simbólicos serán:

#define NULL 0
#define HABITANTES 3E6
#define CR '\n'
#define THEN
#define ELSE else

En estos ejemplos se ve cómo se definen distintos nombres simbólicos de distintos


tipos. En el último caso, se ha creado un nombre simbólico que define un elemento que
no es constante. De esta manera, en un programa se podrían utilizar estos nombres de
la siguiente forma:

if (numHabitantes < HABITANTES) 
THEN cout << numHabitantes + 1 << CR;
ELSE numHabitantes++;

Cuando el preprocesador hiciera su labor de traducción, el resultado sería:

if (numHabitantes < 3E6)
cout << numHabitantes + 1 << '\n';
else numHabitantes++;

352 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

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

Un aspecto importante a la hora de escribir una macro es que no se permite colocar


espacios en la zona del nombre y de los argumentos. Es decir, puede haber espacios inme-
diatamente tras la palabra define, tras el paréntesis cerrado y en la 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

es que son mucho más rápidas de ejecutar que una función.

Para explicar cómo funcionan las macros se va a definir un ejemplo. La siguiente


macro calcula el cuadrado de dos números:

#define cuadrado(x) x * x

Para ver cómo funciona esta macro, se parte de la siguiente sentencia:

a= cuadrado (2);

Cuando se ejecute el preprocesador, lo que va a hacer es sustituir la llamada a la


macro por su valor, reemplazando sus parámetros por el argumento actual de la macro
(en este caso, el número 2). El resultado de la sustitución sería:

a= 2 * 2;

que, efectivamente, calcula el cuadrado de 2. Ahora bien, supóngase que seguidamente


se escribe la siguiente sentencia:

b= cuadrado (a + 2);

www.udima.es 353

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Cuando se ejecute el preprocesador, lo que va a hacer es sustituir la llamada a la


macro por su valor, reemplazando sus parámetros por el argumento actual de la macro
(en este caso, la expresión a + 2). El resultado de la sustitución sería:

b= a + 2 * a + 2;

Como puede verse, la sustitución realizada por el preprocesador no es la esperada


inicialmente, dado que (suponiendo que a valga 4) el valor de la expresión es 4 + 2 * 4 + 2
= 14 (teniendo en cuenta la prioridad de los operadores). Esto ocurre porque la sustitución
se realiza literalmente, sin entrar a evaluar qué o cómo son los argumentos de la macro.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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));

Con esta sustitución, ya se tiene el valor correcto en ambos casos.

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++);

Aparentemente, esta sentencia guardaría en c el cuadrado de a (es decir, 16) y


posteriormente incrementaría el valor de a (a pasaría a valer 5). Pero hay que tener en

354 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

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++));

Por tanto, tras la ejecución de esta sentencia, c pasará a valer 20 (4 * 5) y a se habrá


incrementado dos veces (valdrá 6). Por ello, y para evitar este aparentemente extraño fun-
cionamiento, en C++ existen las funciones en línea, que, como se dijo en la unidad didác-
tica 8, conservan la semántica de función sin tener estos peligrosos efectos colaterales.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

Tras esta directiva, ya no se podrá utilizar el nombre PI en el programa, a menos


que se defina de nuevo.

2.2. INCLUSIÓN DE FICHEROS

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"

La única diferencia entre las dos es el lugar en el que el preprocesador va a ir a


buscar el fichero. Si se usa el primer formato (con < y >), el preprocesador busca el fichero
en unos directorios especiales en los que el compilador tendrá las cabeceras de todas

www.udima.es 355

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

sus librerías. Si se utiliza el segundo formato (entre comillas), el preprocesador busca


el fichero en el mismo directorio en el que está el fichero actual o en otros directorios
donde indique el usuario mediante la configuración del compilador; si no se encuentra
ahí, se busca el fichero en los directorios de librerías del compilador.

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;

Seguidamente, se ven algunos ejemplos de uso de esta directiva:

#include <iostream>
#include "micabecera.h"

2.3. COMPILACIÓN CONDICIONAL

Existe un conjunto de directivas que permiten realizar una compilación condicional.


Estas directivas permiten identificar fragmentos del fichero que solo se compilarán si se
cumplen determinadas condiciones.

La sintaxis de las directivas que permiten una compilación condicional es la siguiente:

#ifdef NOMBRE
#ifndef NOMBRE
#if expresión
#else
#elif expresión
#endif

356 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

El significado de cada una de estas directivas se explica a continuación:

• #ifdef NOMBRE. Se compila el código que va en las líneas siguientes si está


definido el nombre simbólico NOMBRE (es decir, que haya sido definido con
la directiva define).
• #ifndef NOMBRE. Hace lo contrario que la anterior. Se compila el código que
va en las líneas siguientes si no está definido el nombre simbólico NOMBRE
(es decir, que no haya sido definido con la directiva define).
• #if expresión. Se compila el código que va en las líneas siguientes si
la expresión se evalúa como cierta (es decir, su valor es distinto de cero).
La expresión debe ser una expresión constante. También se admite en la
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

expresión utilizar los términos defined o !defined seguidos de un nombre


simbólico, que indicará si está o no está, respectivamente, definido previa-
mente dicho nombre simbólico.
• #else. Compila el código siguiente si no se cumple la anterior directiva del
tipo ifdef, ifndef, elif o if.
• #elif expresión. Si no se cumple la anterior directiva del tipo ifdef,
ifndef, elif o if y esta expresión sí se evalúa como no cero, entonces
se compilan las líneas siguientes.
• #endif. Termina un bloque de compilación condicional, por lo que las líneas
que aparezcan a continuación se compilarán normalmente.

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

Un segundo uso de la compilación condicional es la protección de los ficheros de


cabecera ante declaraciones circulares (del estilo A incluye a B y B incluye a su vez a
A) que pueden ocurrir cuando se divide un programa en varios ficheros. Para ello, es
costumbre y una buena práctica hacer que los ficheros de cabecera incluyan directivas
de compilación condicional, de forma que, cuando se compilen todos los ficheros de un
programa, solo se compilen una vez. Para hacerlo, hay que apoyarse en la definición de
un nombre, tal como se indica en el siguiente ejemplo:

#ifndef _CIRCULO_H_
#define _CIRCULO_H_
// Código que se tiene que compilar una sola vez
#endif

La primera vez que se compile el fichero, el símbolo _CIRCULO_H_ no estará defi-


nido, lo que provoca que no se cumpla la condición y se prosiga la compilación. Nótese
que lo primero que se hace es, precisamente, definir dicho símbolo (no es necesario darle
ningún valor). La siguiente vez que se compile este fichero, como _CIRCULO_H_ ya estará
definido, no se compilará el código situado entre el ifndef y el 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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

#endif
f(5);
#ifndef FINAL
cout << "La función f ha tardado: "
<< tiempoTranscurrido () << " segundos";
#endif

2.4. OTRAS DIRECTIVAS

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

La directiva error provoca que, si el compilador la compila, se genere el mensaje


de error indicado por la cadena. Se utiliza normalmente junto a la compilación condi-
cional para verificar que una zona de código nunca se compila.

#pragma parámetros

La directiva pragma tiene un comportamiento que depende de la implementación,


siempre que los parámetros tengan sentido. Cada compilador podrá utilizar esta direc-
tiva para lo que quiera, aunque es habitual que la usen para modificar la configuración
de la compilación.

www.udima.es 359

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

3. LIBRERÍAS

El lenguaje C++ no dispone de suficientes palabras reservadas como para realizar


todas las tareas que resultan fundamentales para un programador. El problema se solu-
ciona utilizando un conjunto de librerías que proporcionan todas las herramientas nece-
sarias para realizar dichas operaciones. Estas librerías ofrecen operaciones que van desde
la entrada/salida hasta matemáticas y manipulación de cadenas de caracteres.

A continuación se detallan algunas de estas librerías con sus operaciones más


fundamentales.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

3.1. CADENAS DE CARACTERES

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.

3.1.1. Librería cstring

Como ya se ha dicho, la librería cstring.h (llamada string.h en los compiladores de


C) ofrece un conjunto de operaciones para manipular las cadenas de caracteres, al igual
que se hacía en el lenguaje C. Antes de empezar a comentar el uso de la librería, con-
viene recordar que char * es un puntero a un conjunto de caracteres y que no se lleva
una cuenta del número de caracteres que la componen. Por ello, toda cadena de carac-
teres debe terminar en el carácter \0; de esta manera, las funciones que trabajan con ellas
saben dónde terminan dichas cadenas.

Se pueden utilizar las funciones de esta librería si se incluye su cabecera mediante


la directiva correspondiente. Se puede incluir la versión del lenguaje C++ o la versión
original de C de la siguiente forma:

#include <cstring> // Versión C++


#include <string.h> // Versión C

360 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

Las funciones más importantes de esta librería son:

• int strlen (char * str). Esta función devuelve el número de caracteres


que tiene la cadena str. Como ya se ha mencionado, el tamaño de una
cadena de caracteres se determina por la posición del carácter nulo (\0). Se
calcula contando el número de caracteres desde el principio de la cadena
hasta encontrar el carácter nulo, sin incluir este. Por ejemplo:

char cadena[10]= "Hola";
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

En este ejemplo, cadena tiene una capacidad de diez caracteres, pero el


tamaño de la cadena es cuatro, más el quinto carácter que corresponde al
nulo, como se puede observar a continuación:

'H' 'o' 'l' 'a' '\0'

• 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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

En el ejemplo, origen tiene una capacidad de diez caracteres, pero el tamaño


es de cuatro ("hola"), por tanto, destino debe tener capacidad para cinco,
como mínimo. Al final, destino contendrá "hola".

• char * strcat (char * destino, char * origen). Concatena, al final de


destino, el contenido de origen. Al igual que en el caso anterior, destino
debe tener capacidad suficiente como para albergar las cadenas concate-
nadas. Retorna el puntero a la cadena destino. Por ejemplo:

char cadena[50];
strcpy (cadena, "Con");
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

strcat (cadena, "cate"); 
strcat (cadena, "nado");

En el ejemplo, cadena tendrá el valor Concatenado al finalizar las


operaciones.

3.2. LIBRERÍAS DE ENTRADA/SALIDA

Las operaciones de entrada/salida constituyen el conjunto de operaciones que per-


miten la comunicación entre el programa y el exterior, tanto en lo relativo a la entrada de
datos al programa desde dispositivos externos (disco, ratón, teclado, etc.) o del usuario,
como a la salida de datos para el usuario o hacia dispositivos externos (pantalla, disco,
impresora, etc.).

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 ha creado un conjunto de nuevas librerías para realizar las operaciones


de entrada/salida. Estas librerías sustituyen a la librería de entrada/salida estándar de
C (stdio.h), aunque esta puede seguir utilizándose en los programas en C++. Al igual
que en C, como se ha dicho, las funciones de entrada/salida no forman parte del len-
guaje C++.

362 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

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:

Entrada Salida Fichero

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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:

• ostream &ostream::put (char ch). Imprime el carácter ch en el canal


desde el que se le llama:

cout.put ('A').put('B'); // Imprime A y B en cout

• ostream &ostream::write (char *buf, int max). Imprime max carac-


teres de los apuntados por el parámetro buf:

cout.write ("Solución", 3); // Imprime Sol

• ostream &ostream::flush () . Vacía el buffer del canal, forzando su


escritura.
• ostream &ostream::seekp (long pos). Mueve el puntero de escritura
hasta la posición indicada.
• long &ostream::tellp (). Devuelve la posición actual del puntero de
escritura.

364 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

3.2.2. Entrada

La entrada a través de un canal se indica con el operador de extracción (>>), que


se encuentra sobrecargado para las operaciones de entrada. Recibe, como primer ope-
rando, un canal de entrada y, como segundo, la variable donde se quiere almacenar la
información leída. Además, dado que es asociativo por la izquierda y que devuelve una
referencia al primer operando, puede encadenarse:

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:

• int istream::getc (). Extrae un carácter del canal de entrada.

char c= cin.getc (); // Almacena en c el carácter leído

• istream &istream::get (char &ch). Extrae un carácter del canal de entrada


y lo sitúa en el argumento ch.

cin.get (c);

• istream &istream::get (char *buf, int max, char ch= '\n'). Extrae


caracteres del canal de entrada y los coloca donde señala buf, hasta que se
lean max - 1 caracteres o hasta que se encuentre el carácter ch.

• istream &istream::getline (char *buf, int max). Lee una línea com-


pleta del canal de entrada y coloca los caracteres donde señala buf, hasta
un máximo de max - 1 caracteres.

const int MAX= 256;
char cad[MAX];
cin.getline (cad, MAX);

www.udima.es 365

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

• istream &istream::read (char *buf, int max). Lee tantos caracteres


como indique el último argumento (max) y los introduce donde apunta buf.
• istream &istream::seekg (long pos). Mueve el puntero de lectura hasta
la posición indicada.
• long &istream::tellg(). Devuelve la posición actual del puntero de
lectura.
• istream &istream::putback (char ch). Devuelve el último carácter leído
(indicado por ch) al canal de entrada.
• int peek (). Devuelve el siguiente carácter sin extraerlo del canal.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

3.2.3. Ficheros

La entrada y salida a ficheros se realiza mediante las clases ifstream y ofstream,


respectivamente. La clase fstream permite trabajar con ficheros en lectura y escritura,
simultáneamente. Estas clases se encuentran en el fichero de cabecera fstream.h.

Los modos que aparecen en algunas funciones se pueden seleccionar realizando un


OR bit a bit entre los modos indicados en el siguiente cuadro:

Modo Acción

ios::app Añadir nuevos datos al final del fichero

ios::ate Abrir y desplazarse hasta el fin del fichero

ios::in Abrir para extraer (por omisión en ifstream)

ios::out Abrir para insertar (por omisión en ofstream)

ios::trunc Sobrescribir el contenido (por omisión, si se indica ios::out y no se indica


ios::app ni ios::ate)

ios::nocreate Si el fichero no existe, error

ios::noreplace Si el fichero existe, error si se abre para escribir y no está ios::app ni ios::ate

ios::binary Modo binario

366 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

Algunas de las nuevas funciones que se incorporan son:

• ifstream::ifstream (). Constructor que crea un objeto del tipo fichero


de entrada sin asociarlo a ningún fichero.
• ifstream::ifstream (char *nombre, int modo= ios::in). Constructor
que crea un objeto del tipo fichero de entrada y abre el fichero con el nombre
señalado y según el modo indicado. La función se llamará al definir una
variable del tipo ifstream:

ifstream fi ("datos.bin", ios::binary); // se define fi
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• ofstream::ofstream (). Constructor que crea un objeto del tipo fichero


de salida sin asociarlo a ningún fichero.
• ofstream::ofstream (char *nombre, int modo= ios::out). Constructor
que crea un objeto del tipo fichero de salida y abre el fichero con el nombre
señalado y según el modo indicado.
• fstream::fstream (). Constructor que crea un objeto del tipo fichero sin
asociarlo a ningún fichero.
• fstream::fstream (char *nombre, int modo). Constructor que crea un
objeto del tipo fichero y abre el fichero con el nombre señalado y según el
modo indicado.
• void open (char *nombre, int modo). Abre el fichero denominado nombre
según indique el modo.

ifstream fi;
fi.open ("datos.bin");

• void close (). Cierra el fichero.

3.2.4. Formatos

El formato que se aplica en entrada/salida al manejar los tipos fundamentales de


datos viene determinado por los indicadores de formato que se muestran en el cuadro
siguiente. Estos indicadores pueden agruparse realizando un OR bit a bit:

www.udima.es 367

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Indicador Significado

ios::skipws Saltar espacios en la entrada

ios::left Justificación izquierda

ios::right Justificación derecha

ios::internal Justificar después de signo o base

ios::boolalpha Convierte lógicos a texto

ios::dec Conversión decimal


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

ios::oct Conversión octal

ios::hex Conversión hexadecimal

ios::showbase Indicar la base

ios::showpoint Indicar punto decimal

ios::uppercase Salida hexadecimal en mayúsculas

ios::showpos Poner signo a los números positivos

ios::scientific Escribir los números reales en notación científica

ios::fixed Usar punto decimal fijo en números reales

ios::unitbuf Vaciar el buffer intermedio después de cada inserción

ios::stdio Vaciar el buffer de stdout y stderr en cada inserción

El siguiente cuadro muestra los campos de bits que pueden utilizarse:

Campo Indicadores afectados

ios::basefield ios::dec,
ios::hex,
ios::oct

.../...

368 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

Campo Indicadores afectados

.../...

ios::adjustfield ios::left, ios::right,


ios::internal

ios::floatfield ios::fixed,
ios::scientific

Las siguientes funciones permiten acceder a estos indicadores:


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

• long ios::flags (). Devuelve el estado de los indicadores.


• long ios::flags (long). Instala los indicadores del argumento (reempla-
zando los que hubiera) y devuelve el estado anterior.
• long ios::setf (long). Activa los indicadores del argumento (mante-
niendo los que ya hubiera) y devuelve el estado anterior.
• long ios::setf (long, long). Desactiva los indicadores del segundo argu-
mento, activa los indicadores del primer argumento y devuelve el estado
anterior.
• long ios::unsetf (long). Desactiva los indicadores del argumento y
devuelve el estado anterior.

Existe una serie de funciones que permiten modificar el formato en las operaciones
de salida; entre ellas, pueden destacarse:

• int width (). Devuelve el ancho mínimo del campo.


• int width (int ancho). Fija un ancho mínimo para los campos, devol-
viendo el antiguo. Solo afecta a la operación de inserción inmediata.
• char fill (). Devuelve el carácter de relleno.
• char fill (char ch). Fija un carácter de relleno, devolviendo el antiguo.
• int precision (). Devuelve la precisión actual.
• int precision (int p). Especifica la nueva precisión, devolviendo la
anterior.

www.udima.es 369

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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"
}

La salida del ejemplo anterior sería:

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:

Manipulador Acción producida

dec Base decimal

hex Base hexadecimal

oct Base octal

ws Ignora espacios en la entrada

endl Inserta un salto de línea y vacía el canal

.../...

370 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

Manipulador Acción producida

.../...

ends Inserta el carácter nulo

flush Vacía el canal

setbase (int) Establece una nueva base (8, 10 o 16)

resetiosflag (long) Desactiva los flags indicados

setiosflags (long) Activa los flags indicados


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

setfill (int) Establece el carácter de relleno

setprecision (int) Establece la precisión

setw (int) Establece el nuevo ancho

Su utilización es sencilla:

cout << hex << v << endl;
// Muestra v en hexadecimal y salta de línea

Pueden diseñarse nuevos manipuladores definiendo una función de la forma:

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

que podría utilizarse de la siguiente manera:

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

• int ios::good (). Distinto de cero si no existe error.


• int ios::bad (). Distinto de cero si existe error. El canal está corrupto.
• int ios::fail (). Falló la última operación.
• int ios::eof (). Fin de fichero.
• int ios::rdstate (). Devuelve un código que indica el estado.
• void ios::clear (int = 0). Inicializa el estado del canal.

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
}

3.3. LIBRERÍA CSTDLIB

La librería cstdlib.h de C++ (llamada stdlib.h en C) proporciona un conjunto de


funciones de propósito general que van desde la gestión de memoria dinámica hasta la
generación de números aleatorios, comunicación con el entorno, etc.

372 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

Las siguientes funciones son las más utilizadas:

• 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 atoi (const char *str); Convierte un número en forma de cadena


de caracteres a un número entero. Si se da un error, devuelve el valor cero,
y si el número está fuera de rango, devuelve el valor del nombre simbólico
INT_MAX o INT_MIN.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

int num= atoi ("421"); // num valdrá el valor entero 421

• double atof (const char *str); Convierte un número en forma de cadena


de caracteres a un número real. Si se da un error, devuelve el valor cero, y
si el número está fuera de rango, devuelve el valor (positivo o negativo) del
nombre simbólico HUGE_VAL.

double num= atof ("421.12"); //num valdrá el valor real 421.12

• int abs (int num); Devuelve el valor absoluto de un número.

int n= abs (-400); // n valdrá 400

• div_t div (int numerador, int denominador); Esta función devuelve


el resultado de la división entera entre el numerador y el denominador. Se
devuelve el valor en la estructura div_t, que contiene el resultado de la
operación (quot) y el resto de la misma (rem).

div_t res= div (38, 5);
int resultado= res.quot; // resultado valdrá 7
int resto= res.rem; // resto valdrá 3

www.udima.es 373

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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.

3.4. LIBRERÍA CMATH


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

La librería cmath.h de C++ (denominada math.h en C) proporciona una serie de


funciones matemáticas muy comunes de distintos tipos:

• Trigonométricas. Además de cos, sin, tan que se han mencionado ante-


riormente:

– Arcoseno: double asin (double x).


– Arcocoseno: double acos (double x).
– Arcotangente: double atan (double x). Además, para calcular el
arcotangente con dos parámetros, la coordenada x y la coordenada
y: double atan2 (double y, double x).

• Redondeo:

– double ceil (double x). Aproxima al menor entero no menor que x.

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 floor (double x). Aproxima al mayor entero no superior a x.

double n1= floor (4.3); // n1 valdrá 4.0
double n2= floor (2.8); // n2 valdrá 2.0

374 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

double n3= floor (-3.3); // n3 valdrá -4.0
double n4= floor (-7.8); // n4 valdrá -8.0

– double fabs (double x). Devuelve el valor absoluto de un número


real.
– double fmod (double numerador, double denominador). Devuelve
el resto de la división real; siendo el resto el resultado de restar al
numerador, la parte entera de la división, multiplicada por el deno-
minador: resto = numerador – resultado * denominador.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

double n1= fmod (5.3, 2); // n1 valdrá 1.3
double n2= fmod (18.5, 4.2); // n2 valdrá 1.7

En este caso, n1 tomaría el valor 1.3 y n2 sería igual a 1.7.

3.5. LIBRERÍA CCTYPE

La librería cctype.h de C++ (denominada ctype.h en C) declara un conjunto de funcio-


nes para clasificar y transformar caracteres. Todas las funciones reciben como parámetro
un entero (int), correspondiente a un carácter, y devuelven otro valor entero correspon-
diente a un carácter o a un valor lógico (siendo cero falso y cualquier otro valor verdadero).

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:

• int isalnum (int c); Comprueba si el carácter pasado es alfanumérico;


es decir, letras o números.
• int isalpha (int c); Comprueba si el carácter es una letra; es decir, si
pertenece a uno de los conjuntos (A-Z) o (a-z).
• int isdigit (int c); Comprueba si el carácter corresponde a un dígito;
es decir, si está entre el 0 y el 9.

www.udima.es 375

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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ó.

El ejemplo siguiente hace uso de algunas funciones de esta librería:

#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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

En el ejemplo, se cambian las mayúsculas por minúsculas y viceversa. El programa


imprimirá primero Prueba Uno. y, tras el bucle, imprimirá pRUEBA uNO. Obsérvese que
los caracteres que no son letras no han sido modificados.

3.6. ERRORES

Muchas de las funciones anteriormente vistas no tienen capacidad de indicar si ha


habido error o no en su ejecución. Para ello, hay una librería, cerrno.h (errno.h en C),
que define la variable global errno de tipo entero, que guarda el resultado (error o no) de
la última función ejecutada. Además, en la librería cstdio.h (stdio.h en C) se ha definido
una función capaz de escribir en el canal de error (normalmente la pantalla) un mensaje
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

interpretando el error que ha habido. Asimismo, se permite poner un mensaje persona-


lizado delante del mensaje de error. Esta función es: void perror (const char *str).

En el siguiente ejemplo, se intenta calcular el coseno de un valor no válido (-2),


dándose un error de dominio (domain error); errno pasa a tener un valor distinto de 0
(es decir, verdadero) y se pide a perror que muestre qué ha pasado. Seguidamente, se
fija errno a 0 para poder controlar el siguiente error y se prueba el coseno de -1. Al ser
correcta la operación, errno no cambia de valor.

#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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

perror ("Ha ocurrido el siguiente error");
errno= 0;
}
else
{
cout << "acos(-1)= " << n << "\n";
}
}

La salida por pantalla de este programa de ejemplo se muestra a continuación:


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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.

3.7. LIBRERÍAS LIMITS.H Y FLOAT.H

Estas dos librerías (denominadas climits.h y cfloat.h en C++ y limits.h y float.h en


C) contienen una serie de definiciones de nombres simbólicos que pueden ser útiles al
trabajar con números reales y enteros. Los más interesantes se muestran en el siguiente
cuadro:

Nombre Descripción

CHAR_BIT Número de bits que ocupa un carácter

INT_MIN Mínimo entero representable

INT_MAX Máximo entero representable

UINT_MAX Máximo entero sin signo representable

FLT_MAX Máximo número real (float, double y long double) representable

.../...

378 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

Nombre Descripción

.../...

DBL_MAX Máximo número real (float, double y long double) representable

LDBL_MAX Máximo número real (float, double y long double) representable

FLT_MIN Mínimo número real (float, double y long double) representable

DBL_MIN Mínimo número real (float, double y long double) representable

LDBL_MIN Mínimo número real (float, double y long double) representable


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

3.8. LIBRERÍA STL

La librería STL (Standard Template Library) es la librería estándar definida por el


lenguaje C++. Consiste en un conjunto de estructuras de datos genéricas (contenedores)
y sus operaciones estándar. Un contenedor es un objeto que guarda una colección de
otros objetos. Están implementados, de manera que se puede almacenar prácticamente
cualquier tipo de elemento. La funcionalidad ofrecida hace uso de las técnicas de orien-
tación a objetos (que no se han estudiado aquí) y, por tanto, solo se presentan a título
informativo. A continuación se detallan las principales estructuras que hay y parte de su
funcionalidad más significativa:

Librería Descripción Funciones

vector Un vector almacena los ele- • front: devuelve el primer elemento


mentos de manera estricta- • back: devuelve el último elemento
mente lineal. Los vectores • size: devuelve el número de elementos que contiene
son útiles para: acceder a • empty: indica si el vector está vacío
cada elemento por su índice,
• operador []/at: devuelve el elemento de una posición
iterar sobre los elementos
siguiendo un orden, agregar • push_back: inserta un elemento al final
o eliminar elementos en • pop_back: elimina el último elemento
cualquier posición, etc. • insert: inserta un elemento en la posición indicada
• erase: elimina el elemento de la posición indicada
• swap: intercambia el contenido de dos vectores
• clear: borra todo el contenido del vector

.../...

www.udima.es 379

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Librería Descripción Funciones

.../...

deque Contiene un tipo de datos • Las mismas funciones que vector


de lista doblemente enla- • push_front: insertar un elemento al principio
zada. Este tipo de lista es • pop_front: elimina el primer elemento
útil para: acceder a cada
elemento por su índice,
iterar sobre los elementos
siguiendo un orden, agre-
gar o eliminar elementos de
cualquier extremo, etc.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

list Da la posibilidad de ma- • front: devuelve el primer elemento


nejar datos organizados • back: devuelve el último elemento
en forma de lista. Las listas • size: devuelve el número de elementos que contiene
son útiles para: realizar una • empty: indica si la lista está vacía
inserción eficiente de ele-
• push_back: insertar un elemento al final
mentos en cualquier parte,
movimiento eficiente de • pop_back: elimina el último elemento
elementos dentro de la lista, • push_front: inserta un elemento al principio
iterar sobre elementos hacia • pop_front: elimina el primer elemento
delante o hacia atrás, etc. • insert: inserta un elemento en la posición indicada
• erase: elimina el elemento de la posición indicada
• swap: intercambia el contenido de dos listas
• clear: borra todo el contenido
• splice: mueve elementos entre listas
• remove: elimina elementos con determinado valor
• remove_if: elimina elementos que cumplan una
condición
• unique: elimina valores duplicados
• merge: fusiona dos listas ordenadas
• sort: ordena la lista
• reverse: invierte el orden de los elementos

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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

Librería Descripción Funciones

.../...

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

multiset Es igual que un conjunto, Las mismas que set


pero permitiendo más de
un elemento igual.

map Guarda un conjunto de ele- • Las mismas que set


mentos únicos, según una • operador []: devuelve el elemento de una posición
clave dada. Cada elemento
está compuesto por la clave
y el elemento que se quiere
guardar.

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

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Librería Descripción Funciones

.../...

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

• to_string: convierte el conjunto al tipo string


• count: cuenta el número de unos
• size: devuelve el tamaño
• any: devuelve cierto si hay algún uno
• none: devuelve cierto si no hay ningún uno

382 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

 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

• El preprocesador de C++ permite incluir ficheros de cabecera, que incluyen


normalmente declaraciones de tipos, variables y funciones.
• El preprocesador de C++ posibilita realizar una compilación condicional
de acuerdo a ciertos criterios, de tal manera que solo se compile una parte
del código fuente.
• Existe una librería para manejar cadenas de caracteres como punteros a
char (originalmente diseñada para los compiladores de C) y otra librería
para manejar cadenas de caracteres como string (diseñada para los com-
piladores de C++).
• Las librerías de entrada/salida ofrecen muchas posibilidades para gestionar
la entrada y salida de información desde y hacia distintos dispositivos con
diferentes formatos.
• Los compiladores de C++ suelen incorporar otras funciones de librerías
que permiten realizar distintos tipos de operaciones.

 ACTIVIDADES DE AUTOCOMPROBACIÓN
Enunciado 1

¿Cómo se sustituirá la expresión x= z > macro(i,j) si se tiene la directiva del pre-


procesador #define macro(a,b) a ? a : b ?

www.udima.es 383

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

¿Cuál es la principal utilidad de la directiva include?

a) Incluir cualquier fichero de código fuente en el fichero actual.


b) Incluir declaraciones realizadas en un fichero de cabecera.
c) Incluir directivas del preprocesador en el fichero.
d) Incluir la implementación de las funciones de librería.

Enunciado 4

¿Qué hace la directiva ifndef hola?

a) Devuelve cierto si no está definido hola.


b) Si la variable hola está definida, no se compila el código que venga a
continuación.

384 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

c) Si el nombre simbólico hola no está definido se compila el código que


venga a continuación.
d) Si el nombre simbólico hola está definido se compila el código que venga
a continuación.

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?

a) cout >> setprecision(2) >> f >> oct >> i >> '\n';


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

b) cout << setprecision(2) << f << ios::octal << i << endl;


c) cout << setprecision(2) << f << oct << i << endl;
d) cout << float(2) << f << int << i << endl;

www.udima.es 385

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Solución 1

b) x= z > i ? i : j

Solución 2

c) 9

Solución 3

b) Incluir declaraciones realizadas en un fichero de cabecera.


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Solución 4

c) Si el nombre simbólico hola no está definido se compila el código que


venga a continuación.

Solución 5

b) cout << setprecision(2) << f << ios::octal << i << endl;

 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

Powered by TCPDF (www.tcpdf.org)


Sumario │

J. L. Fuertes Castro El preprocesador de C++. Librerías

nica más eficiente y la menos eficiente.


3. Programar en C++ las funciones que se han explicado correspondientes a
la librería cstring.h.
4. Escribir un programa que lea un fichero de texto del disco y lo imprima en
pantalla.
5. Buscar información sobre las librerías que ofrece el compilador que se
esté utilizando y comprobar si todas las funcionalidades explicadas en esta
unidad didáctica están presentes en las librerías del compilador. En caso
de que alguna función no esté disponible, intentar buscar otra función que
realice la misma o parecida operación.
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

 REFERENCIAS BIBLIOGRÁFICAS
Básica

Alonso, F. et al. Programación sin secretos. Madrid: Cultural, 1999.


C++ FAQ. Disponible en <https://isocpp.org/faq>.
Ellis, M. A. y Stroustrup, B. The Annotated C++ Reference Manual. Addison-Wesley, 1991.
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

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

Powered by TCPDF (www.tcpdf.org)


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Powered by TCPDF (www.tcpdf.org)


Sumario │

ÍNDICE SISTEMÁTICO
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

PÁGINA

Sumario ...................................................................................................... 5
Prólogo ....................................................................................................... 7

Unidad didáctica 1. Concepto de programa informático ................. 9

Objetivos de la unidad ...................................................................................................... 11

1. Introducción a las computadoras ............................................................................ 12


2. La programación ........................................................................................................ 14
3. Concepto de programa .............................................................................................. 16
4. El pseudocódigo ......................................................................................................... 20
4.1. Reglas generales del pseudocódigo ............................................................ 21

5. Estructuras de control ............................................................................................... 22


5.1. Secuencia ........................................................................................................ 22
5.2. Condiciones .................................................................................................... 22
5.2.1. Estructura condicional simple .................................................... 23
5.2.2. Estructura condicional doble ...................................................... 24
5.2.3. Estructura condicional múltiple ................................................. 26

www.udima.es 389

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

6. Estructuras de control: repeticiones ........................................................................ 29


6.1. Estructura de tipo «Mientras» ..................................................................... 29
6.2. Estructura de tipo «Hasta» .......................................................................... 31
6.3. Estructura de tipo «Para» ............................................................................. 32

Conceptos básicos .............................................................................................................. 34


Actividades de autocomprobación .................................................................................. 34
Actividades de repaso ....................................................................................................... 36
Referencias bibliográficas ................................................................................................. 39

Unidad didáctica 2. Algoritmos y sistemas de representación de


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

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

2. Diagramas de flujo y ordinogramas ........................................................................ 49


2.1. El diagrama de flujo ...................................................................................... 49
2.1.1. Características ................................................................................ 50
2.1.2. Tipos ............................................................................................... 51
2.2. El ordinograma............................................................................................... 51
2.2.1. Reglas de diseño ............................................................................ 53
2.2.2. Ordinograma del algoritmo de Euclides.................................... 53
2.2.3. Ordinograma de un número primo mayor que N.................... 53

3. La programación estructurada ................................................................................ 55


3.1. Diagramas y programa propio .................................................................... 57
3.2. Diagramas estructurados o diagramas privilegiados .............................. 60
3.2.1. El bloque secuencial, secuencia o encadenamiento ................. 60
3.2.2. El bloque condicional, condición o alternativa ......................... 60
3.2.3. El bloque de repetición, bucle o iteración ................................. 62
3.3. Programa estructurado ................................................................................. 64
3.4. Teoremas de la programación estructurada .............................................. 65
3.4.1. Teorema de estructura (existencia) ............................................ 65

390 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

Índice sistemático

3.4.2. Corolario de arriba abajo (top-down) .......................................... 65


3.4.3. Teorema de corrección (o validación) ........................................ 66
3.4.4. Teorema de descomposición ....................................................... 66

4. Diagramas estructurados arborescentes ................................................................. 67


4.1. Diagrama arborescente del MCD ............................................................... 69
5. Diagramas estructurados de la metodología Nassi-Shneiderman o de Chapin. 70
5.1. Diagrama N-S o de Chapin del MCD ......................................................... 72
5.2. Ventajas de los diagramas estructurados con respecto a los ordinogra-
mas clásicos .................................................................................................... 73

Conceptos básicos .............................................................................................................. 74


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Actividades de autocomprobación .................................................................................. 74


Actividades de repaso ....................................................................................................... 79
Referencias bibliográficas ................................................................................................. 81

Unidad didáctica 3. Tratamiento informático de un problema ...... 83

Objetivos de la unidad ...................................................................................................... 84

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

5. Codificación ................................................................................................................ 101


6. Pruebas ........................................................................................................................ 102
7. Mantenimiento ........................................................................................................... 105

Conceptos básicos .............................................................................................................. 107


Actividades de autocomprobación .................................................................................. 108
Actividades de repaso ....................................................................................................... 110
Caso práctico ....................................................................................................................... 111
Referencias bibliográficas ................................................................................................. 113

www.udima.es 391

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Unidad didáctica 4. La programación y los lenguajes informá-


ticos ......................................................................... 115

Objetivos de la unidad ...................................................................................................... 117

1. La programación ........................................................................................................ 119


2. Paradigmas de programación .................................................................................. 121
2.1. Tipos de paradigmas de programación ..................................................... 124
2.1.1. Paradigmas procedimentales u operacionales ......................... 126
2.1.2. Paradigmas declarativos .............................................................. 126
2.1.3. Paradigmas demostrativos .......................................................... 127
2.1.4. Secuencias de control en paradigmas ........................................ 128
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

3. Paradigma imperativo .............................................................................................. 129


3.1. Lenguajes imperativos orientados a expresiones y a sentencias ............ 132

4. Lenguajes de programación ..................................................................................... 133


4.1. Lenguajes máquina........................................................................................ 134
4.2. Lenguajes de bajo nivel ................................................................................ 135
4.2.1. El traductor de ensamblador ....................................................... 136
4.3. Lenguajes de alto nivel ................................................................................. 137
4.3.1. El traductor de los lenguajes de alto nivel ................................ 139
4.3.1.1. Compilación ................................................................ 139
4.3.1.2. Interpretación ............................................................. 143
4.4. Historia de los lenguajes de programación ............................................... 145

Conceptos básicos .............................................................................................................. 149


Actividades de autocomprobación .................................................................................. 149
Actividades de repaso ....................................................................................................... 152
Referencias bibliográficas ................................................................................................. 152

Unidad didáctica 5. El lenguaje imperativo C++ ................................ 155

Objetivos de la unidad ...................................................................................................... 156

1. Introducción ............................................................................................................... 157


2. Historia de C++ ........................................................................................................... 157

392 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

Índice sistemático

3. Características generales de C++ .............................................................................. 159


4. Elementos básicos de C++ ......................................................................................... 160
5. Estructura de un programa C++ .............................................................................. 163
6. Palabras reservadas de C++ ...................................................................................... 166
7. Comentarios en C++ ................................................................................................... 168

Conceptos básicos .............................................................................................................. 170


Actividades de autocomprobación .................................................................................. 170
Actividades de repaso ....................................................................................................... 173
Referencias bibliográficas ................................................................................................. 174
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Unidad didáctica 6. Expresiones ........................................................... 175


Objetivos de la unidad ...................................................................................................... 177

1. Introducción ............................................................................................................... 178


2. Constantes ................................................................................................................... 178
2.1. Constantes enteras ........................................................................................ 179
2.2. Constantes reales ........................................................................................... 184
2.3. Constantes lógicas ......................................................................................... 186
2.4. Constantes carácter ....................................................................................... 187
2.5. Constantes cadenas de caracteres ............................................................... 189

3. Variables ...................................................................................................................... 190


3.1. Nombres de variables ................................................................................... 191
3.2. Declaraciones ................................................................................................. 192
3.3. Inicializaciones ............................................................................................... 192
3.4. Identificadores constantes ............................................................................ 193

4. Tipos básicos de datos ............................................................................................... 193


4.1. Tipo entero ..................................................................................................... 194
4.2. Modificadores de tipo ................................................................................... 194
4.3. Tipo real .......................................................................................................... 196
4.4. Tipo carácter ................................................................................................... 197
4.5. Tipo lógico ...................................................................................................... 197
4.6. Tipo vacío ....................................................................................................... 197
4.7. Punteros .......................................................................................................... 198

www.udima.es 393

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

4.8. Referencias ..................................................................................................... 198


4.9. Declaraciones en bloques ............................................................................. 199
4.10. Conversiones de tipos ................................................................................... 200

5. Operadores ................................................................................................................. 201


5.1. Operadores y expresiones ............................................................................ 201
5.1.1. Operador, operando y expresión ................................................ 201
5.1.2. Operadores unarios, binarios y ternarios .................................. 202
5.2. Precedencia y asociatividad de operadores .............................................. 203
5.3. Operadores y expresiones aritméticas ....................................................... 206
5.4. Operadores y expresiones relacionales y lógicas ..................................... 209
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

5.5. Operadores y expresiones de asignación ................................................... 212


5.6. Operadores y expresiones sobre bits .......................................................... 216
5.6.1. Operador complemento a uno .................................................... 216
5.6.2. Operadores lógicos de bits .......................................................... 217
5.6.3. Operadores de desplazamiento .................................................. 218
5.6.4. Operadores de asignación con manipulación de bits .............. 219
5.7. Operadores y expresiones para el manejo de punteros ........................... 220
5.7.1. Operador dirección ....................................................................... 220
5.7.2. Operador indirección ................................................................... 221
5.8. Otros operadores ........................................................................................... 221
5.8.1. Operadores paréntesis ................................................................. 221
5.8.2. Operador condicional ................................................................... 222
5.8.3. Operadores signo .......................................................................... 223
5.8.4. Operadores de incremento y decremento ................................. 223
5.8.5. Operador tamaño .......................................................................... 224
5.8.6. Operador de conversión de tipos ............................................... 225
5.8.7. Operador coma .............................................................................. 225
5.8.8. Operadores de acceso a miembros ............................................. 226
5.8.9. Operador de acceso a vectores .................................................... 227
5.8.10. Operador de alcance ..................................................................... 227
5.8.11. Operadores «new» y «delete» ..................................................... 228

Conceptos básicos .............................................................................................................. 230


Actividades de autocomprobación .................................................................................. 230
Actividades de repaso ....................................................................................................... 233
Referencias bibliográficas ................................................................................................. 234

394 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

Índice sistemático

Unidad didáctica 7. Sentencias y entrada/salida básica ................... 235

Objetivos de la unidad ...................................................................................................... 237

1. Introducción ............................................................................................................... 238


2. Sentencias básicas ...................................................................................................... 238
2.1. Asignación ...................................................................................................... 238
2.2. Llamada a funciones ..................................................................................... 240
2.3. Sentencia «return» ......................................................................................... 241
2.4. Sentencia vacía ............................................................................................... 242

3. Sentencias de control de flujo ................................................................................... 243


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

3.1. Estructura secuencial .................................................................................... 243


3.2. Sentencias condicionales .............................................................................. 243
3.2.1. Sentencia «if» ................................................................................. 243
3.2.2. Sentencia «if-else» ......................................................................... 245
3.2.3. Sentencia «switch» ........................................................................ 246
3.3. Sentencias repetitivas ................................................................................... 248
3.3.1. Sentencia «while» .......................................................................... 248
3.3.2. Sentencia «for» .............................................................................. 250
3.3.3. Sentencia «do-while» .................................................................... 252
3.4. Sentencias de salto ........................................................................................ 253
3.4.1. Sentencia «break» .......................................................................... 253
3.4.2. Sentencia «continue» .................................................................... 255

4. Entrada/salida básica ................................................................................................. 256


4.1. Salida ............................................................................................................... 257
4.2. Entrada ............................................................................................................ 258

Conceptos básicos .............................................................................................................. 259


Actividades de autocomprobación .................................................................................. 259
Actividades de repaso ....................................................................................................... 262
Referencias bibliográficas ................................................................................................. 263

Unidad didáctica 8. Funciones ............................................................... 265

Objetivos de la unidad ...................................................................................................... 267

www.udima.es 395

Powered by TCPDF (www.tcpdf.org)


│ Sumario

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

3. Parámetros .................................................................................................................. 274


3.1. Parámetros formales ..................................................................................... 274
3.2. Parámetros actuales ...................................................................................... 275
3.3. Paso de parámetros por valor ...................................................................... 276
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

3.4. Paso de parámetros por referencia ............................................................. 277


3.5. Paso por dirección ......................................................................................... 278
3.6. Parámetros por omisión ............................................................................... 279

4. Alcance y visibilidad ................................................................................................. 281


4.1. Definición de alcance .................................................................................... 281
4.2. Variables locales ............................................................................................ 282
4.3. Variables globales .......................................................................................... 283
4.3.1. Variables globales del fichero ..................................................... 284
4.3.2. Variables globales del programa ................................................ 285
4.4. Variables estáticas ......................................................................................... 286
4.4.1. Variables globales estáticas ......................................................... 286
4.4.2. Variables locales estáticas ............................................................ 287
4.5. Resumen del modo de almacenamiento de variables .............................. 288

5. Recursividad ............................................................................................................... 289


6. Sobrecarga de funciones ........................................................................................... 292

Conceptos básicos .............................................................................................................. 294


Actividades de autocomprobación .................................................................................. 294
Actividades de repaso ....................................................................................................... 297
Referencias bibliográficas ................................................................................................. 298

Unidad didáctica 9. Tipos avanzados de datos .................................. 299

Objetivos de la unidad ...................................................................................................... 301

396 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Sumario │

Í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

3. Punteros ...................................................................................................................... 309


3.1. Declaración de punteros ............................................................................... 311
3.2. Operador puntero y dirección ..................................................................... 312
3.3. Asignación y liberación de memoria dinámica ........................................ 315
3.4. Aritmética de punteros ................................................................................. 320
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

3.5. Punteros y vectores ....................................................................................... 321

4. Cadenas ....................................................................................................................... 323


4.1. Declaración de cadenas de caracteres ........................................................ 324
4.2. Inicialización .................................................................................................. 324
4.3. Uso de cadenas de caracteres ...................................................................... 325

5. Estructuras y uniones ................................................................................................ 328


5.1. Concepto de estructura ................................................................................ 328
5.2. Declaración de estructuras ........................................................................... 328
5.3. Inicialización de estructuras ........................................................................ 329
5.4. Uso de estructuras ......................................................................................... 330
5.5. Campos de bits .............................................................................................. 332
5.6. Concepto de unión ........................................................................................ 333
5.7. Inicialización de uniones .............................................................................. 335
5.8. Uso de uniones............................................................................................... 335

6. Definiciones de tipos ................................................................................................. 336


7. Tipos enumerados ..................................................................................................... 338
7.1. Concepto de tipo enumerado ...................................................................... 338
7.2. Declaración de tipos ...................................................................................... 338
7.3. Uso de tipos enumerados ............................................................................. 339

Conceptos básicos .............................................................................................................. 341


Actividades de autocomprobación .................................................................................. 341
Actividades de repaso ....................................................................................................... 344
Referencias bibliográficas ................................................................................................. 345

www.udima.es 397

Powered by TCPDF (www.tcpdf.org)


│ Sumario

FUNDAMENTOS DE LA PROGRAMACIÓN

Unidad didáctica 10. El preprocesador de C++. Librerías .................. 347


Objetivos de la unidad ...................................................................................................... 349

1. Introducción ............................................................................................................... 350


2. Preprocesador de C++ ............................................................................................... 350
2.1. Nombres simbólicos y macros ..................................................................... 351
2.2. Inclusión de ficheros ..................................................................................... 355
2.3. Compilación condicional ............................................................................. 356
2.4. Otras directivas .............................................................................................. 359

3. Librerías ....................................................................................................................... 360


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

3.1. Cadenas de caracteres ................................................................................... 360


3.1.1. Librería cstring .............................................................................. 360
3.2. Librerías de entrada/salida .......................................................................... 362
3.2.1. Salida .............................................................................................. 364
3.2.2. Entrada ........................................................................................... 365
3.2.3. Ficheros .......................................................................................... 366
3.2.4. Formatos ......................................................................................... 367
3.2.5. Errores ............................................................................................ 372
3.3. Librería cstdlib ............................................................................................... 372
3.4. Librería cmath ................................................................................................ 374
3.5. Librería cctype ............................................................................................... 375
3.5.1. Clasificación ................................................................................... 375
3.5.2. Manipulación ................................................................................. 376
3.6. Errores ............................................................................................................. 377
3.7. Librerías limits.h y float.h ............................................................................ 378
3.8. Librería STL .................................................................................................... 379

Conceptos básicos .............................................................................................................. 383


Actividades de autocomprobación .................................................................................. 383
Actividades de repaso ....................................................................................................... 386
Referencias bibliográficas ................................................................................................. 387

398 www.udima.es

Powered by TCPDF (www.tcpdf.org)


Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Powered by TCPDF (www.tcpdf.org)


092018
Copia registrada y de uso exclusivo para: Daniel Cedres Martin - 78819838B

Powered by TCPDF (www.tcpdf.org)


David Lizcano Casas (coord.)

Loïc A. Martínez Normand


José Luis Fuertes Castro
Fernando Alonso Amo
El presente manual pretende introducir los conceptos
básicos de la construcción de programas de ordenador y

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

de alto nivel. Los ejemplos de esta parte están presentados


usando un lenguaje genérico, llamado pseudocódigo. El
objetivo de usar este pseudocódigo es poder plasmar los
conceptos de forma independiente a como se representan
en cada lenguaje de programación.
En la segunda parte se aplican los conceptos presentados
anteriormente a un lenguaje concreto de programación, el
lenguaje C++. Este lenguaje ha sido elegido por su versa-
tilidad y potencia.
El objetivo fundamental que se persigue es que el lector
pueda ser capaz de resolver problemas sencillos mediante

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

Powered by TCPDF (www.tcpdf.org)

1/1

También podría gustarte