Fundamentos de Programacion

405
UNIVERSIDAD DE GRANADA Grado en Ingeniería Informática FUNDAMENTOS DE PROGRAMACIÓN Curso: 2011/2012 Clase: Primero - Grupo: B Aviso legal: los archivos están sujetos a derechos de propiedad intelectual y su titularidad corresponde a los usuarios que los han subido a SWAD. Esto es solo una recopilación de toda la asignatura impartida en la UGR.

description

Temario de la asignatura.

Transcript of Fundamentos de Programacion

Page 1: Fundamentos de Programacion

UNIVERSIDAD DE GRANADA

Grado en Ingeniería

Informática FUNDAMENTOS DE

PROGRAMACIÓN

Curso: 2011/2012 Clase: Primero - Grupo: B

Aviso legal: los archivos están sujetos a derechos de propiedad intelectual y su titularidad corresponde a los usuarios que los han subido a SWAD. Esto es solo una

recopilación de toda la asignatura impartida en la UGR.

Page 2: Fundamentos de Programacion

TEORÍA

Curso: 2011/2012 Clase: Primero - Grupo: B

Page 3: Fundamentos de Programacion

Contenidos

I. Introducción a la Programación 1

I.1. El ordenador, algoritmos y programas . . . . . . . . . . . . 2

I.1.1. El Ordenador: Conceptos Básicos . . . . . . . . . . 2

I.1.2. Lenguajes de programación . . . . . . . . . . . . . . 3

I.1.3. Datos y Algoritmos . . . . . . . . . . . . . . . . . . . 6

I.1.4. Compilación . . . . . . . . . . . . . . . . . . . . . . 11

I.2. Especificación de programas . . . . . . . . . . . . . . . . . 13

I.2.1. Escritura y organización de un programa . . . . . . . 13

I.2.2. Elementos básicos de un lenguaje de programación 19

I.2.3. Tipos de errores en la programación . . . . . . . . . 22

I.3. Datos y tipos de datos . . . . . . . . . . . . . . . . . . . . . 24

I.3.1. Representación en memoria de datos e instrucciones 24

I.3.2. Datos y tipos de datos . . . . . . . . . . . . . . . . . 26

I.4. Operadores y Expresiones . . . . . . . . . . . . . . . . . . 38

I.4.1. Terminología en Matemáticas . . . . . . . . . . . . . 38

1

I.4.2. Operadores en Programación . . . . . . . . . . . . . 39

I.4.3. Expresiones . . . . . . . . . . . . . . . . . . . . . . 41

I.5. Tipos de datos comunes en C++ . . . . . . . . . . . . . . . 43

I.5.1. Rango y operadores aplicables a un tipo de dato . . 43

I.5.2. Los tipos de datos enteros . . . . . . . . . . . . . . 44

I.5.3. Los tipos de datos reales . . . . . . . . . . . . . . . 51

I.5.4. Operando con tipos numéricos distintos . . . . . . . 60

I.5.5. El tipo de dato carácter . . . . . . . . . . . . . . . . 64

I.5.6. El tipo de dato cadena de caracteres . . . . . . . . . 73

I.5.7. El tipo de dato lógico o booleano . . . . . . . . . . . 76

I.5.8. El tipo enumerado . . . . . . . . . . . . . . . . . . . 82

II. Estructuras de Control 85

II.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . 86

II.2. Estructura condicional . . . . . . . . . . . . . . . . . . . . 91

II.2.1. Introducción . . . . . . . . . . . . . . . . . . . . . . 91

II.2.2. Estructura condicional simple . . . . . . . . . . . . . 91

II.2.3. Condicional doble . . . . . . . . . . . . . . . . . . . 97

II.2.4. Anidamiento de estructuras condicionales . . . . . . 103

II.2.5. Construcción de estructuras condicionales . . . . . 116

II.2.6. Estructura condicional múltiple . . . . . . . . . . . . 127

II.3. Estructuras repetitivas . . . . . . . . . . . . . . . . . . . . 133

Page 4: Fundamentos de Programacion

II.3.1. Bucles controlados por condición: pre-test y post-test 133

II.3.2. Bucles controlador por contador . . . . . . . . . . . 161

II.3.3. Anidamiento de bucles . . . . . . . . . . . . . . . . . 170

II.3.4. Particularidades de C++ . . . . . . . . . . . . . . . . 178

III. Funciones y Clases 198

III.1. Funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . 199

III.1.1. Fundamentos . . . . . . . . . . . . . . . . . . . . . . 199

III.1.2. Funciones void . . . . . . . . . . . . . . . . . . . . . 227

III.1.3. Documentación de una función . . . . . . . . . . . . 231

III.1.4. Ámbito de un dato . . . . . . . . . . . . . . . . . . . 235

III.1.5. Las funciones y los principios de programación . . . 241

III.2. Clases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245

III.2.1. Motivación. Clases y Objetos . . . . . . . . . . . . . 245

III.2.2. Encapsulación . . . . . . . . . . . . . . . . . . . . . 249

III.2.3. Ocultación de información . . . . . . . . . . . . . . . 265

III.2.4. Constructores . . . . . . . . . . . . . . . . . . . . . 276

III.2.5. Diseño de una clase . . . . . . . . . . . . . . . . . . 285

III.2.6. Registros . . . . . . . . . . . . . . . . . . . . . . . . 292

III.2.7. Datos miembro constantes . . . . . . . . . . . . . . 293

IV. Vectores y Matrices 305

IV.1. Fundamentos . . . . . . . . . . . . . . . . . . . . . . . . . 306

IV.1.1. Introducción . . . . . . . . . . . . . . . . . . . . . . 306

IV.1.2. Operaciones con Vectores . . . . . . . . . . . . . . . 309

IV.2. La clase MiVector . . . . . . . . . . . . . . . . . . . . . . . 319

IV.3. Algoritmos de Búsqueda . . . . . . . . . . . . . . . . . . . 324

IV.3.1. Búsqueda Secuencial . . . . . . . . . . . . . . . . . 324

IV.3.2. Búsqueda Binaria . . . . . . . . . . . . . . . . . . . 332

IV.3.3. Otras búsquedas . . . . . . . . . . . . . . . . . . . . 335

IV.4. Otros métodos de la clase MiVector . . . . . . . . . . . . . 339

IV.5. Algoritmos de Ordenación . . . . . . . . . . . . . . . . . . 348

IV.5.1. Ordenación por Selección . . . . . . . . . . . . . . . 350

IV.5.2. Ordenación por Inserción . . . . . . . . . . . . . . . 354

IV.5.3. Ordenación por Intercambio Directo (Método de laBurbuja) . . . . . . . . . . . . . . . . . . . . . . . . 357

IV.6. Las clases ������ y ���� . . . . . . . . . . . . . . . . . . 362

IV.6.1. La clase ������ . . . . . . . . . . . . . . . . . . . . . 362

IV.6.2. La clase ���� . . . . . . . . . . . . . . . . . . . . . 370

IV.7. Vectores de varias dimensiones: Matrices . . . . . . . . . . 372

IV.7.1. Declaración . . . . . . . . . . . . . . . . . . . . . . . 372

IV.7.2. Operaciones con matrices . . . . . . . . . . . . . . . 373

IV.7.3. Más de dos dimensiones . . . . . . . . . . . . . . . 381

IV.7.4. La clase MiMatriz . . . . . . . . . . . . . . . . . . . . 382

Page 5: Fundamentos de Programacion

V. Clases (Segunda parte) 385

V.1. Copiando objetos . . . . . . . . . . . . . . . . . . . . . . . 386

V.1.1. Operador de asignación . . . . . . . . . . . . . . . . 386

V.1.2. El constructor de copia . . . . . . . . . . . . . . . . 390

V.1.3. Copiar o no copiar: He ahí el dilema . . . . . . . . . 393

V.2. Trabajando con varios objetos . . . . . . . . . . . . . . . . 394

V.2.1. Pasando objetos como parámetros . . . . . . . . . . 394

V.2.2. Objetos declarados localmente en un método y mé-todos que devuelven objetos . . . . . . . . . . . . . 401

V.2.3. Objetos como datos miembro de otros objetos . . . 426

V.2.4. Vectores de objetos. Matrices . . . . . . . . . . . . . 434

V.3. Diseño de una solución . . . . . . . . . . . . . . . . . . . . 444

V.3.1. Funciones globales versus métodos . . . . . . . . . 444

V.3.2. Tipos de relaciones entre clases . . . . . . . . . . . 450

V.3.3. Relación de dependencia . . . . . . . . . . . . . . . 452

V.3.4. Relación de asociación . . . . . . . . . . . . . . . . 454

V.3.5. Acoplamiento . . . . . . . . . . . . . . . . . . . . . . 458

V.3.6. Arquitectura por capas . . . . . . . . . . . . . . . . 459

V.3.7. Casos prácticos de diseño . . . . . . . . . . . . . . 461

V.4. Tratamiento de errores con excepciones . . . . . . . . . . . 473

VI. Recursividad 485

VI.1. El concepto matemático de Recursividad . . . . . . . . . . 486

VI.1.1. Soluciones recursivas . . . . . . . . . . . . . . . . . 486

VI.1.2. Diseño de algoritmos recursivos . . . . . . . . . . . 489

VI.2. Funciones recursivas . . . . . . . . . . . . . . . . . . . . . 491

VI.2.1. Definición de funciones recursivas . . . . . . . . . . 491

VI.2.2. Ejecución de funciones recursivas . . . . . . . . . . 492

VI.2.3. Traza de algoritmos recursivos . . . . . . . . . . . . 496

VI.3. Clases con métodos recursivos . . . . . . . . . . . . . . . 499

VI.3.1. Métodos recursivos . . . . . . . . . . . . . . . . . . 499

VI.3.2. Ordenación rápida: Quicksort . . . . . . . . . . . . . 510

VI.4. Recursividad versus iteración . . . . . . . . . . . . . . . . 516

Page 6: Fundamentos de Programacion

El color marrón se utilizará para los títulos de las secciones, apartados,etc

El color azul se usará para los términos cuya definición aparece por pri-mera vez. En primer lugar aparecerá el término en español y entre parén-tesis la traducción al inglés.

El color rojo se usará para destacar partes especialmente importantes

Algunos símbolos usados:

denota contenido que el alumno debe estudiar por su cuenta. Entracomo materia en el examen.

denota contenido de ampliación. El texto incluido en la transparen-cia es de obligada lectura aunque las referencias son de consultaopcional y no entran en el examen.

denota contenido de ampliación, a nivel de experto. No entra en elexamen.

Consejos sobre buenas prácticas de programación

denota código o prácticas de programación que pueden producirerrores lógicos graves

denota código que nos da escalofríos de sólo verlo.

denota código bien diseñado que nos ha de servir de modelo enotras construcciones.

denota algo especialmente importante.

Page 7: Fundamentos de Programacion

Reseña histórica.

Principio de Programación.

Tema I

Introducción a la Programa-ción

Objetivos:

� Introducir los conceptos básicos de programación, para poderconstruir los primeros programas.

� Introducir los principales tipos de datos disponibles en C++ pararepresentar información del mundo real.

� Enfatizar, desde un principio, la necesidad de seguir buenos hábi-tos de programación.

Autor: Juan Carlos Cubero.

Sugerencias: por favor, enviar un e-mail a ������������ ��������

Page 8: Fundamentos de Programacion

Introducción a la ProgramaciónEl ordenador, algoritmos y programas → 2

I.1. El ordenador, algoritmos y programas

I.1.1. El Ordenador: Conceptos Básicos

"Los ordenadores son inútiles. Sólo pueden darte respuestas".Pablo Picasso

� Hardware

� Software

� Usuario (User)

� Programador (Programmer)

� Lenguaje de Programación (Programming Language)

Introducción a la ProgramaciónEl ordenador, algoritmos y programas → Lenguajes de programación 3

I.1.2. Lenguajes de programación

Programa (Program): Es el conjunto de instrucciones especificadas enun lenguaje de programación concreto, que pueden ejecutarse en un or-denador y que resuelven un problema

Lenguaje de programación (Programming language): Lenguaje formal uti-lizado para comunicarnos con un ordenador e imponerle la ejecución deun conjunto de órdenes.

Código binario (Binary code):

"There are 10 types of people in the world, those who can read binary,and those who can’t".

Page 9: Fundamentos de Programacion

Introducción a la ProgramaciónEl ordenador, algoritmos y programas → Lenguajes de programación 4

� Lenguaje ensamblador (Assembly language). Depende del micro-pocesador (Intel 8086, Motorola 88000, etc) Se usa para progra-mar drivers, microcontroladores (que son circuitos integrados queagrupan microprocesador, memoria y periféricos), compiladores,etc. Se ve en otras asignaturas.

������ �����

����

����

���� �� �� ����� �� �����

����

��� ��� ����

��� ��� ��

��� ��� ����� ���� ��

��� ��� �

� ���

� �

� Lenguajes de alto nivel (High level language) (C, C++, Java, Lisp,Prolog, Perl, Visual Basic, C#, Go ...) En esta asignatura usaremosC++ (ISO C++).

�� ���� ���!���"

��� # ����$�� ��%

� ��� &'(

�� )���� �� ��)%

*

Introducción a la ProgramaciónEl ordenador, algoritmos y programas → Lenguajes de programación 5

� Reseña histórica del lenguaje C++

1967 Martin Richards: BCPL para escribir S.O.

1970 Ken Thompson: B para escribir UNIX (inicial)

1972 Dennis Ritchie: C

1983 Comité Técnico X3J11: ANSI C

1983 Bjarne Stroustrup: C++

1989 Comité técnico X3J16: ANSI C++

1990 Internacional Standarization Organization ���������������

Comité técnico JTC1: Information Technology

Subcomité SC-22: Programming languages, their environments and systemsoftware interfaces.

Working Group 21: C++

������������ ����������������������

2011 Nuevo estándar. Buscar C++11 en Internet.

¿Qué programas se han hecho en C++?

Google, Amazon, sistema de reservas aéreas (Amadeus), omnipresente en la indus-tria automovilística y aérea, sistemas de telecomunicaciones, el explorador Mars Ro-vers, el proyecto de secuenciación del genoma humano, videojuegos como Doom,Warcraft, Age of Empires, Halo, la mayor parte del software de Microsoft y unagran parte del de Apple, la máquina virtual Java, Photoshop, Thunderbird y Firefox,MySQL, OpenOffice, etc.

Entrevista reciente a Bjarne Stroustrup:

�������������� �������������� ������������������������ � � ��

������������������

Page 10: Fundamentos de Programacion

Introducción a la ProgramaciónEl ordenador, algoritmos y programas → Datos y Algoritmos 6

I.1.3. Datos y Algoritmos

Algoritmo (Algorithm): es una secuencia ordenada de instrucciones queresuelve un problema concreto, atendiendo a las siguientes característi-cas básicas:

� Corrección (sin errores).

� Precisión (no puede haber ambigüedad).

� Repetitividad (en las mismas condiciones, al ejecutarlo, siempre seobtiene el mismo resultado).

� Finitud (termina en algún momento). Número finito de órdenes noimplica finitud.

� Características esenciales:

� Validez (resuelve el problema pedido)

� Eficiencia (lo hace en un tiempo aceptable)

Un dato (data) es una representación simbólica de una característica opropiedad de una entidad.

Los algoritmos operan sobre los datos. Usualmente, reciben unos datosde entrada con los que operan, y a veces, calculan unos nuevos datos desalida.

Introducción a la ProgramaciónEl ordenador, algoritmos y programas → Datos y Algoritmos 7

Ejemplo. Algoritmo de la media aritmética de N valores.

� Datos de entrada: N, valor1, valor2, ..., valorN

� Datos de salida: media

� Instrucciones en lenguaje natural:Sumar los N valores y dividir el resultado por N

Ejemplo. Algoritmo para la resolución de una ecuación de primer gradoax + b = 0

� Datos de entrada: a, b

� Datos de salida: x

� Instrucciones en lenguaje natural:Calcular x como el resultado de la división −b/a

Podría mejorarse el algoritmo contemplando el caso de ecuaciones degeneradas

Ejemplo. Algoritmo para el cálculo de la hipotenusa de un triángulo rec-tángulo.

� Datos de entrada: lado1, lado2

� Datos de salida: hipotenusa

� Instrucciones en lenguaje natural:

hipotenusa =

√lado12 + lado22

Page 11: Fundamentos de Programacion

Introducción a la ProgramaciónEl ordenador, algoritmos y programas → Datos y Algoritmos 8

Ejemplo. Algoritmo para ordenar una lista de valores numéricos.

(9, 8, 1, 6, 10, 4) −→ (1, 4, 6, 8, 9, 10)

� Datos de entrada: el vector

� Datos de salida: el mismo vector

� Instrucciones en lenguaje natural:

– Calcular el mínimo valor de todo el vector

– Intercambiarlo con la primera posición

– Volver a hacer lo mismo con el vector formado por todas lascomponentes menos la primera.

(9, 8, 1, 6, 10, 4) →(1, 8, 9, 6, 10, 4) →(X, 8, 9, 6, 10, 4) →(X, 4, 9, 6, 10, 8) →(X,X, 9, 6, 10, 8) →· · ·

Introducción a la ProgramaciónEl ordenador, algoritmos y programas → Datos y Algoritmos 9

Una vez diseñado el algoritmo, pasamos a implementarlo en un lenguajede programación concreto.

"First, solve the problem. Then, write the code".

Implementación de un algoritmo (Algorithm implementation): Transcrip-ción a un lenguaje de programación de un algoritmo.

Ejemplo. Implementación del algoritmo para el cálculo de la media (para4 valores) en C++:

���� � ���� � ����� � ���� � ������

����� � ���� � ��

Ejemplo. Implementación del algoritmo para el cálculo de la hipotenusa:

���������� � ������������� � �������������

Un programa incluirá la implementación de uno o más algoritmos.

Ejemplo. Programa para dibujar planos de pisos.Utilizará algoritmos para dibujar cuadrados, de medias aritméticas, sali-das gráficas en plotter, etc.

Muchos de los programas que se verán en FP implementarán un únicoalgoritmo.

Page 12: Fundamentos de Programacion

Introducción a la ProgramaciónEl ordenador, algoritmos y programas → Datos y Algoritmos 10

Ampliación:Uno de los pilares fundamentales de la informática lo constituye la máquinade Turing (Turing machine). Es un modelo formal de ordenador basado enun alfabeto, un conjunto de estados y un conjunto de transiciones sobredichos estados.

La máquina de Turing permite realizar cualquier cómputo que un compu-tador digital sea capaz de realizar.Turing demostró que existen problemas que una máquina no puede resol-ver.Antes de diseñar la máquina de Turing, éste ayudó a descifrar los mensajesencriptados por la máquina Enigma en la segunda guerra mundial.Consultad en Wikipedia la biografía de Turing.También puede consultarse:���������������� ��������������

La importancia de Turing en el campo de la Informática es tal que el equiva-lente a los premios Nobel llevan su nombre: A.M.Turing Award, patrocinadopor Intel y Google.Por cierto, el servidor de la ETS Informática se llama �������������.

Introducción a la ProgramaciónEl ordenador, algoritmos y programas → Compilación 11

I.1.4. Compilación

Al código escrito en un lenguaje concreto se le denomina código fuente(source code). Éste se guarda en ficheros de texto normales (en el casode C++ tienen extensión ����).

�����������

����� ������ ��� �� ������ �� �� ���������

�� �� ������� ��������� �������� �� ����� �� �������

�������� �������� �� ��������� �� �� ����� �� ���

�������� ������� �� ��������� �� �� ����� ����������

����� ��������� ����

��� ����� ! �� ����� ��������

��"�� ���#� �� $����� %���"��� ��� �����

��"�� ���&� �� �� �� ���� ' �� ���������

��"�� ����������

��� �� (�����)�� �� ������� ��� ���� �����* ( �

��� �� ���#�

��� �� (�����)�� �� ������� ��� ������ �����* (�

��� �� ���&�

��������� + �,�����# ���# - ���& ���& �

��� �� (.�/� ��������� %��� ( �� ��������� �� (.�.�( �

0

Page 13: Fundamentos de Programacion

Introducción a la ProgramaciónEl ordenador, algoritmos y programas → Compilación 12

����������� es un simple fichero de texto. Para obtener el programaejecutable (el fichero en binario que puede ejecutarse en un ordenador)se utiliza un compilador:

Código fuente

del programa−→ Compilación −→ Programa

ejecutable

La extensión del programa ejecutable en Windows es � �

Código Fuente: �����������

������� ����������

����� �������� ����

��� ������ �

������ ������

��� �� ���������� �� ��������

�� �� ������

−→ Compilador −→

Programa Ejecutable: ���������� �

� �� �

� � ���� �

�� � �

���� � ����

��� �����

��� � � ��

�� � ���

�� ����

Introducción a la ProgramaciónEspecificación de programas → 13

I.2. Especificación de programas

I.2.1. Escritura y organización de un programa

� Los programas en C++ pueden dividirse en varios ficheros aunquepor ahora vamos a suponer que cada programa está escrito en unúnico fichero (�����������).

� Se pueden incluir comentarios en lenguaje natural.

� ���������� ��

������ ������ �

�� ���������� � ���� �����

El texto de un comentario no es procesado por el compilador.

� Al principio del fichero se indica que vamos a usar una serie derecursos definidos en un fichero externo o biblioteca (library)

������� ����������

������� ������

� A continuación aparece ��� ������� que indica que comienza elprograma principal. Éste se extiende desde la llave abierta �, hastaencontrar la correspondiente llave cerrada.

� Dentro del programa principal van las sentencias (senten-ce/statement) que componen el programa. Una sentencia es unaparte del código fuente que el compilador puede traducir en unainstrucción en código binario.

� Las sentencias van obligatoriamente separadas por punto y coma(�)

� El compilador va ejecutando las sentencias secuencialmente dearriba abajo. En el tema II se verá como realizar saltos, es decir,interrumpir la estructura secuencial.

Page 14: Fundamentos de Programacion

Introducción a la ProgramaciónEspecificación de programas → Escritura y organización de un programa 14

� Cuando llega a la llave cerrada � correspondiente a ������, y sino han habido problemas, el programa termina de ejecutarse y elSistema Operativo libera los recursos asignados a dicho programa.

Existen varios tipos de sentencias:

� Sentencias de declaración de datos (data)

Cada dato que usemos en un programa debe declararse al principio (des-pués de ����), asociándole un tipo de dato concreto.

��� �����

��� �����

��� ���� ����

Declara tres datos (variables) de tipo real que el programador puede usaren el programa.

� Sentencias de cálculo

A través de la asignación �

���� � ��

���� � ��

���� ��� � �������������� � �����������

asigna a la variable ���� ��� el resultado de evaluar lo que aparece a laderecha de la asignación.Nota. No confundir � con la igualdad en Matemáticas

Introducción a la ProgramaciónEspecificación de programas → Escritura y organización de un programa 15

� Sentencias de Entrada/Salida

� Sentencias para mostrar información en el periférico de salida es-tablecido por defecto.En FP, dicho periférico será la pantalla, pero podría ser un ficheroen disco o dispositivo externo (impresora, plotter, puerto FireWire,etc.).Se construyen usando ����, que es un recurso externo incluido enla biblioteca ������.

���� �� � ����� � �� �������

– Lo que haya dentro de un par de comillas dobles se muestratal cual, excepto los caracteres precedidos de �. Por ejemplo,�� hace que el cursor salte al principio de la línea siguiente.���� �� ������������ ���� � ��������� ���� ������

���� �� ����� ������ �� �� ���� �������

– Los números se escriben tal cual (decimales con punto)���� �� �� ! "#$%�

– Si ponemos una variable, se imprime su contenido.

���� �� ���&�������� � �������� ��� ����� �����' ��

�����

(�������� ) �*��+��� ,��� - ���$,���$.�

���� �� ���/ (�������� ��� �'

���� �� (���������

Observad el espacio al final del mensaje.

¿Qué haría lo siguiente? ���� �� �(����������

– Podemos usar una única sentencia:���� �� ���/ (�������� ��� � �� (���������

Page 15: Fundamentos de Programacion

Introducción a la ProgramaciónEspecificación de programas → Escritura y organización de un programa 16

– Aunque no es recomendable, también pueden incluirse expre-siones como:

���� �� ��� �� ������ ��� � �� ��������������������������

Es mejor almacenar previamente el valor de la expresión enuna variable (�� ������) y luego utilizarla donde se necesite(por ejemplo, para imprimir su valor)

Es importante dar un formato adecuado a la salida de datos enpantalla. El usuario del programa debe entender claramente el sig-nificado de todas sus salidas.

�� ���

���� ���� ! "#�

��$��� ���� ! %&�

���� �� ���� ���� �� ��$��� ����� �� '$ ��$� "#%&

�� (')*�

���� �� ���+�$ ���� �� ����� ! � �� ���� �����

���� �� ���*,$��� ���� �� ����� ! � �� ��$��� �����

Introducción a la ProgramaciónEspecificación de programas → Escritura y organización de un programa 17

� Sentencias para leer datos desde el dispositivo de entrada estable-cido por defecto. Por ahora, será el teclado. Se construyen usando���, que es un recurso externo incluido en la biblioteca ������.

��� �� ��� ���

Por ejemplo, ��� �� ����, espera a que el usuario introduzca unvalor real (��� ��) desde el teclado (dispositivo de entrada) y, cuan-do se pulsa la tecla �����, lo almacena en la variable ����. Confor-me se va escribiendo el valor, éste se muestra en pantalla, inclu-yendo el salto de línea.�

�La lectura de datos con ��� puede considerarse como unaasignación en tiempo de ejecución

Las entradas de datos deben etiquetarse adecuadamente:

�� ����

��� �� �����

��� �� �����

�� �����

���� �� ���������� � ��� ���� ��� !���� ������ ��

��� �� �����

���� �� ���������� � ��� ���� ��� �� ���� ������ ��

��� �� �����

Cuando la entrada se realiza desde un fichero (y no el teclado), la lecturaes automática sin que se espere la tecla �����.

Page 16: Fundamentos de Programacion

Introducción a la ProgramaciónEspecificación de programas → Escritura y organización de un programa 18

Estructura básica de un programa (los corchetes delimitan secciones op-cionales):

[ /* Breve descripción en lenguaje natural

de lo que hace el programa */ ]

[ Inclusión de recursos externos ]

����� ������� ���

��� �������

[Declaración de datos]

[Sentencias del programa separadas por ;]

Introducción a la ProgramaciónEspecificación de programas → Elementos básicos de un lenguaje de programación 19

I.2.2. Elementos básicos de un lenguaje de pro-gramación

I.2.2.1. Tokens y reglas sintácticas

Cada lenguaje de programación tiene una sintaxis propia que debe res-petarse para poder escribir un programa. Básicamente, queda definidapor:

a) Los componentes léxicos (tokens). Formados por caracteres al-fanuméricos y/o simbólicos. Representan la unidad léxica mínimaque el lenguaje entiende.

���� � � �� � ����� �� �

Pero por ejemplo, ni � ni ��� son tokens válidos.

b) Reglas sintácticas (Syntactic rules): determinan cómo han de com-binarse los tokens para formar sentencias. Algunas se especificancon tokens especiales (formados usualmente por símbolos):

– Separador de sentencias �

– Para agrupar varias sentencias se usa � �

Se verá su uso en el tema II. Por ahora, sirve para agrupar las sentencias

que hay en el programa principal

– Para agrupar expresiones (fórmulas) se usa � �

� ����� ����������� � ����������� ��

Page 17: Fundamentos de Programacion

Introducción a la ProgramaciónEspecificación de programas → Elementos básicos de un lenguaje de programación 20

I.2.2.2. Palabras reservadas

Suelen ser tokens formados por caracteres alfabéticos.Tienen un significado específico para el compilador, y por tanto, el pro-gramador no puede definir variables con el mismo identificador.

Algunos usos:

� ����

� Para definir tipos de datos como por ejemplo ����

� Para establecer el flujo de control (control flow), es decir, para es-pecificar el orden en el que se han de ejecutar las sentencias, como��, � �, ��� etc.Estos se verán en el tema 2.

�� ������ �����������

��� �������

���� ����� �� ���� � �� ����� � ���� ���������

���� ����� �� ���� � �� ����� � ���� ���������

Introducción a la ProgramaciónEspecificación de programas → Elementos básicos de un lenguaje de programación 21

Palabras reservadas comunes a C (C89) y C++

auto break case char const continue default

do double else enum extern float for

goto if int long register return short

signed sizeof static struct switch typedef union

unsigned void volatile while

Palabras reservadas adicionales de C++

and and_eq asm bitand bitor bool catch

class compl const_cast delete dynamic_cast explicit export

false friend inline mutable namespace new not

not_eq operator or or_eq private protected public

reinterpret_cast static_cast template this throw true try

typeid typename using virtual wchar_t xor xor_eq

Palabras reservadas añadidas en C99

_Bool _Complex _Imaginary inline restrict

Page 18: Fundamentos de Programacion

Introducción a la ProgramaciónEspecificación de programas → Tipos de errores en la programación 22

I.2.3. Tipos de errores en la programación

� Errores en tiempo de compilación (Compilation error)Ocasionados por un fallo de sintaxis en el código fuente.No se genera el programa ejecutable.

�� �������� ��� ��

�� ����� ������� ���

���� �������� ����

� � ��� � !

���"�� ����#$

���"�� ���� %&

���"�� '����� ���$

����# ( %�

����% ( )

'����� ��� ( �*��!����#������# + ����%�����%,�

���� �� -.� '����� ��� /��� �� '����� ����

,

Introducción a la ProgramaciónEspecificación de programas → Tipos de errores en la programación 23

"Software and cathedrals are much the same. First we build them,then we pray".

� Errores en tiempo de ejecución (Execution error)Se ha generado el programa ejecutable, pero se produce un errordurante la ejecución.

��� ����������

��� ��������� �

���������� � �

��������� � � � � ����������

� Errores lógicos (Logic errors)Se ha generado el programa ejecutable, pero el programa ofreceuna solución equivocada.

���������

���� � �

���� � �

���������� � ���� ����� ���� � ����� �����

���������

Page 19: Fundamentos de Programacion

Introducción a la ProgramaciónDatos y tipos de datos → 24

I.3. Datos y tipos de datos

I.3.1. Representación en memoria de datos e ins-trucciones

Un programa realiza instrucciones y opera con datos. Una vez compiladoel programa, todo son combinaciones adecuadas de 0 y 1.

UNIDAD UNIDAD

ENTRADA

CPU

SALIDA

MEMORIA PRINCIPAL

0101100 11110110 00000001 101000010001111 11100011 10100100 101110011111111 00111111 11010010 00100100

MEMORIA MASIVA

datos e instrucciones datosdatosinstrucciones

datos e instrucciones

DE CONTROL ARITMETICO-LOGICA

Introducción a la ProgramaciónDatos y tipos de datos → Representación en memoria de datos e instrucciones 25

Datos

"Juan Pérez" −→ 1 0 1 1 .. 0 1 1

75225813 −→ 1 1 0 1 .. 0 0 0

3.14159 −→ 0 0 0 1 .. 1 1 1

Instrucciones

Abrir Fichero −→ 0 0 0 1 .. 1 1 1

Imprimir −→ 1 1 0 1 .. 0 0 0

Nos centramos en los datos.

Page 20: Fundamentos de Programacion

Introducción a la ProgramaciónDatos y tipos de datos → Datos y tipos de datos 26

I.3.2. Datos y tipos de datos

Al trabajar con un lenguaje de alto nivel, no haremos referencia a la se-cuencia de 0 y 1 que codifican un valor concreto, sino a lo que representapara nosotros.

Un dato (data) es un conjunto de celdas de memoria que tiene asociadoun nombre -identificador (name)- y un contenido -valor (value)-.

������������ Juan Pérez

������ ������� 75225813

�� 3.14159

Un programa necesitará representar datos de diverso tipo (cadenas decaracteres, enteros, reales, etc). Para cada tipo, el lenguaje ofrece un tipode dato (data type).

������ �������������

��� ������ ��������

����� ���

������������ � ���� �������

������ ������� � ���������

�� � � �!��"�

Introducción a la ProgramaciónDatos y tipos de datos → Datos y tipos de datos 27

Por ejemplo, en C++:

Tipos

⎧⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎩

Simples

⎧⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎩

Numéricos

⎧⎨⎩

Enteros : ���� ����� ���

Reales : ���� ��� ��� ���

Caracteres : ���

Lógico : ���

Puntero : �

Enumerado : ����

Compuestos

⎧⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎩

Vectores y matrices

Cadena de caracteres :

Vectores de caracteres,

������

Registros

Clases

Por ahora sólo usaremos ��� ��, ���, ��� y ������.

Page 21: Fundamentos de Programacion

Introducción a la ProgramaciónDatos y tipos de datos → Datos y tipos de datos 28

I.3.2.1. Literales

Son la especificación de un valor concreto de un tipo de dato. Dependien-do del tipo, tenemos:

� Literales numéricos (numeric literals): son tokens numéricos.Para representar datos reales, se usa el punto � para especificar

la parte decimal:� � ���

� Literales de cadenas de caracteres (string literals): Son cero o máscaracteres encerrados entre comillas dobles:�����

� Literales de otros tipos, como literales de caracteres (character li-terals) , Literales lógicos (boolean literals) �� �, etc.

I.3.2.2. Declaración de variables

Cada variable que se use en un programa debe declararse al principio(después de ���), asociándole un tipo de dato concreto y un identifica-dor.

� Al declarar una variable, el compilador reserva una zona de memo-ria para trabajar con ella. Ninguna otra variable podrá usar dichazona.

� Cada variable debe estar asociado a un único tipo de dato (el tipono puede cambiarse durante la ejecución).El valor que se le puede asignar a una variable depende del tipo dedato con el que es declarado.

Introducción a la ProgramaciónDatos y tipos de datos → Datos y tipos de datos 29

� Formas de declarar variables:

� Un único identificador por declaración:

������ ����������� ���

������ ����������� ���

���

������ ������

������ ������

������ ����������

� Varios identificadores por declaración:

������ ����������� �� ���� ���� �� ������

������ ������ ������ ����������

� Opcionalmente, se puede dar un valor inicial durante la declara-ción:

������ ����������� � � ����� ���������

������ ����������� � � ����� ���������

����������� �����

������ ���� � ����

equivale a:������ �����

���� � ����

Page 22: Fundamentos de Programacion

Introducción a la ProgramaciónDatos y tipos de datos → Datos y tipos de datos 30

Cuando se declara una variable y no se inicializa, ésta no tiene ningúnvalor asignado por defecto. Puesto que desconocemos su valor, lo po-dremos considerar como basura, y lo representaremos gráficamente por�.

�� ������� ��� ���� ��� �� ��������� � ������ ��

�� � ���� �� � ������

��

����� �� ���������

���� ������� ����

��� ������

�� ��� ���������� ��� �� ������� �� ��� �� � ���

�� ��� ���������� �� �������� � ������� �� � ���

���������� ��

?

���������

?

�� � �� !"����� #�� ������� �� ��$ !�

��� �� ���������� ���

��������� % ���������� �� � &'()�

�� � �� ! �������� � ������$ ! �� ����������

*

���������� ��

32538.0

���������

4229.94

Introducción a la ProgramaciónDatos y tipos de datos → Datos y tipos de datos 31

Un error lógico muy común es usar una variable no asignada:

��� �������

�� � �� ��������� �� �� ��� ����� �� ����

�� � ��������� �� ��������� � �� ����� �� ����

�������� � �� �������� � ����� �� !�

��� "" #��������� � �� ���� # "" ���������

$

I.3.2.3. Datos constantes

Podríamos estar interesados en usar variables a las que sólo permitimostomar un único valor, fijado de antemano. Es posible con una constante(constant). Se declaran como sigue:

���� "���%"�����&%� "�'�������%�

� A las constantes se les aplica las mismas consideraciones que hi-cimos con las variables, sobre tipo de dato y reserva de memoria.

� Suelen usarse identificadores sólo con mayúsculas para diferen-ciarlos de las variables.

Page 23: Fundamentos de Programacion

Introducción a la ProgramaciónDatos y tipos de datos → Datos y tipos de datos 32

��

�������� � � �� �� ��� � �� �� � ��������� �

� ��� �� � ���� �� � �� ���� ��� ������

��

� ����� � ��������

� �� ��������� ����

�� �� ��� �

����� ����� � ! "#$%$&�

����� ����' ��� �' ���� ���

� ! "#$(� �� �) *���� �� ���� ��� +� ,)�

��� �� - �����.�� �� /���� ��� ��� � -�

� � �� ��� ��

���� ! � � ��� � � ��� ��

���� �� ! 0 � � � ��� ��

��� �� -*� ���� /��� - �� �����

��� �� -1� ���� �� /��� - �� ���� ���

2

Ventaja declaración de constantes:

� Información al propio programador.

� Imposibilidad de cambiarlo por error (� ).

� Código menos propenso a errores. Para cambiar el valor de � , (porejemplo por "#$%$(304), sólo hay que tocar en la línea de declara-ción de la constante.

Introducción a la ProgramaciónDatos y tipos de datos → Datos y tipos de datos 33

��

�������� ��� ������ �� � � ���� � ����� �

� �� ��� � �� �� ���

��

������ ������ ���

��� �������

���� ����� ������ !"# �� ��� ���$ ���%�� � &����

����� � � ����# �� � � ���� � �����' � ����

����� �������(�����# �� )������ �����' � ����

�������(�����

?

����

0.18

� � ����

?

��� �� *�������+� ������� �����, *#

�� �� �������(�����#

� � ���� � �������(����� � ����#

��� �� *-� � � ���� � �����, * �� � � ����#

.

�������(�����

32538

����

0.18

� � ����

4229.94

Page 24: Fundamentos de Programacion

Introducción a la ProgramaciónDatos y tipos de datos → Datos y tipos de datos 34

Formalmente, al conjunto de variables y constantes, se le denomina da-tos. Así pues, los datos se pueden clasificar como:

datos

⎧⎨⎩

variables

constantes

� Las variables son datos cuyo valor puede variar a lo largo del pro-grama, p.e., �����.

� Las constantes son datos cuyo contenido no varía a lo largo de laejecución del programa, p.e., el número π.

Una sintaxis de programa algo más completa:

[ /* Breve descripción en lenguaje natural

de lo que hace el programa */ ]

[ Inclusión de recursos externos ]

��� ���� ��� ����

�� ������

[Declaración de constantes]

[Declaración de variables]

[Sentencias del programa separadas por ;]

Introducción a la ProgramaciónDatos y tipos de datos → Datos y tipos de datos 35

I.3.2.4. Normas para la elección del identificador

Cada dato necesita un identificador único. Un identificador de un dato esun token formado por caracteres alfanuméricos con las siguientes res-tricciones:

� Debe empezar por una letra o subrayado (_)

� No pueden contener espacios en blanco ni ciertos caracteres es-peciales como letras acentuadas, la letra eñe, las barras � o �, etc.Ejemplo: ����� ����� �� ���������

� El compilador determina la máxima longitud que pueden tener (porejemplo, 31 caracteres)

� Sensibles a mayúsculas y minúsculas.���� y ���� son dos identificadores distintos.

� No se podrá dar a un dato el nombre de una palabra reservada. Noes recomendable usar el nombre de algún identificador usado enlas bibliotecas estándar (por ejemplo, ����)

� ������ � �������

�� �� �������� ����

�� �� ����

��� �� ����� �� !� �� � ���" �

��� �� �� �� �� !� �� � ���" �

Ejercicio. Determinar cuáles de los siguientes son identificadores váli-dos. Si son inválidos explicar por qué.

a) �� ���� b) ��� ��� c) ��# $��% d) �� �

e) ��� � & � ��� �� f) � ��� '� g) � ��(�

Page 25: Fundamentos de Programacion

Introducción a la ProgramaciónDatos y tipos de datos → Datos y tipos de datos 36

� Consejos muy importantes para elegir el identificador de un dato:

� El identificador de un dato debe reflejar su semántica (contenido).Por eso, salvo excepciones (como las variables contadoras de losbucles -tema II-) no utilizaremos nombres con pocos caracteres

�� ��� ��� ��

������ � ��� � ��� ��������

� No utilizaremos nombres genéricos

��� ������

����� ������������

� Usaremos minúsculas para los datos variables. Las constantes seescribirán en mayúsculas. Los nombres compuestos se separaráncon subrayado �:

����������������� ����

������������������� �����

� No se nombrarán dos datos con identificadores que difieran única-mente en la capitalización, o un sólo carácter.

����� ������ ����

����� ���������������� ��������

Hay una excepción a esta norma. Cuando veamos las clases, po-dremos definir una con el nombre ���� y un objeto instancia dedicha clase con el nombre ����.

� Cuando veamos clases, funciones y métodos, éstos se escribiráncon la primera letra en mayúscula. Los nombres compuestos sesepararán con una mayúscula.

Clase ���������, Método ������

Introducción a la ProgramaciónDatos y tipos de datos → Datos y tipos de datos 37

En el examen, se baja puntos por no seguir las anterioresnormas.

Page 26: Fundamentos de Programacion

Introducción a la ProgramaciónOperadores y Expresiones → 38

I.4. Operadores y Expresiones

I.4.1. Terminología en Matemáticas

Notaciones usadas en los operadores matemáticos:

� Notación prefija (Prefix notation). El operador va antes de los argu-mentos. Estos suelen encerrarse entre paréntesis.�������� ��������� ���������� ������

� Notación infija (Infix notation). El operador va entre los argumen-tos.��� ���

Según el número de argumentos, diremos que un operador es:

� Operador unario (Unary operator). Sólo tiene un argumento:�������� ��������

� Operador binario (Binary operator). Tienes dos argumentos: ���������� ������ ��� ���

� Operador n-ario (n-ary operator). Tiene más de dos argumentos.

Introducción a la ProgramaciónOperadores y Expresiones → Operadores en Programación 39

I.4.2. Operadores en Programación

Los lenguajes de programación proporcionan operadores que permitenmanipular los datos.

� Se denotan a través de tokens alfanuméricos o simbólicos.

� Suelen devolver un valor y actúan sobre ciertos datos (variables oconstantes), literales y sobre el resultado que dan otros operado-res.

� Tipos de operadores:

� Los definidos en el núcleo del compilador.No hay que incluir ninguna bibliotecaSuelen usarse tokens simbólicos para su representación y suelenser infijos

Ejemplos: � (suma), � (resta), � (producto), etc.

� Los definidos en bibliotecas externas.

Por ejemplo, �����

Suelen usarse tokens alfanuméricos para su representación y sue-len ser prefijos. Si hay varios argumentos se separan por una co-ma.

��� � ����� � ��������

Tradicionalmente se usa el término operador (operator) a secas para de-notar los primeros, y el término función (function) para los segundos.

A los argumentos de las funciones se les denomina parámetros (parame-ter).

Page 27: Fundamentos de Programacion

Introducción a la ProgramaciónOperadores y Expresiones → Operadores en Programación 40

��� ������ �

��� � ��� �� � ����������

� ��� ����� �����

� �� ����� !� �� "��� ��� ���� �

�� ## �����

$$ %��&������ "'�����(

���� � �� ) *+������ ���

���� � �� ) ���� ) �����

En general:

"������� � ,-*����.��

Primero se evalúa la expresión en la parte derecha de la asignación yluego se realiza la asignación.

Introducción a la ProgramaciónOperadores y Expresiones → Expresiones 41

I.4.3. Expresiones

Una expresión (expression) es una combinación de datos y operadoressintácticamente correcta, que el compilador evalúa y devuelve un valor.

���

�����

����������

���������� � ��������

�� ������������ � ���������

Así pues, los operadores y funciones actúan, en general, sobre expresio-nes. Las expresiones pueden aparecer a la derecha de una asignación,pero no a la izquierda.

��� � ����� �� � � �� �����������

¿Qué haría lo siguiente?

������ ���� � ��

���� � ���� � ��

Una expresión NO es una sentencia de un programa:

� Expresión: �� ������������ � ���������

� Sentencia: ���������� � �� ������������ � ����������

Page 28: Fundamentos de Programacion

Introducción a la ProgramaciónOperadores y Expresiones → Expresiones 42

Cuando el compilador evalúa una expresión, devuelve un valor de un tipode dato (entero, real, carácter, etc.). Diremos que la expresión es de dichotipo de dato.

Por ejemplo:

� � � es una expresión entera

��� � ��� es una expresión de reales

�� ���� �

������ ���������

�� ����������

�������� � ��� � ����

���������� � � � ��

������

Nota. Cuando se usa una expresión dentro de ���, el compilador detectael tipo de dato y la imprime de forma adecuada.

��� �� ����������� � � �� ����

��� �� ����������� � � �� ��������

Imprime en pantalla:

�������� �

�������� � !"�#

Introducción a la ProgramaciónTipos de datos comunes en C++ → 43

I.5. Tipos de datos comunes en C++

I.5.1. Rango y operadores aplicables a un tipo dedato

El comportamiento de un tipo de dato viene dado por:

� El rango (range) de valores que puede representar, que depende dela cantidad de memoria que dedique el compilador a su representa-ción interna. Intuitivamente, cuanta más memoria se dedique paraun tipo de dato, mayor será el número de valores que podremosrepresentar.

� El conjunto de operadores que pueden aplicarse a los datos de esetipo.

Ampliación:La cantidad de memoria que el compilador asigna a cada tipo se puede con-sultar con el operador ������������ cuyo resultado es un entero quecontiene el número de bytes asignados a ����. ������ es un operadorpues está en el núcleo del compilador, pero se usa en forma prefija, ence-rrando el argumento entre paréntesis, como las funciones.Los valores mínimos y máximos que se pueden representar para cada tipo,se pueden consultar en los ficheros ����� y ����. Consultad también:������������ ������ ����������������������������

Page 29: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → Los tipos de datos enteros 44

I.5.2. Los tipos de datos enteros

I.5.2.1. Representación de los enteros

Propiedad fundamental: Cualquier entero puede descomponerse como lasuma de determinadas potencias de 2.

53 = 0∗215+0∗214+0∗213+0∗212+0∗211+0∗210+0∗29+0∗28+0∗27+

+0 ∗ 26 + 1 ∗ 25 + 1 ∗ 24 + 0 ∗ 23 + 1 ∗ 22 + 0 ∗ 21 + 1 ∗ 20

La representación en binario sería la secuencia de los factores (1,0) -bits-que acompañan a las potencias:

0000000000110101

� Dos elementos a combinar: �� �

� r posiciones. Por ejemplo, r = 16

� Se permiten repeticiones e importa el orden0000000000110101 �= 0000000000110110

� Número de datos distintos representables = 2r

Ampliación:La forma fácil de representar el signo sería añadiendo otro bit al principiopara indicar si es positivo o negativo (bit de signo). Los ordenadores ac-tuales usan otras técnicas que agilizan los cómputos. Buscar en Internet:Representación de números con signo

Introducción a la ProgramaciónTipos de datos comunes en C++ → Los tipos de datos enteros 45

I.5.2.2. Rango de los enteros

Subconjunto del conjunto matemático Z. La cardinalidad dependerá delnúmero de bits (r) que cada compilador utiliza para su almacenamiento.

Los compiladores suelen ofrecer distintos tipos enteros. En C++:������ ���� ��� ������ , etc. El más usado es ���.

El estándar de C++ no obliga a los compiladores a usar un tamaño deter-minado.

Lo usual es que un ��� ocupe la longitud de la palabra (word) del seg-mento de datos del sistema operativo. Hoy en día, lo usual es 32 bits (8bytes) y 64 bits (16 bytes). En el caso de 32 bits el rango de un ��� es:

[−232

2,232

2− 1

]= [−2147483648, 2147483647]

��� �������

������ � ���

Cuando necesitemos un entero mayor, podemos usar ������ . Ocupa 64bits (16 bytes) y el rango es:

[−9223372036854775808, 9223372036854775807]

Page 30: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → Los tipos de datos enteros 46

Literales enteros

Un literal (literal) es la especificación (dentro del código fuente) de un va-lor concreto de un tipo de dato. Los literales enteros (integer literals) seconstruyen con tokens formados por símbolos numéricos. Pueden em-pezar con un signo �

�� ������� �

Nota. En el código se usa el sistema decimal (��) pero internamente, elordenador usa el código binario (000000000110101)

¿Qué tipo de dato se usa para representar un literal entero? Depende dela memoria reservada y de los tipos disponibles en cada compilador. Elcompilador usará el tipo de dato que se ajuste al tamaño del literal entero.Así, si un compilador usa 32 bits para un �, ��������� será un literal detipo �.

� ��� ��

��� � � ���������� �� � � �

����� � ����� ��

� ����� � � ���������������� �� ����� � �����

Los literales demasiado grandes provocarán un error:

� ��� ��

��� � � ��������������������� �� � � ��������

Introducción a la ProgramaciónTipos de datos comunes en C++ → Los tipos de datos enteros 47

I.5.2.3. Operadores

Operadores binarios

� � � � �

suma, resta, producto, división entera y módulo.El operador módulo (�) representa el resto de la división enteraDevuelven un entero.Binarios. Notación infija: ���

� �

� � �� �� ����� � �� �������� �� ����� �

� � �� �� ����� � �� �������� �� ����� ��

� � � �� �� ����� � �� �������� �� ����� �

� � � �� �� ����� � �� �������� �� ����� �

� � �� �� ����� � �� �������� �� ����� �

� � � � �� ����� � �� �������� �� ����� �

� ��� � ��� �� ����� � �� �������� �� ����� ��

� � �� �� ����� � �� �������� �� �����

� � � � �� ����� � �� �������� �� ����� �

� ��� � ��� �� ����� � �� �������� �� ����� �

� � � � �� ������ ��������

Operaciones usuales:

� Extraer el dígito menos significativo: ��! � �� → !

� Truncar desde el dígito menos significativo: ��! � �� → ��

Page 31: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → Los tipos de datos enteros 48

Operadores unarios de incremento y decremento

�� y �� Unarios de notación postfija.

Incrementan y decrementan, respectivamente, el valor de la variable en-tera sobre la que se aplican (no pueden aplicarse sobre una expresión).

����������� � �������� � ������ � �

�� ������� ��

�������� � �������� � �� �

����������� � ������� � ������ � �

�� ������� ��

�������� � �������� � �� �

��� ���� � ��

���� � ������� ��� �� ! � ����

������� ��� �� " � ����

Operador unario de cambio de signo

� Unario de notación prefija.

Cambia el signo de la variable sobre la que se aplica.

��� ���� � �# ����$���������

����$�������� � ������ ��� �� �� � ����$��������

����$�������� � �����$��������� ��� �� � � ����$��������

Introducción a la ProgramaciónTipos de datos comunes en C++ → Los tipos de datos enteros 49

I.5.2.4. Expresiones enteras

Son aquellas expresiones, que al evaluarlas, devuelven un valor entero.

������ �� ����������� �

¿Cómo evalúa el compilador la siguiente expresión?

� � � � ��

Posibilidad 1:

1. Primero hacer 3+5

2. Después, el resultado se multiplica por 7

El resultado sería: 56

Posibilidad 2:

1. Primero hacer 5*7

2. Después, el resultado se suma a 3

El resultado sería: 38

La forma que adopta el compilador depende de la precedencia de losoperadores. Ante la duda, forzad la evaluación deseada mediante la utili-zación de paréntesis:

���� � �������� ���� � ��������

Page 32: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → Los tipos de datos enteros 50

Reglas de precedencia:

��

� �������� ����� � ����� � ������

� � �

� �

Cualquier operador de una fila superior tiene más prioridad que cualquie-ra de la fila inferior.

�������� � ������ �� ������� � �������

Los operadores de una misma fila tienen la misma prioridad. Se evalúande izquierda a derecha según aparecen en una expresión.

�������� � ������ �� ������� � �������

Ejercicio. Teniendo en cuenta el orden de precedencia de los operadores,indicad el orden en el que se evaluarían las siguientes expresiones:

a) � � � � � b) � � � � c) � � � � �

Ejemplo. Incrementar el salario en 100 euros y calcular el número de bi-lletes de 500 euros a usar en el pago.

��� �������� �� �����!!�

������� � "�!!!�

�� �����!! � �������� � #!!� � �!!� �� �$

�� �����!! � ������� � #!! � �!!� �� %���� �&�� �

Introducción a la ProgramaciónTipos de datos comunes en C++ → Los tipos de datos reales 51

I.5.3. Los tipos de datos reales

Reales: subconjunto finito de R

� Parte entera de 4,56 −→ 4

� Parte real de 4,56 −→ 56

C++ ofrece distintos tipos para representar valores reales. Principalmen-te, ����� (usualmente 32 bits) y ����� (usualmente 64 bits).

����� ��������

�������� � �������

I.5.3.1. Literales reales

Son tokens formados por dígitos numéricos y con un único punto quesepara la parte decimal de la real. Pueden llevar el signo � al principio.

������� ��� �������

Importante:

� El literal � es un entero.

� El literal ��� es un real.

Los compiladores suelen usar el tipo ����� para representar literalesreales.

También se puede utilizar notación científica:

������ representa el número 5,32 ∗ 105 = 532000

������ representa el número 42,9 ∗ 10−2 = 0,429

Page 33: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → Los tipos de datos reales 52

I.5.3.2. Representación de los reales

¿Cómo podría el ordenador representar 541,341?

Lo fácil sería:

� Representar la parte entera 541 en binario

� Representar la parte real 341 en binario

De esa forma, con 64 bits (32 bits para cada parte) podríamos representar:

� Partes enteras en el rango [−2147483648, 2147483647]

� Partes reales en el rango [−2147483648, 2147483647]

Sin embargo, la forma usual de representación no es así. Se utiliza la re-presentación en coma flotante (floating point). La idea es representar unvalor y la escala. En aritmética decimal, la escala se mide con potenciasde 10:

42,001 → valor = 4,2001 escala = 10

42001 → valor = 4,2001 escala = 104

0,42001 → valor = 4,2001 escala = 10−1

El valor se denomina mantisa (mantissa) y el coeficiente de la escala ex-ponente (exponent).

En la representación en coma flotante, la escala es 2. A grosso modo seutilizan m bits para la mantisa y n bits para el exponente. La forma explí-cita de representación en binario se verá en otras asignaturas. Podemosadelantar que la representación de la parte real se hace en potencias in-versas de 2. Por ejemplo, 1011 representaría

1 ∗ 1

21+ 0 ∗ 1

22+ 1 ∗ 1

23+ 1 ∗ 1

24=

Introducción a la ProgramaciónTipos de datos comunes en C++ → Los tipos de datos reales 53

= 1 ∗ 1

2+ 0 ∗ 1

4+ 1 ∗ 1

8+ 1 ∗ 1

16= 0,6875

Problema: Usando este método NO es posible representar de forma exac-ta muchos reales. Valores tan sencillos como 0,1 o 0,01 no se puedenrepresentar de forma exacta.

0,1 � 1 ∗ 1

24+ 0 ∗ 1

25+ 0 ∗ 1

26+ 0 ∗ 1

27+ 0 ∗ 1

28+ · · ·

Por tanto:

¡Todas las operaciones realizadas con los reales puedendevolver valores que sólo sean aproximados!

Especial cuidado tendremos con operaciones del tipo

������ ����� ���

�� � ������ � ��� ������������� ����� ������ ������

ya que los errores de aproximación se irán acumulando.

Page 34: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → Los tipos de datos reales 54

I.5.3.3. Rango y Precisión

La codificación en coma flotante separa el valor de la escala. Esto permitetrabajar (en un mismo tipo de dato) con magnitudes muy grandes y muypequeñas.

������ ��������

������� � ����������������������� �� ��

������� � ���������������������� � �� ���

������ ����������� ��������������

���������� � �������� �� ��

������������� � �� � ! � �� ��

Pero el precio a pagar es muy elevado: muy poca precisión (tanto en laparte entera como la real)

������ ��������

������� � �!��"#��� �!����� �� $ %

������� � �!��"#��� �!��"#��� �� $ &

�� '� ��������( �� ���� �)�*������

�� +� �,��)��$ �!��"#��� �!��"����

La regla a usar es que con 32 bits, se consigue una precisión aproximadade 7 dígitos y con 64 bits, se consiguen aproximadamente 16 dígitos.

Introducción a la ProgramaciónTipos de datos comunes en C++ → Los tipos de datos reales 55

���������� � �� �������� �����

�� �� ���������� �� ����� ���������� �� �!�����"

�� �� �������� �����

���������� � ��

�� #� �� ����$ ��%�$

�� &��'�(� $� ���������� �� ����� ����������

�� �� �!�����" �����������

Cuanto mayor sea la parte entera a representar, menor será la precisiónen decimales que obtendremos (sin contar que, además, muchos deci-males como 0.1 no se pueden representar de forma exacta)

Por ejemplo, usando 32 bits, hay aproximadamente 8388607 números en-tre 1,0 y 2,0, mientras que sólo hay 8191 entre 1023,0 y 1024,0

Debido a la poca precisión, los programas financieros no trabajan conreales en coma flotante. Soluciones:

� Trabajar con enteros y potencias de 10.

��% $�������

$������ � ���� � �� ��� ����$ ) � �(�%���$

$������ � �� ��� �� �� � ����$ ) � �(�%���$

$������ � � � �� � ����$

� Usar tipos o clases específicas (BCD por ejemplo)

Page 35: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → Los tipos de datos reales 56

En resumen:

� Los tipos enteros representan datos enteros de for-ma exacta.

� Los tipos reales representan la parte entera de for-ma exacta, siempre que trabajemos con menos de16 dígitos (en una representación con 64 bits)La parte real será sólo aproximada. Además, la apro-ximación será mejor cuanto menor sea la parte en-tera del número.

Los reales en coma flotante también permiten representar valores espe-ciales como infinito (infinity) y una indeterminación (undefined) ��� (Nota Number)

������ �������� � �� � ����

������� � ���� ��� �� �������� ���

������� � ���������� �� �������� ���

������� � � ���� ��� �� �������� ���

������� � ���������� �� �������� ���

Introducción a la ProgramaciónTipos de datos comunes en C++ → Los tipos de datos reales 57

I.5.3.4. Operadores

�� �� �� �

Binarios, de notación infija. También se puede usar el operador unario decambio de signo (�). Aplicados sobre reales, devuelven un real.

���� �� �

�� � ��� � ���� �� ����� �� � � �� ����

�� � ��� � ���� �� ����� �� � � �� ���������

¡Cuidado! El comportamiento del operador � depende del tipo de los ope-randos: si todos son enteros, es la división entera. Si todos son reales,es la división real.

���� �� �

�� � ��� � ���� �� ����� �� � � �� ���������

�� � � � �� �� ����� �� � � �� �

�� � � � ���� �� �� � ��!�� ���"�#�

Page 36: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → Los tipos de datos reales 58

I.5.3.5. Funciones estándar

Hay algunas bibliotecas estándar que proporcionan funciones que traba-jan sobre datos numéricos (enteros o reales) y que suelen devolver unreal. Por ejemplo, �����

���� ���� � �� ����� ���� ���� ������ ����� ����

Todos los anteriores son unarios excepto ���, que es binario. Devuelvenun real.

� ������ � ��������

� ������ �������

�� �� ��������� ����

�� �� ��

������ ���� ��� ���������

���� �� !�"�

�������� �������� ���

�������� ���"�#� ���� ���

$

Introducción a la ProgramaciónTipos de datos comunes en C++ → Los tipos de datos reales 59

I.5.3.6. Expresiones reales

Son expresiones cuyo resultado es un número real.

����������� es una expresión real

�� ����� ������ es una expresión real

�������� � ������� es una expresión real

En general, diremos que las expresiones aritméticas (arithmetic expres-sion) o numéricas son las expresiones o bien enteras o bien reales.

Precedencia de operadores:

� ��������� ����� �� ����� �� ����

� �

� �

Consejo: Para facilitar la lectura de las fórmulas matemáti-cas, evitad el uso de paréntesis cuando esté clarocuál es la precedencia de cada operador.

−b +√b2 − 4ac

2a

������������������������� �� !""# $!

�������������� � ��������������� !""# $!

��� � �������� � �������������� "# !%#�&'&!

Page 37: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → Operando con tipos numéricos distintos 60

I.5.4. Operando con tipos numéricos distintos

I.5.4.1. Usando enteros y reales en una misma expresión

Muchos operadores numéricos permiten como argumentos, expresionesde tipos distintos.

��� � ��� ������ ����

��� � ��� ������ ��� �����

� � � ������ �

��� � � ������ ��� �����

Para evaluar el resultado de una expresión que contengadatos con tipos distintos, el compilador usará el tipo ade-cuado que sea capaz de albergar el resultado.

Por ejemplo, usará un ���� para almacenar el resultado de ��� � �, esdecir, ��� �����.

El operador de asignación también permite trabajar con tipos distintos.

���� ����

��� ������ � ��

��� � �� �� ���� � ���

��� � ������� �� ���� � ���

Internamente se produce una transformación de tipo (casting) del valor� (en su representación como un ���) al valor ��� (en su representacióncomo un ����)

Introducción a la ProgramaciónTipos de datos comunes en C++ → Operando con tipos numéricos distintos 61

������ ����

���� �� � � �� ������ ������

�� ������ � ���� �� ����� ��������

���� � � � �� ������ ���

�� ������ � ���� �� ����� �

Muy importante: Primero se evalúa la expresión en la parte derecha de laasignación y luego se realiza la asignación.

��� ����� � � ����� �

������ �����

����� ������ � �������� �� !�

asigna a ����� el valor �� .

Es un error lógico, difícil a veces de detectar.

Posible solución: ¿Declarar ����� y ����� como ������? El resultado sería���, pero no debemos cambiar el tipo asociado a la edad, pues su semán-tica es de un entero. Forzaremos la división real usando un literal real enun operando.

��� ����� � � ����� �

������ �����

����� ������ � ��������� �� !�

Page 38: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → Operando con tipos numéricos distintos 62

¿Qué pasa cuando asignamos un real a un entero? Simplemente, se pier-de la parte decimal, es decir, se trunca.

������ ����

�� ������

���� ���

������ ���� �� ����� � ������ �� ����� �

Este truncamiento también ocurre si ejecutamos

�� �� ������

e introducimos un valor real.

Casos especiales:

El casting a entero de un ������ que contenga infinito o indeterminaciónes un valor basura.

�� ������� ����������

������ ����

���������� �

���� ������������������� �� �������� � !

������ ���� �� �������� ������

���� ������������������ �� �������� �

������ ���� �� �������� ������

������ ������������� �� "���� �#����$� %&�� '�()

Introducción a la ProgramaciónTipos de datos comunes en C++ → Operando con tipos numéricos distintos 63

I.5.4.2. Problemas de desbordamiento

Recordemos que con un literal demasiado grande, el compilador da unerror al intentar asignarlo a una variable. Pero al operar con varios da-tos enteros, el compilador no puede realizar ninguna comprobación. Portanto, es fácil salirse del rango representable. En este caso, se produceun desbordamiento aritmético (arithmetic overflow) y el resultado es unvalor cualquiera impredecible (basura). Se produce un error lógico.

��� ������� ���������

������ � � �� ����� ���������� ���

������ � � �� ��������� ��� �����

��������� � �

������ � ������ � ��������� �� ������ ������ ��!

El compilador es capaz de evaluar la expresión

� ��

El resultado � lo almacena temporalmente en un ""����#. Elproblema viene al hacer la asignación de una expresión de tipo ""����# auna variable de tipo ���.

Esto mismo ocurre también con los reales.

En general, debemos tener cuidado con las asignaciones a datos de untipo más pequeño que la expresión de la asignación. Algunos compila-dores pueden advertir de este hecho, durante el proceso de compilación,con un aviso (warning) (pero no es un error de compilación).

Page 39: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato carácter 64

I.5.4.3. Un ��� no es siempre un entero de 32 bits con signo

Una de las principales críticas al estándar C++ es que cada compiladortiene cierto margen de maniobra y puede implementar cada tipo de datode forma distinta. Una restricción fundamental es:

� ���� �� �� � ���� � ��� � ����

Por tanto, podría ser que un ��� fuese un entero de 32 bits con signo enun compilador y en otro fuese un entero de 16 bits con signo.

Obviamente, esto puede ocasionar problemas de desbordamiento comohemos visto en la sección anterior.

Los ficheros de cabecera ������� y ������� contienen definicionesde los rangos de valor de todos los tipos fundamentales.

Ampliación:Consultad las restricciones básicas en:��������������������������������

y una referencia más avanzada en:��������������������������������

I.5.5. El tipo de dato carácter

I.5.5.1. Rango

Es un conjunto finito y ordenado de caracteres: letras minúsculas, ma-yúsculas, dígitos del 0 al 9 y otros caracteres especiales.

Hay varios tipos de dato de carácter: �� ��� �����! ��, etc. EnFP usaremos ��.

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato carácter 65

Código ASCII (256 caracteres) Cada carácter tiene un código numeradode 0 a 255.

Page 40: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato carácter 66

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato carácter 67

Literales de carácter

Son tokens formados por:

� Un único carácter encerrado entre comillas simples:��� ��� ��� ��� ���

Observad que ��� es un literal de carácter y � es un literal entero

¡Cuidado!: ����� o ���� no son literales de carácter.

� O bien una secuencia de escape, es decir, el símbolo � seguido deotro símbolo, como por ejemplo:

Secuencia Significado

� Nueva línea (retorno e inicio)

� Tabulador

�� Retrocede 1 carácter

�� Retorno de carro

�� Salto de página

�� Comilla simple

�� Comilla doble

�� Barra inclinada

Las secuencias de escape también deben ir entre comillas simples,por ejemplo, ���, �� �, etc.

Page 41: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato carácter 68

�������� ��� ����

����� ��������� ����

��� �������

���� ��� ����������� !"�!�

��� ��� ������

��� ����� !#!� $$ �������� !#!

��� ��� ����� %���&�����%�

��� !"�! %�����' � ��� �(� �� �� ��������� �)���%�

��� !"�! !"�! %���( �� ��(��� ���� �)���%�

��� ������������

��� !"�! %��� �� ��� ������ ������* % !"!!�

+

Escribiría en pantalla:

#���&�����

�����' � ��� �(� �� �� ��������� �)���

���( �� ��(��� ���� �)���

��� �� ��� ������ ������* !

Nota. Para escribir un retorno de carro, también puede usarse una cons-tante llamada ���� en la forma:��� ���� %���,�% ����

Observad la diferencia:

��(�� �

��� ��� ��

��� � ! !� $$ ���� �� �� �� -��� ! !

./� $$ &� ��(�� ���

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato carácter 69

I.5.5.2. Funciones estándar

El fichero de cabecera ������ contiene varias funciones relativas a carac-teres. Por ejemplo:

������ �����

�� ���� ��������

�� � �������� ����

� � ��� ���

��� ����������

��������� � ������������ �� ������ � ���

��������� � ����������� �� ������ � ���

��������� � ������������ �� ������ � � �

��������� � ��������!��� �� ������ � �!�

""""""""""""""""""

Page 42: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato carácter 70

I.5.5.3. El tipo ���� como un tipo entero

En C++, el tipo ���� es realmente un tipo entero pequeño. Cuando hace-mos

���� ��������

�������� � ���

estamos asignando a la variable �������� el número de orden en la tablaASCII del carácter ���, es decir, el ��.

���� ��������

�������� � ��� �� �������� ������� ��

De hecho, también podríamos poner:

���� ��������

�������� � �� �� �������� ������� ��

Lo anterior es posible con cualquier tipo entero:

�� ��������

�������� � ��� �� �������� ��

�������� � �� �� �������� ��

�������� � ��� �� �������� ��

�������� � � �� �������� �

Así pues, el tipo ���� es un entero pequeño ya que está pensado paraalbergar los números de órdenes de la tabla ASCII.

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato carácter 71

Veamos algunas consecuencias:

� Podemos operar con los caracteres como si fuesen números:

���� �������� �� ������ ������� �� ��������

�������� � ����� �� �������� �� � ���

�������� � ���� �� �������� �� � ���

�������� � ��� � �� �������� �! � ���

�������� � ��� � ��� �� �������� �"#

� También podemos usar el operador con dos argumentos de ca-rácter. Devuelve un entero:

�� �����

����� � ��� ��� �� �������� "

El recurso ��$� se ha programado de la siguiente forma:

� Si se pasa a ��$� un literal o variable de tipo ����, imprime el carác-ter correspondiente al entero almacenado.

� Si se pasa a ��$� un literal o variable de tipo entero (distinto a ����),imprime el entero almacenado.

¿Qué imprimiría la sentencia ��$� %% �����? No imprime ��� como cabríaesperar sino 66 ya que � es un literal entero y por tanto de tipo ��. El tipo�� es más grande que el tipo ����, por lo que ����� es una expresión detipo ��.

Page 43: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato carácter 72

Estudiar:C++ ofrece un amplio repertorio de tipos de datos para represen-tar, por ejemplo, enteros sólo positivos, reales muy grandes, etc.Consultad���������������� ��������������

���������������������� �������������������

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato cadena de caracteres 73

I.5.6. El tipo de dato cadena de caracteres

Los literales de cadenas de caracteres son una sucesión de caracteresencerrados entre comillas dobles:������, ��� son literales de cadena de caracteres

���� ���� �� � ������� �� ���� � �� ������������

Las secuencias de escape también pueden aparecer en los literales decadena de caracteres presentes en ����

� � ��� ���

���� ���� �� ������

���� �� ������ � �������� � �� ������ �� �� ����

���� �� ������� �� ������� ���� �� ����

���� �� ��

���� �� ��� �� � � ������� ������ ���

���� � ���� �� � � ������� ����� ����

!

Escribiría en pantalla:

��� �� ����

������ � �������� � �� ������ �� �� ��

����� �� ������� ���� �� ��

��� �� � � ������� ������ � ���� �� � � ������� ����� �

Page 44: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato cadena de caracteres 74

Ejercicio. Determinar cuales de las siguientes son constantes de cade-na de caracteres válidas, y determinar la salida que tendría si se pasasecomo argumento a ����

a) ���� ���� b) � ��� ���� c) ���� ����

d) ������������� e) ���������� �� f) ����������� ��

g) ������������ ��

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato cadena de caracteres 75

C++ ofrece dos alternativas para trabajar con cadenas de caracteres:

� A la vieja usanza, usando vectores de caracteres con terminador����.Se verá en otras asignaturas.

� Usando el tipo ����� (la recomendada en esta asignatura)

��� ���� �

����� ������������������

����������������� � ��������� ���������������

���� �� ������������������

��������

Para poder operar con un string debemos incluir la biblioteca �����:

���!��� ��������"

���!��� ������"

���� �������� ����

��� ���� �

����� ����

��� � �#�!� $ ��

��� � ��� % ����&���

���� �� ����

Realmente, ����� es una clase (lo veremos en temas posteriores) por loque le serán aplicables métodos en la forma:

��� � �#�!� $ ��

���������������&�� � '' ()*

Page 45: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato lógico o booleano 76

I.5.7. El tipo de dato lógico o booleano

Es un tipo de dato muy común en los lenguajes de programación quese utiliza para representar los valores verdadero y falso que suelen estarasociados a una condición.En C++ se usa el tipo ����.

I.5.7.1. Rango

Un dato lógico, sólo puede tomar dos valores: verdadero y falso. Pararepresentarlos, se usan los siguientes literales:

���� ���

Una expresión lógica es una expresión cuyo resultado es un tipo de datológico.

I.5.7.2. Operadores

Son los operadores clásicos de la lógica Y, O, NO que en C++ son losoperadores ��� � � respectivamente.

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato lógico o booleano 77

p ≡ Carlos es varón

q ≡ Carlos es joven

p q p �� q p �� q � p

true true true true true false

true false false true false true

false true false true

false false false false

Por ejemplo:

Si p es �����, y q es true,

p �� q será falsep �� q será true

Recordad:

� ����� �� expresión siempre es �����.

� �� �� expresión siempre es ��.

Page 46: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato lógico o booleano 78

Muchas funciones de ������ devuelven un valor lógico

����� ����� ������� ���

Por ejemplo,

����������

es una expresión lógica (devuelve ����)

�� ��� �� �� ���� �� ���� ����� ����� ��

������� ��������

����� �� ������ ���

��� ����� !

��� ��"���# ��"����� # ��"������"�� �$���

��� �� ������

��"��� % ���������� �� &����� ���� � ��"���

��"����� % ����� ����� �� &����� �$�� � ��"�����

��"������"�� �$��� % ������������

�� &����� �$�� � ��"������"�� �$���

�� ������ % ���"��� '' ��"����� � �� (�������) ����

�� ������ % ���"��� ** ��"����� � �� (�������) �$��

�� ������ % +��"��� �� (�������) �$��

�������

,

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato lógico o booleano 79

I.5.7.3. Operadores Relacionales

Son los operadores habituales de comparación de expresiones numéri-cas.Pueden aplicarse a operandos tanto enteros, reales, como de caracteresy tienen el mismo sentido que en Matemáticas. El resultado es de tipo����.

�� (igual), �� (distinto), �, �, �� (menor o igual) y �� (mayor o igual)

Algunos ejemplos:

� La expresión � � � devuelve valor � ��

� La expresión � � � devuelve el valor �����

� La relación de orden entre caracteres se establece según la tablaASCII.La expresión ���� � ���� devuelve el valor �����.

�� es el operador relacional distinto.� es la negación lógica.�� es el operador relacional de igualdad.� es la operación de asignación.

Tanto en �� como en �� se usan 2 signos para un único operador

Page 47: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato lógico o booleano 80

�� ������� � ������� ��� �������

��� �������

��� ������ � �� ������ � ��

����� ����� �����

���� ����� ��������

���� � ������ � �������

���� � ������ � �������

���� � ������� � ������� �� ������� � !��

���� � �"#�

���� � #"��

���� � ���� $ �������

���� � ���� �� ����� $ ������

������� � ���� �� �����

%

Veremos su uso en la sentencia condicional:

�& �' � ��

��� �� (' �� ���� )�� �(�

�& � �' $ ���

��� �� (' �� ���� � ����� )�� �(�

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo de dato lógico o booleano 81

Reglas de Precedencia:

��

� �� � ��

�� ��

��

��

A es menor o igual que B y B no es mayor que C

� � � �� � � � � � � ���

���� ������

����� � � �� � �� �� � �� �� ���

����� � �� �� �� �� ���� � ���� �� ����

����� � �� �� �� �� ��� � ��� �� !��"!�#��

����� � �� �� �� �� �� �� ��� �� �$�%� "!&�'

�Consejo: Simplificad las expresiones lógicas, para así au-

mentar su legibilidad.

Ejercicio. Escribid una expresión lógica que devuelva �'$! si un númeroentero !�#� está en el intervalo [0,100]

Page 48: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo enumerado 82

I.5.8. El tipo enumerado

Supongamos un programa de contabilidad en el que queremos represen-tar tres posibles valores de desgravación, a saber 7, 16 y 30 %. Alternati-vas:

� Usar una única variable ����������

�� ����������

���������� � �

������

Propenso a errores: podemos poner por error el literal 17, que esaceptado en un ��.

� Usar tres constantes:

���� �� ������������ � �

���� �� ������������� � ��

���� �� ������������� � ��

Tedioso, pues siempre tendremos que manejar tres variables

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo enumerado 83

� Usar un tipo enumerado (enumerated type). Es un tipo entero quesólo acepta unos valores concretos especificados por el progra-mador.

������ ������

��� ������������� �������� ������� ���������

������������� �����������

���� �� ����� �� � � �

���������� � ����� �� !� ����� ����� ���� �

�� "" ������

����� � ����� # �����$������������%%&%�

���������� � '� �� (� �� ����)� *#+

�� "" ����������� �� (� �� ����)� *#+

Si a una constante sólo se le puede asignar un único valor,a un tipo enumerado sólo se le puede asignar un númeromuy limitado de valores.

Ampliación:Si no se pone ningún valor en la definición del tipo, C++ le asigna a cadavalor del enumerado el siguiente entero del asignado al valor anterior. Alprimero le asigna el cero.

��� ���,���-���� ������ ���� �����.� �/0������

���,���-���� ���

�� � �����

���� �� ��� �� %

���� �� ���� �� �

���� �� ����� �� .

���� �� �/0����� �� '

Page 49: Fundamentos de Programacion

Introducción a la ProgramaciónTipos de datos comunes en C++ → El tipo enumerado 84

Bibliografía recomendada para este tema:

� A un nivel menor del presentado en las transparencias:

– Primer capítulo de Deitel & Deitel

– Primer capítulo de Garrido.

� A un nivel similar al presentado en las transparencias:

– Capítulo 1 y apartados 2.1, 2.2 y 2.3 de Savitch

� A un nivel con más detalles:

– Los tres primeros capítulos de Stephen Prata.

– Los dos primeros capítulos de Lafore.

Tema II

Estructuras de Control

Objetivos:

� Introducir las estructuras condicionales que nos permitirán realizarsaltos hacia adelante durante la ejecución del código.

� Introducir las estructuras repetitivas que nos permitirán realizarsaltos hacia atrás durante la ejecución del código.

� Introducir pautas de programación en la construcción de las es-tructuras condicionales y repetitivas.

Autor: Juan Carlos Cubero.

Sugerencias: por favor, enviar un e-mail a ������������ ��������

Page 50: Fundamentos de Programacion

Estructuras de ControlIntroducción → 86

II.1. Introducción

Estructuras

⎧⎪⎪⎪⎨⎪⎪⎪⎩

Secuencial

Condicional

Repetitiva

Estructura Secuencial (Sequential control flow structure): las instruccio-nes se van ejecutando sucesivamente, siguiendo el orden de apariciónde éstas. No hay saltos.

Estructuras de ControlIntroducción → 87

Ejemplo. Calcular las raíces de una ecuación de 2o grado.

p(x) = ax2 + bx + c = 0

Algoritmo:

� Entradas: Los parámetros de la ecuación a, b, c.Salidas: Las raíces de la parábola r1, r2

� Descripción:Calcular r1, r2 en la forma siguiente:

r1 =−b +

√b2 − 4ac

2ar2 =

−b − √b2 − 4ac

2a

p(x) = ax2 + bx + c

-20

-15

-10

-5

0

5

-4 -2 0 2 4

p(x)

Page 51: Fundamentos de Programacion

Estructuras de ControlIntroducción → 88

�������� ��� ����

�������� ������

����� ��������� ����

��� �������

����� �� �� �� �� �� ���� � �� �� ��������

����� ����� ��� � �� !�"��� ��������

��� #$�%�� ���� ��&������� �� � ��' #�

��� �� ��

��� #$�%�� ���� ��&������� �� �� � ��' #�

��� �� ��

��� #$�%�� ���� ��&������� �������������' #�

��� �� ��

���� ( � )� * �+ �� �,�)-,�,� � � � � ,���

��� ( � )� ) �+ �� �,�)-,�,� � � � � ,���

��� #$�.�� �"��� ��# ���� # / # ��� �

0

Principio de Programación:

Una única vez (Once and only once)

Cada descripción de comportamiento debe aparecer unaúnica vez en nuestro programa.

Dicho de otra forma:

JAMÁS ha de repetirse código

La repetición de código hace que los programas sean difíciles de actuali-zar ya que cualquier cambio ha de realizarse en todos los sitios en el queestá repetido el código.

Estructuras de ControlIntroducción → 89

�������� ��� ����

�������� ������

����� ��������� ����

��� �������

����� �� �� �� �� �� ���� � �� �� ��������

����� ����� ��� � �� !�"��� ��������

����� ������� �������� �

� ��� #$�%�� ���� ��&������� �� � ��' #�

��� �� ��

( ��� #$�%�� ���� ��&������� �� �� � ��' #�

) ��� �� ��

* ��� #$�%�� ���� ��&������� �������������' #�

+ ��� �� ��

, ������ - �. �� �/�0)/�/� ��

1 �������� - /��

2 ���� - �0� 3 ������� � �������� �

�4 ��� - �0� 0 ������� � �������� �

�� ��� #$�5�� �"��� ��# ���� # 6 # ��� �

7

Flujo de control: (1,2,3,4,5,6,7,8,9,10,11).

Page 52: Fundamentos de Programacion

Estructuras de ControlIntroducción → 90

¿Es � distinto de cero?

– Si. Entonces sigue la ejecución.

– No. Entonces salta las sentencias 7–11 y termina.

������� ��� ����

������� ��� ��

����� ������� � ��

�� �������

����� �� �� �� �� ����� ��� � �� �������

����� ������ ���� � �� !�"�� �� �����

����� �������� �����������

��� #$�%� ����� ��&���� � � �����' #�

��� �� ��

��� #$�%� ����� ��&���� � �� �����' #�

��� �� ��

��� #$�%� ����� ��&���� �������� ' #�

��� �� ��

�& ��()*� �

���������� ) +��

������� ) �,� � �+�-.+�+� ��

����� ) �-� / �������� � �����������

���� ) �-� - �������� � �����������

��� #$�0�� ��"�� ���# ����� # 1 # ���� �

2

2

Estructuras de ControlEstructura condicional → 91

II.2. Estructura condicional

II.2.1. Introducción

Una condición (condition) es una expresión lógica.

Una ejecución condicional (conditional execution) consiste en la ejecu-ción de una (o más) sentencia(s) dependiendo de la evaluación de unacondición.

Una estructura condicional (conditional structure) es una estructura quepermite una ejecución condicional. También se les denomina sentenciacondicional (conditional statement) ya que todo el bloque de la estructuraforma una sentencia.

Existen tres tipos: Simple, Doble y Múltiple.

II.2.2. Estructura condicional simple

�� (<condición>)

<bloque if>

<condición> es una expresión lógica

<bloque if> es el bloque que se ejecutará si la expresión lógica se evalúaa ����.

Nota. Los paréntesis sobre la condición son obligatorios.

Page 53: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Estructura condicional simple 92

Una notación para describir algoritmos: Diagramas de flujo (flowchart)

Símbolos básicos

INICIO

FIN

Simbolo terminal

Operacion de E/S

Direccion del flujo

Estructura secuencial

Delimitadores

Bifurcador de flujo

<CONDICION>true

false

Estructuras de ControlEstructura condicional → Estructura condicional simple 93

Ejemplo. Raíces de una ecuación de segundo grado

Page 54: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Estructura condicional simple 94

Ejemplo. Leer la edad de una persona e imprimir ��� ����� �� enel caso de que su edad sea mayor o igual que 18.

�� ��

��� �� ��

�� �� �� ���

��� �� ����� ����� ���

Ejemplo. Comprobad si es menor de edad o es mayor de 65, pero encualquier caso con unos ingresos menores a 40000

�� �� ��������

� � ���

������� � ������

�� ����� �� ��� ! "" ��������#����� $$ %&�

��� �� ���'�� ��(��� �)���* �� ���� ���

Precedencia de operadores:

�� � ����� �� ��� !� "" ��������#����� $$ %&�

��� �� ���'�� ��(��� �)���* �� ���� ���

Estructuras de ControlEstructura condicional → Estructura condicional simple 95

Si hay varias sentencias, es necesario encerrarlas entre llaves. Dicho deotra forma: si no ponemos llaves, el compilador entiende que la únicasentencia del bloque �� es la que hay justo debajo.

�� ������

�� ����� � ����

������ � ����� ��������� ��

����� � ��� � ������� � �� ������

����� � ��� � ������� � �� ������

���� �� !�"�� ��#�� ��� �� ����� �� $ �� ������

Para el compilador es como si fuese:

�� ������%

�� ����� � ����

&

������ � ����� ��������� ��

����� � ��� � ������� � �� ������

����� � ��� � ������� � �� ������

���� �� !�"�� ��#�� ��� �� ����� �� $ �� ������

Page 55: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Estructura condicional simple 96

¿Qué pasa si a = 0 en la ecuación de segundo grado?

El algoritmo debe devolver −c/b. Podemos hacer lo siguiente:

�� ������

�� ���� � � ����

������ � ����� ��������� ��

����� � ��� � ������� � �� ���� ��

����� � ��� � ������� � �� ���� ��

� �� !"�#�� ��$��� � �! ����� ! % ! ������

&

�� ������

� �� !"�'���� ��� (���� ��$�! �����

Problema: Se evalúan dos condiciones equivalentes.Solución: Usar un condicional doble.

Estructuras de ControlEstructura condicional → Condicional doble 97

II.2.3. Condicional doble

�� <condición>

<bloque if>;

����

<bloque else>;

Page 56: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Condicional doble 98

Estructuras de ControlEstructura condicional → Condicional doble 99

�������� ��� ����

�������� ������

����� ��������� ����

��� �������

����� �� �� �� �� �� ���� � �� �� ��������

����� ����� ��� � �� !�"��� ��������

����� ������� �������� �

��� #$�%�� ���� ��&������� �� � ��' #�

��� �� ��

��� #$�%�� ���� ��&������� �� �� � ��' #�

��� �� ��

��� #$�%�� ���� ��&������� �������������' #�

��� �� ��

�& ��()*� �

�������� ) +��

������ ) �, �� �+�-.+�+� ��

���� ) �-� / ������� � �������� �

��� ) �-� - ������� � �������� �

��� #$�0�� �"��� ��# ���� # 1 # ��� �

2

���� �

���� ) -����

��� #$�0� 3���� �"� �� # �����

2

2

Page 57: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Condicional doble 100

Ejemplo. Calculad el mayor de dos valores � y �.

��� �� ��

��� �� ��

�� � � ��

�� ��

����

�� ��

���� �� ����� ����� �� � �� �� �

cin >> a; cin >> b; if (a>=b)

max = a; else max = b;

if (a>=b) max = a; else max = b;

Tabulador(recomendación: 3 espacios)

Compila correctamente :-( PERO Suspenso automático :-O

Línea en blanco

Estructuras de ControlEstructura condicional → Condicional doble 101

Ejemplo. El mayor de tres números �, � y � (primera aproximación).

Algoritmo:

� Entradas: �, � y �

Salidas: El mayor entre �, � y �

� Descripción:

�� � �� ��� � � �� ���� �� ��� �� �

�� � �� ��� � � �� ���� �� ��� �� �

�� � �� ��� � � �� ���� �� ��� �� �

� Implementación:

�� ������� �� �������

��� � ��

�� ������� �� �������

��� � ��

�� ������� �� �������

��� � ��

Page 58: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Condicional doble 102

(a>=b)

(a>=c)y

(b>=a)

(b>=c)y

(c>=a)

(c>=b)y

max = a

max = b

max = c

cout << max

false

false

true

true

false

true

Estructuras de ControlEstructura condicional → Anidamiento de estructuras condicionales 103

II.2.4. Anidamiento de estructuras condicionales

Dentro de un bloque if (else), puede incluirse otra estructura condicional,anidándose tanto como permita el compilador.

¿Cuándo se ejecuta cada instrucción?

�� �������� �

��� ��

�� ��������� �

��� ���

���� �

��� ���

��� ���

���� �

��� ���

������� ��������

��� � true independiente

��� �� true true

��� �� true false

��� �� true independiente

��� �� false independiente

Page 59: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Anidamiento de estructuras condicionales 104

Ejemplo. El mayor de tres números (segunda aproximación)

Algoritmo:

� Entradas y Salidas: idem

� Descripción:

�� � �� ���� �� � ��������

������� �� ������ ���� � � �

�� ��� ����

������� �� ������ ���� � � �

� Implementación:

�� ������

�� ������

��� � ��

����

��� � ��

����

�� ������

��� � ��

����

��� � ��

Estructuras de ControlEstructura condicional → Anidamiento de estructuras condicionales 105

a>=b

a>=c b>=c

max = a max = c max = b max = c

false

true false

truetrue false

cout << max

Page 60: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Anidamiento de estructuras condicionales 106

Ejemplo. El mayor de tres números (tercera aproximación)

Algoritmo:

� Entradas y Salidas: idem

� Descripción e Implementación:

��

�������� � �� � ���� ��� � � ��

�������� � �� � ��� �� � ��

��

� ������

�� � ��

��

�� � ��

� ������

�� � ��

Estructuras de ControlEstructura condicional → Anidamiento de estructuras condicionales 107

a>=b

c>max

max = b max = a

max = c

true

false

true

false

cout << max

Page 61: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Anidamiento de estructuras condicionales 108

¿Con qué algoritmo nos quedamos?Supongamos que todos los valores son distintos

� La solución 1 siempre evalúa 3 condiciones y realiza 1 asignación.

� La solución 2 siempre evalúa 2 condiciones y realiza 1 asignación.

� La solución 3 siempre evalúa 2 condiciones y realiza 1 ó 2 asigna-ciones.

La solución 2 realiza alguna evaluación menos, pero la solución 3 es mu-chísimo mejor:

� Es mucho más fácil de entender

� No repite código

� Es mucho más fácil de extender a varios valores.

Estructuras de ControlEstructura condicional → Anidamiento de estructuras condicionales 109

El mayor de cuatro números con la segunda aproximación:

�� ������

�� �����

�� �����

��� � �

����

��� �

����

�� ����

��� �

����

��� �

����

�� �����

�� �����

��� � �

����

��� �

����

�� ����

��� �

����

��� �

Page 62: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Anidamiento de estructuras condicionales 110

El mayor de cuatro números con la tercera aproximación:

Algoritmo:

� Entradas y Salidas: idem

� Descripción e Implementación:

��

�������� � �� � ���� ��� � � ��

�������� � �� � ��� �� � ��

�������� � �� � ��� �� � ��

��

� ������

�� � ��

��

�� � ��

� ������

�� � ��

� ������

�� � ��

En general:

�������� � �� � ���� ��� � � ��

���� ���� ��� � ��� ������ ��������

�������� � �� � ��� �� � � ��� ������

Estructuras de ControlEstructura condicional → Anidamiento de estructuras condicionales 111

¿Cómo describimos un algoritmo?

Descripción de un algoritmo: Se trata de describir la idea principal delalgoritmo, de forma concisa y esquemática, sin entrar en detalles innece-sarios.

�� ������

� � ��

� ��

� � ��

�� �����

� � ��

Una lamentable descripción del algoritmo:

Compruebo si a>=b. En ese caso, lo que hago es asignarle a la variablemax el valor a y si no le asigno el otro valor, b. Una vez hecho esto,paso a comprobar si el otro valor, es decir, c, es mayor que max (lavariable anterior), en cuyo caso le asigno a max el valor c y si no, nohago nada.

El colmo:

Compruevo si a>=b y en ese caso lo que ago es asignarle a la variablemax el valor a y sino le asigno el otro valor b una vez echo esto pasoa comprovar si el otro valor es decir c es mayor que max (la variableanterior) en cuyo caso le asigno a max el valor c y sino no ago nada

Page 63: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Anidamiento de estructuras condicionales 112

� Nunca parafrasearemos el código

�� �� � �� � � ���� ���� � ��� �� ����� �

� ���� ����� �� ���� ���� �

� � ��� ����� �� � ������� ����� ��

� �� ����� ��� ���� � ���� ����

�� ���� ���� �

��

�� ���

��� �!

����

��� !

�� ������

��� �!

� Seremos esquemáticos (pocas palabras en cada línea)

�� "������� �� �#���� � ��� � � � � � � ��� �����

����� $������ � �������� �� �#���� � ��� �� � �������

�� ��� ���������� ���� � �� ���� ����� �

��

�� "������� �� �#���� ���� � ��� � � �

"������� �� �#���� � ��� ��� � ��

��

Estructuras de ControlEstructura condicional → Anidamiento de estructuras condicionales 113

� Comentaremos un bloque completo

La descripción del algoritmo la incluiremos antes de un bloque,pero nunca entre las líneas del código. Esto nos permite separarlas dos partes y poder leerlas independientemente.

�� �������� �� �� ����� � � �

�� ������

�� � ��

����

�� �� �� ��� �

�� � ��

�� �������� �� �� ����� �� � �

�� ������

�� � ��

También es válido incluir la descripción a la derecha del código,pero es mucho más difícil de mantener (al incluir líneas de códigonuevas, se descompone todo el comentario):

�� ������

�� ������ �� �� � ������ �� � ����� ��� �� ���� � �

�� � �� �� �������� �� �� ����� � � �

���� �� �������� �� �� ����� �� � �

�� � ��

Usad descripciones de algoritmos que sean concisas,pero claras y completas, con una presentación visual

agradable y esquemática.No seguir estas normas baja puntos en el examen.

Page 64: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Anidamiento de estructuras condicionales 114

Ejemplo. Estructuras condicionales anidadas

�� �������� � ���� ����� ��� ��� ������ � ���

������ ���� ����

���� ������� � ��

�� �������

�� �� ��� �� ���

���� �������

�� �� � �!� ���� � ����� �������" ��

��� �� �� ���

�� �� � �!� ���� � ����� �������" ��

��� �� �� ���

�� �� � �#��$� �%�%���� �&�&� ��� �'�'� �������" ��

��� �� �������

�( ������� )) *%*�

�� �� � �%�� ) � �� �� ��+�� ���

�( ������� )) *&*�

�� �� � �&� � ) � �� �� ��,�� ���

�( ������� )) *'*�

�� �� � �'� ��������-� ) � �� �� ��.�� ���

�( ������� /) *&* 00 ������ /) *%* 00 ������ /) *'*�

�� �� � �1����� ������-���

2

Estructuras de ControlEstructura condicional → Anidamiento de estructuras condicionales 115

Ejemplo. Estructuras condicionales anidadas (continuación)

Lo hacemos más eficientemente:

�� ������� �� �

��� �� ������ � � �� �� ����� ���

����

�� ������� �� ��

��� �� ������ � � � �� �� ����� ���

����

�� ������� �� ��

��� �� ������ ���������� � � �� �� ����� ���

����

��� �� ��� ��!��� ���"�������

Una forma también válida de tabular:

�� ������� �� �

��� �� ������ � � �� �� ����� ���

���� �� ������� �� ��

��� �� ������ � � � �� �� ����� ���

���� �� ������� �� ��

��� �� ������ ���������� � � �� �� ����� ���

����

��� �� ��� ��!��� ���"�������

#

Page 65: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Construcción de estructuras condicionales 116

II.2.5. Construcción de estructuras condiciona-les

II.2.5.1. ¿Anidar o no anidar?

Un ejemplo en el que es mejor anidar

Ejemplo. Reescribid el siguiente ejemplo utilizando únicamente estructu-ras condicionales no anidadas:

�� �����

�� ����

�� ����

� ���

����

� ���

����

� ���

����

� ���

�� ������ �� ���� �� �����

� ���

�� ������ �� ���� �� ����

� ���

�� ������ �� �����

� ���

�� �����

� ���

Preferimos el primero ya que realiza menos comprobaciones, y sobre to-

Estructuras de ControlEstructura condicional → Construcción de estructuras condicionales 117

do porque no duplica código (el de las condiciones) y es, por tanto, me-nos propenso a errores de escritura o ante posibles cambios futuros.

Un ejemplo en el que es mejor no anidar

�� ��� �� ��� �� ����

�� ��� �� ����

��� �� ���

�� ��� ���

�� ���

���

�� ���

������ ����� �� ���� �� �� �

�� �� �

�� ���� �������� �����

�� �� � � �� ����

�� ���� � �� �� �

�� ���� � �� ����

��� ��� ����� �� ���� �� �� �

�� �� �

�� ���� �� �� � � �� ����

� ��� �� ����

Page 66: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Construcción de estructuras condicionales 118

Son equivalentes. Elegimos la primera porque:

� Al aumentar el anidamiento se va perdiendo en legibilidad y conci-sión.

� Muy importante: la segunda opción repite código (��������) y portanto es más propenso a errores de escritura o ante posibles cam-bios futuros.

Los factores a tener en cuenta (entre otros) para anidar ono estructuras condicionales son:

� Que no se repita código.

� Que se aumente la legibilidad de éste.

Estructuras de ControlEstructura condicional → Construcción de estructuras condicionales 119

II.2.5.2. Separación de entradas/salidas y cómputos

��� �����

��� �����

� ����� � ��

���� �� ����� ����� �� ������

Para favorecer la reutilización de código entre distintasplataformas (Linux, Windows, etc) los bloques que realizanentradas o salidas de datos (���� ����) serán independien-tes de los bloques que realizan cómputos.

��� �����

���� ��������������

�� ������� �� ������

��� �����

�� !�"�����

������������� � ����� ���

�� #����� �� �����������

� �������������� �� �����

���� �� ����� ����� �� ������

Esto me permite reutilizar el código ������������� � ����� ��� en otrossitios:

������������� � ����� ���

� �������������� �� �����

#�������$����%���&������'����(�)�*��#+�%���� ����� �� �������

Page 67: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Construcción de estructuras condicionales 120

Nota. Realmente, la reutilización del código no será a través de co-piar/pegar sino encapsulando el código a reutilizar en una función, méto-do de una clase, etc.

Sobre el uso de variables lógicas en los ��:

�� ������������ �����

��� �� ����� ��� �� ������

equivale a:

�� �������������

��� �� ����� ��� �� ������

Al igual que

�� ������������ ������

��� �� ����� ���� �� ������

equivale a

�� ��������������

��� �� ����� ���� �� ������

Ejercicio. Utilizad una variable lógica �������������������� y reescribidel código siguiente, separando E/S y Cómputos:

�� � �������� �� ����� !� "" ��#�����$%%%%� && '(�

��� �� ���)���������� �� �������� ������������

Estructuras de ControlEstructura condicional → Construcción de estructuras condicionales 121

II.2.5.3. Simplificación de expresiones: Álgebra de Boole

Debemos intentar simplificar las expresiones lógicas, para que sean fáci-les de entender. Usaremos las leyes del Álgebra de Boole, muy similaresa las conocidas en Matemáticas elementales como:

−(a + b) = −a − b a(b + c) = ab + ac

��� �� �� ���� � � �� �� ��

��� �� �� ���� � � �� �� ��

� �� �� �� �� ���� � � �� �� �� �� �� �� ��

� �� �� �� �� ���� � � �� �� �� �� �� �� ��

Nota. Las dos primeras (relativas a la negación) se conocen como Leyesde Morgan. Las dos siguientes son la ley distributiva (de la conjuncióncon respecto a la disyunción y viceversa).

Ampliación:Consultad:������������������������� ��������� ����

������������ ���� �!� ����" !��#$$���� ����%

Page 68: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Construcción de estructuras condicionales 122

Ejemplo. Es trabajador activo si su edad no está por debajo de 18 o porencima de 65.

���� ��������

�����

� �� �����

������� � ��������� �� ���������

� ���������

��� �� �� ����� ���� � ������

!!!!!!

Aplicando las leyes de Morgan:

��������� �� ��������

�"����� �

���������� ## ����������

�"����� �

����� �� ��� ## ����� �� ���

Es más fácil de entender el siguiente código:

������� � ����� �� ��� ## ����� �� ����

� ���������

��� �� �� ����� ���� � ������

Estructuras de ControlEstructura condicional → Construcción de estructuras condicionales 123

Ejemplo. Es posible beneficiario de ayudas si no es un trabajador activo.Además, ya sea menor de 18 años o mayor de 65, la unidad familiar ala que pertenezca no puede tener una base imponible mayor de 35000euros.

���� �����������

�������

���������� ��������������� � ������ �� ���� � ����

��

��������������� � ������ �� ���� � �����

Es mucho más fácil de entender lo siguiente (aplicando la lay distributi-va):

���������� �������������� � ������ ��

� ��� � �� �� ��� � �� ��

Además, no repetimos código (������������� � �����)

Page 69: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Construcción de estructuras condicionales 124

II.2.5.4. Cuidado con la comparación entre reales

La expresión ������ �� ���������� podría evaluarse a � ��� debido ala precisión finita para calcular ������� (��)

Es más:

������ ����������� ��� ������� ���

����������� �� � ����

������� �� � ����������� �� � ����

�� �������� �� �� �� �� ����� � �� ��� � ��� !"#

���� $$ %&�������� ��� ��'%�

����

Recordad que la representación en coma flotante no es precisa y 0.1 seráinternamente un valor próximo a 1, pero no exacto.

Soluciones:

� Fomentar condiciones de desigualdad

� Mejor: Fijar un error de precisión y aceptar igualdad cuando la di-ferencia de las cantidades sea menor que dicho error.

������ �� ��� �� �(�

����� ������ ������� � ��������

�� ���� ��"�� �( $ �������

���� $$ %)�� �*� ���%�

Estructuras de ControlEstructura condicional → Construcción de estructuras condicionales 125

Ampliación:Como no es lo mismo comparar si �������� está cerca de ��������, quecomparar si ������� está cerca de �������, el método anterior hay querefinarlo. Para más información:��������� �������� �� ����� ��������������������

���������������� �������� ���������� ��������� ���

� ��������� �������

Page 70: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Construcción de estructuras condicionales 126

II.2.5.5. Evaluación en ciclo corto y en ciclo largo

Evaluación en ciclo corto (Short-circuit evaluation): El compilador opti-miza la evaluación de expresiones lógicas evaluando sus términos deizquierda a derecha hasta que sabe el resultado de la expresión completa(lo que significa que puede dejar términos sin evaluar). La mayoría de loscompiladores realizan este tipo de evaluación por defecto.

Evaluación en ciclo largo (Eager evaluation): El compilador evalúa todoslos términos de la expresión lógica para conocer el resultado de la expre-sión completa.

Ejemplo.

�� � ����� �� ��� �� ���� �

Supongamos � � ��.

� Ciclo largo: El compilador evalúa (innecesariamente) todas las ex-presiones lógicas

� Ciclo corto: El compilador evalúa sólo la primera expresión lógica.

Por lo tanto, pondremos primero aquellas condiciones que sean más pro-bables de evaluarse como �����

Nota. Lo mismo pasa cuando el operador es ��

Estructuras de ControlEstructura condicional → Estructura condicional múltiple 127

II.2.6. Estructura condicional múltiple

Recordemos el ejemplo de lectura de dos enteros y una opción:

��� ������ ����

��� ������

���� �� ������ ����� �� � ��� ��� ����� �

��� �� �����

���� �� ������ ����� �� ������� ��� ����� �

��� �� ����

���� �� ������������� ��� ���� � ��� ���� � �

�� ���� ���������� � �

��� �� ������

� ������� !! "�"�

���� �� ������� ! � �� �����#����

���� � ������� !! "�"�

���� �� �������� ! � �� �����$����

���� � ������� !! "�"�

���� �� ���������������%� ! � �� �����&����

����

���� �� ���'������ ��� ���%��

Page 71: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Estructura condicional múltiple 128

������ (<expresión>) {

���� <constante1>:

<sentencias1>

����

���� <constante2>:

<sentencias2>

����

.........................

[ �������

<sentencias>]

}

� <expresión> es un expresión entera.

� <constante i> ó <constante2> es un literal entero.

� ������ sólo comprueba la igualdad.

� No debe haber dos ����� con la misma <constante> en el mismo������. Si esto ocurre, sólo se ejecutan las sentencias del caso queaparezca primero.

� El identificador especial ������ permite incluir un caso por defec-to, que se ejecutará si no se cumple ningún otro. Se suele colocarcomo el último de los casos.

Estructuras de ControlEstructura condicional → Estructura condicional múltiple 129

Se usa frecuentemente en la construcción de menús:

�������� ��� ����

����� ��������� ����

��� �������

��� ����������

��� �����

��� ������ ���� �� � ��� �� ���� ��

��� �� �����

��� ������ ���� �� ������ �� ���� ��

��� �� �����

��� ������������ ��� ���� � � � ���� � ��

��� �� �����

�!���� ������ �

���� "�"� ��� ������� # � ����$�����

% ��&�

���� " "� ��� ��� ���� # � ����'�����

% ��&�

���� "("� ��� ���(�����������)� # � ����*�����

% ��&�

��+�����

��� ���,������ �� ���)���

-

-

Page 72: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Estructura condicional múltiple 130

El gran problema con la estructura ������ es que el programador olvidaráen más de una ocasión, incluir la sentencia ���. La única ventaja es quese pueden realizar las mismas operaciones para un grupo determinadode constantes:

������ � ��� �� �

�� ����

�� ���� � �� �� ������ � � �� �� ���� ��

����

�� ����

�� � �� � �� �� ��� �� � � �� �� �!�� ��

����

�� ����

�� �"�� � �� �� ���"�#���#����$� � � �� �� �%�� ��

����

�&�#�� � �� �� ���'��(�� ����$���

����

)) * �� � ���� ��+� � � �����

,

Estructuras de ControlEstructura condicional → Estructura condicional múltiple 131

Pero para conseguir ese objetivo, la siguiente solución sería mucho me-jor:

������ � �������������

������ �������� �

��� ���� ���� �� ������� � � �� �����������

���

��� � �� ���� �� ��� ��� � � �� �����!�����

���

��� �"�� ���� �� ���"�#���#�����$� � � �� �����%�����

���

�&��#��

���� �� ���'��(��� �����$��

���

)) *����� ��� ���+� �� �� ������

,

Y para no tener errores lógicos si se nos olvida incluir ���, podemosvolver a lo que ya sabemos:

������ � �������������

�& ������� �� ����

���� �� ������� � � �� �����������

#� �& ������� �� � ��

���� �� ��� ��� � � �� �����!�����

#� �& ������� �� �"��

���� �� ���"�#���#�����$� � � �� �����%�����

#�

���� �� ���'��(��� �����$��

Page 73: Fundamentos de Programacion

Estructuras de ControlEstructura condicional → Estructura condicional múltiple 132

Consejo: Sólo para C++ → En la medida de lo posible, evitadel uso de la estructura ������ por los errores lógi-cos producidos al olvidarnos incluir algún ���

Estructuras de ControlEstructuras repetitivas → 133

II.3. Estructuras repetitivas

Una estructura repetitiva (iteration/loop) (también conocidas como bu-cles, ciclos o lazos) permite la ejecución de una secuencia de sentencias:

o bien, hasta que se satisface una determinada condición → Buclecontrolado por condición (Condition-controlled loops)

o bien, un número determinado de veces → Bucle controlado porcontador (Counter controlled loop)

II.3.1. Bucles controlados por condición: pre-testy post-test

II.3.1.1. Formato

Pre-test

����� (<condición>) {

<cuerpo bucle>

}

Post-test

�� {

<cuerpo bucle>

} ����� (<condición>);

Funcionamiento: En ambos, se va ejecutando el cuerpo del bucle mien-tras la condición sea verdad.

� En un bucle �����, primero se pregunta y luego (en su caso) seejecuta.

� En un bucle �� �����, primero se ejecuta y luego se pregunta.

Cada vez que se ejecuta el cuerpo del bucle diremos que se ha producidouna iteración (iteration)

Page 74: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 134

<cuerpo bucle>

(Pre−test)

<condicion>false

true

<cuerpo bucle>

<condicion>

(Post−test)

true

false

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 135

II.3.1.2. Algunos usos de los bucles

Ejemplo. Crear un filtro (filter) de entrada de datos: Leer un valor y nopermitir al usuario que lo introduzca fuera de un rango determinado.

�� �������� �� ��� � ���� ���� �������

�� ������ �� ������

������ ������ ��

������ �� ���

���� � ���� � ����

�� � ����

�� � ����

���

��� �� ���������� �� � ��� ������! ��

� �� � ����

"#��� �� ��� � $��

��� �� ���� �����

"

Nota. El filtro anterior no nos evita todos los posibles errores. Por ejem-plo, si se introduce un valor demasiado grande, se produce un desborda-miento y el resultado almacenado en � ��� es impredecible

Page 75: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 136

Elección Pre-test, o post-test: ¿Quiero que siempre se ejecute al menosuna vez el cuerpo?

Ejemplo. Escribir 20 líneas con 5 estrellas cada una.

��������� ��

��

���� �� ���� �� ������� �

��������� ��������� � �� �� ����� ������� � �

������ ���������� � � !�

O bien:

��������� �

��

���� �� ���� �� ������� �

��������� ��������� � ��

������ ���������� � � !�

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 137

O bien:

��������� ��

���� ���������� � ����

���� �� ���� �� ������� �

��������� ��������� � ��

Preferible:

��������� �� �� ��� � � �!��� ��"#��

���� ���������� � ����

���� �� ���� �� ������� �

��������� ��������� � ��

Dentro del bucle, JUSTO antes de comprobar la condición, la variable����� contiene el número de líneas que hay impresas $%�

Nota. Podríamos usar el operador de incremento:

���� ���������� � ����

���� �� ���� �� ������� �

������������

Page 76: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 138

Consejo: Fomentad el uso de los bucles pre-test. Casi siem-pre habrá algún caso en el que no queramos ejecu-tar el cuerpo del bucle ni siquiera una vez.

Ejercicio. Leer un número positivo ���� e imprimir ���� líneas con 5 es-trellas cada una.

���� �� ���� ��� ����� �� ���������� ������ ��������� ��

�� �� �����

�������� � ��

���

���� �� �� �� ������� �

�������� �

!"#��� $�������� � ����%�

Problema: ¿Qué ocurre si ���� � �?Proponer una solución:

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 139

Ejemplo. Leed un entero ���� y escribir los pares ≤ ����

��� �� ����

�� �

����� ��� �� ������

�� � �� � �

���� �� ��

Consejo: En el diseño de los bucles siempre hay que com-probar el correcto funcionamiento en los casos ex-tremos (primera y última iteración)

Al final, escribe uno más. Cambiamos el orden de las instrucciones:

��� �� ����

�� � �� ������ �������

����� ��� �� ������ �� ��� ����!

���� �� �� �� "� �� ����#����

�� � �� � � �� ������ ���$�

�� �������

� �� %� �� "���

Si no queremos que salga 0, cambiaríamos la inicialización:

�� � �

Page 77: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 140

Ejemplo. Calculad el número de dígitos que tiene un entero

����� �� � ��� �

�� �� � ��� �

Algoritmo:

� Entradas: �

� Salidas: �������� �

� Descripción e implementación:

�� ��������� � � � �� ����� ����� � ��� �����

�� ����� �� ��� � ��� �� ����� �� ������� ���

�������� � ! �"

#���� $� � %&'

� ! �(��"

�������� �))"

*

Mejor si no modificamos la variable original:

��� ��� ! �"

�������� � ! �"

#���� $��� ��� � %&'

��� ��� ! ��� ���(��"

�������� �))"

*

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 141

II.3.1.3. Lectura Anticipada

Ejemplo. Realizad un programa que sume una serie de valores leídos des-de teclado, hasta que se lea el valor -1 (terminador = -1)

����������� ����

����� ��������� ����

��� �������

��� ����� ���� �

���� � ��

��

��� �� ���� �

���� � ���� � ���� �

������ ����� �� � ��

��� !"�#� ���� �� ! �����

Problema: Procesa el � y lo suma.

Page 78: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 142

Solución:

���

��� �� �����

� ����� �� ���

��� � ��� � �����

����� ����� �� ����

Funciona, pero evalúa dos veces la misma condición, lo cual es ineficien-te y, mucho peor, duplica código.

Recordad: Evitad el uso de bucles �� ����

Solución: técnica de lectura anticipada. Leemos el primer valor con ���

antes de entrar al bucle y comprobamos si hay que procesarlo (el primervalor podría ser ya el terminador!)

��� � ��

��� �� ����� �� ���� ���������

���� ����� �� ��� � �� � � !���"

��� � ��� � �����

��� �� ����� �� #� ��$���� ���������

���� %% &'�#� ��� � & %% ����

Nota. La primera vez que entra al bucle, la instrucción���� ����� �� ��� hace las veces de un condicional.

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 143

Otra posible solución, usando variables lógicas:

���� ���������� ��

���� � ��

���������� � � ����

����� ����������� ���

��� �� ������

�� ������ �� ���

���������� � � ������

�����

���������� � � ����

���� � ���� � ������

O mejor aún:

���������� � � ����

����� ����������� ���

��� �� ������

���������� � � ������ � ����

�� ����������� ��

���� � ���� � ������

Page 79: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 144

Otro ejemplo de lectura anticipada:

�� �������� � �� � ��� ������ ����� ����� � �

�� �� � ���� �������� � ����� � ���� ������ ������

������ ���������

���� ������� ����

��� ������

��� !������" !��������" ������

!������#$�

!��������#$�

��� �� %&�������� �����' %�

��� �� ������

(��� � �

�) � �

��

��� �� %&�������� �����' %�

��� �� ������

*

��� �� %&�+��� % �� !������ �� % ���� %

�� !�������� �� % ������%�

*

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 145

cin >> valor;

while (valor != 0){

if (valor % 2 == 0)

ContPar = ContPar + 1;

else

ContImpar = ContImpar + 1;

cout << "Introduce ...

cin >> valor;

}

cout << "Fueron " ....

Línea en blanco después

Línea en blanco antes

Page 80: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 146

II.3.1.4. Condiciones compuestas

Es normal que necesitemos comprobar más de una condición en un bu-cle. Dependiendo del algoritmo necesitaremos conectarlas con �� o con��.

Ejemplo. Leer una opción de un menú. Sólo se admite s ó n.

���� �����

��

���� �� ������� ��������� �� �������

� �� �����

����� � ������ � ������ !

������ ������ " #�

¿Cuándo quiero salir del bucle? Cuando cualquiera de las condicionessea �����.

¿Cual es el operador que cumple lo siguiente?:

����� $������� ��� %�� ���� � �����

Nota. En este ejemplo, mucho mejor si pasamos la opción a mayúscu-la dentro del bucle y comprobamos únicamente las condiciones con loscaracteres en mayúscula

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 147

Ejemplo. Leer dos valores desde el teclado forzando a que ambos seandistintos de cero.

���

���� �� ������� �� � ������ ��

�� �� ������

���� �� ������� �� ���� ������ ��

�� �� ������

������ ��������� ����������

¿Cuándo quiero salir del bucle? Cuando ambas condiciones, simultánea-mente, sean ��� �. En cualquier otro caso, entro de nuevo al bucle.

¿Cual es el operador que cumple lo siguiente?:

��� � !"������ ��� � � ��� �

���� !"������ ��� #�� ��� � ����

En cualquier caso, hubiese sido mucho mejor leer cada valor en un bucleindependiente. De esa forma, si nos equivocamos al introducir uno perono el otro, sólo tendremos que volver a leer el valor incorrecto. Hacedloen la casa.

Consejo: En la construcción de condiciones compuestas,empezad planteando las condiciones simples quela forman. Pensad cuando queremos salir del bu-cle y conectad adecuadamente dichas condicio-nes simples, dependiendo de si nos queremos salircuando todas simultáneamente sean ��� � (OR) ocuando cualquiera de ellas sea ��� � (AND)

Page 81: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 148

Ejemplo. Calcular el máximo común divisor de dos números � y �.

Algoritmo:

� Entradas: Los dos enteros � y �

Salidas: el entero ���������, máximo común divisor de � y �

� Descripción e Implementación:

�� ������ ���� ����� ������ ����

��� �� ����� �� ����� �������

������� ���� �� ��� � ������

������ ��� �� ���� �������

��

� �����

����� � ��

����

����� � ��

���� � ������

� �� ��� ! ���� "� #� �� ! ���� "� #��

���� $$�

��������� � �����

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 149

El uso de una variable lógica hará que el algoritmo sea más fácil de en-tender:

������������ � � ���

��� � ����������������

�� ��������� �� �� ��������� �� ���

������������ � ����

� ��

���������

���������� � �������

¿Qué pasaría si quitásemos el � ��?

Page 82: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 150

Ejemplo. Encontrar el primer divisor propio impar de un número.

�������� ��� ����� ������ �� �� �����

����� ��������� �� ������� � ����� ������ � ����� �����

��� ����

��� �� ��

��� � ��

����� �� � ��� �� � �� � � ����

��� � ��� !�

Una vez terminado el bucle, ¿cómo comprobamos cual fue la condiciónque nos hizo salir?

�" �� � ��� �� ��

���� ## $%�&���� ������� ���' $ ## ����

����

���� ## $%�$ ## � ## $ �� ����� ��������� ����� �����$�

¿Y si el bucle terminó por la otra condición (� es un primo igual a ���)?En este caso � � ��� sería también cero, pero no queremos imprimir elmismo � como un divisor suyo.

��� � ��

����� �� � ��� �� � �� � � ����

��� � ��� !�

�" ���� # � �� � � ��� �� ��

���� ## $%�&���� ������� ���' $ ## ����

����

���� ## $%�$ ## � ## $ �� ����� ��������� ����� �����$�

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 151

Repetimos evaluación de condiciones equivalentes.

Solución: Usamos variables lógicas:

Nota. Podríamos salir del bucle en

Consejo: Fomentad el uso de variables lógicas para contro-lar las condiciones de salida de los bucles. Usare-mos tantas variables lógicas como condiciones ne-cesitemos controlar, y las conectaremos apropia-damente con los operadores lógicos.

Page 83: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 152

Ejemplo. Leer números enteros de la entrada por defecto hasta que seintroduzcan 10 ó hasta que se introduzca un número negativo. Imprimirla media aritmética.

���� � ��

� �� �� ���

���� ���������� � ��

�� � ���� �� �� �� �� ����� ���������� �� �����

���� � ���� � �� ���

���� �������������

� �� �� ���

���� � ��������� �����������

Problema: Lee el undécimo y se sale, pero ha tenido que leer dicho valor.Solución: O bien cambiamos la inicialización de ���� ���������� a 0,o bien leemos hasta 9. En cualquier caso, el décimo valor hay que proce-sarlo fuera del bucle.

�������

�� � ���� �� �� �� �� ����� ���������� � �����

���� � ���� � �� ���

���� �������������

� �� �� ���

���� � ���� � �� ���

���� � ��������� �����������

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 153

Problema: Si se ha salido con un negativo lo suma.Además, ��������������� también se incrementa en uno con el valornegativo, por lo que habría que tenerlo en cuenta a la hora de hallar lamedia aritmética. Quedaría:

� � � ��

��� �� ������

��������������� � ��

����� ������� �� �� �� ����������������������

� � � � � � ������

������������������

��� �� ������

�� ���������������� �� ���

� � � � � � ������

����

������������������

��� � � � ����������������

¿Pero y si el último leído es negativo?

�� ����������������� �� ��� �� ������ �����

� � � � � � ������

����

������������������

Podemos observar la complejidad (por no decir chapucería) innecesariaque ha alcanzado el programa.

Page 84: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 154

�Consejo: Construid los bucles de forma que no haya que

arreglar nada después de su finalización

Replanteamos desde el inicio la solución y usamos mejor variables lógi-cas:

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 155

Bajemos puntos en el examen. El algoritmo es el mismo, pero observadlos nombres de variables:

��� � ��

������ � ��

������� � ����

������� � ����

����� � ������� �� ���������

�� �� ��

�� �� � ��

������� � ��� ��

�� ��

��� � ��� � ��

���������

�� ������� �� ���

������� � ��� ��

�� ����� � ���!��"�#��������

�� ������� �� ��

��� �� $%&� � �����'��� ������ $�

�� �

��� �� $%(���� ���)*��� � $ �� �� ������

Page 85: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 156

Algunas citas sobre la importancia de escribir código que sea fácil deentender:

"Any fool can write code that a computer can understand. Good pro-grammers write code that humans can understand".Martin Fowler

"Programs must be written for people to read, and only incidentally formachines to execute".Abelson & Sussman

"Always code as if the guy who ends up maintaining your code will bea violent psychopath who knows where you live".

Un principio de programación transversal:

Principio de Programación:

Sencillez (Simplicity)

Fomentad siempre la sencillez y la legibilidad en laescritura de código

"There are two ways of constructing a software design: One way isto make it so simple that there are obviously no deficiencies, and theother way is to make it so complicated that there are no obvious defi-ciencies. The first method is far more difficult.".C.A.R. Hoare

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 157

Ejemplo. Comprobar si un número es primo.

�������� ��� ����

�������� ������

����� ��������� ����

��� �������

��� ��� � ����� �

�� ���� ���

��� ���� ����� �� ���� ���� ��� ��

��� �� ��� �

���� �� � ���

����� !

"���� ������ ��� ��

�# ���� $ ����� %�

���� �� #�����

����� &&�

'

�# ����� ���

��� ��� � �� � ��(���

����

��� ��� � � �� � ��(���

'

Para hacerlo más eficiente, nos salimos en cuanto sepamos que no esprimo. Nos salimos del bucle con un ��. La misma variable ���� ��

nos sirve:

Page 86: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 158

�������� ����

������ �

����� � ������ � ����� �� ����������

�� ������ � ������ ��

�������� ������

����

���������

Incluso podríamos quedarnos en ����������, ya que si ����� no es pri-mo, tiene al menos un divisor menor que ����������. En cualquier caso,��� es una operación costosa y habría que evaluarlo empíricamente.

�������� ����

��� �����������

������ �

����� � ������ � ��� �� ����������

�� ������ � ������ ��

�������� ������

����

���������

Nota. Realmente, para que compile sin problemas debemos poner ���

����� �!�������

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 159

Ampliación:Cuando ����� es un entero muy grande, el algoritmo anterior no termina enun tiempo razonable.

� ¿Qué es un número grande?

�������� ������ ������������� �������

� ¿Qué significa tiempo razonable?

Está fuera del alcance del curso e implica nociones más profundassobre complejidad computacional

Para una introducción informal pero clara:

�������������������������������������� ��������

El problema teórico más importante en Informática es determinar siexisten problemas que no pueden resolverse en un tiempo razona-ble con un algoritmo (aunque sí exista un algoritmo que comprueberápidamente si una propuesta es una solución o no). Este problemaestá aún sin resolver y es uno de los siete problemas del milenio,recompensado con 1 millón de dólares por el Instituto Clay de Ma-temáticas. En Agosto de 2010 un científico de HP proclamó haberlodemostrado, pero en pocas semanas se encontraron fallos en la de-mostración.

� El primer algoritmo para determinar en un tiempo razonable si unnúmero es primo, es bastante reciente (2002):

��������� �� !" ��������� ����

� Sobre números primos en general:

������������������

Page 87: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlados por condición: pre-test y post-test 160

II.3.1.5. Bucles sin fin

Ejercicio. ¿Cuantas iteraciones se producen?

�������� �

�� �� ��������� � �� �

����������

���� �� ���� �� ��������

�������� � �

�� �� ��������� �� ��� �

�������� � �������� �

Fomentad el uso de condiciones de desigualdad.

�������� � �

�� �� ��������� �� ��� �

�������� � �������� �

Estructuras de ControlEstructuras repetitivas → Bucles controlador por contador 161

II.3.2. Bucles controlador por contador

II.3.2.1. Motivación

Se utilizan para repetir un conjunto de sentencias un número de vecesfijado de antemano. Se necesita una variable contadora, un valor inicial,un valor final y un incremento.

Ejemplo. Hallar la media aritmética de cinco enteros leídos desde teclado.

��� �������

��� ����� ���� ���� ���� ������

����� ������

���� � ��

����� � ��

���� � ��

����� � �����

����� ������ �� �������

�� �� ���������� �� � ��� ��

�� !! �����

���� � ���� " �����

����� � ����� " ��

#

����� � ���� $ ������ %�&���

�� �� ���'� ����� �� � �� ������

#

Page 88: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlador por contador 162

�������� es la variable controladora del ciclo.

������ es el valor inicial que toma la variable controladora.

��� es el valor final que toma la variable controladora.

Estructuras de ControlEstructuras repetitivas → Bucles controlador por contador 163

II.3.2.2. Formato

La sentencia ��� permite la construcción de una forma compacta de losciclos controlados por contador, aumentando la legibilidad del código.

��� �����

��� ����� ��� ������ ����� ������� ������

����� �� ���

������ � ��

����� � ��

���� � ��

��� ����� �� � ������ � ����� �� �� ����� � ����� �� � ����� �� � ��

���� �� �������� ��� �� ������ ��

��� ������

���� � ���� � ������

!

�� �� � ���� " �����#�$��

���� �� ���%� �� �� �� � �� �� ���

!

Page 89: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlador por contador 164

��� �������� ������ � ������� ����� � ������� ������� � ���

���� ����������� �� ������ ��

��� �� ������

���� ���� � ������

� ������� ������ es la asignación inicial de la variable contadora.

� Si usamos como condición

������� �����

se producirá una iteración menos.

� ������� ������� � � aumenta en 1 el valor de ������� encada iteración. Por abreviar, suele usarse ��������� en vez de������� ������� � �

��� �������� ������ � ������� ����� � ����������

Podemos usar cualquier otro incremento:

����������

������� ������� � ��

� En el caso de incrementos negativos, la condición de terminacióndel bucle tendrá que ser del tipo: ������� � �����

Estructuras de ControlEstructuras repetitivas → Bucles controlador por contador 165

��� ([<contador = valor inicial>] ; [<condición sobre contador>];

[<actualización del contador>])

<cuerpo del bucle>

Page 90: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlador por contador 166

Encuentre errores en este código:

��� �� � ��� ��� ����

��� �� � �� � ��

Ejemplo. ¿Cuántos pares hay en [−10, 10]?

��� �������� ����������

��������� � ��

���� �������� � ���� �������� �� ��� ����������� �

�� � �������� ! �� ��

������������

��� �� �"�#�$ � �� ��������� �� � �������

Este problema también se podría haber resuelto como sigue:

��� ��������� ����

��� ���� � ���� ��� �� ��� ��� � ����!�

������������

��� �� �"�#�$ � �� ��������� �� � �������

Estructuras de ControlEstructuras repetitivas → Bucles controlador por contador 167

Ejemplo. Imprimir 9 veces el mensaje ����

��� ��

� �� � � � �� �� ����

���� �� ���������

¿Con qué valor sale la variable �? 10

Cuando termina un bucle for, la variable contadora se queda con el primervalor que hace que la condición del bucle sea falsa.

¿Cuántas iteraciones se producen en un �?

� Si ��������� � , ������ es menor que ���� y la condición es������� �� ����

���� � ������ �

� Si ��������� � , ������ es menor que ���� y la condición es������� � ����

���� � ������

� �� � �� � � �� ����

���� �� ���������

� �� � �� � � �� ����

���� �� ���������

Page 91: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Bucles controlador por contador 168

Número de iteraciones con incrementos cualesquiera.

Si es del tipo �������� � ���, tenemos que contar cuantos intervalosde longitud igual a ���� ���� hay entre los valores ��� y ���. Comoes un menor estricto, debemos quedarnos justo en el elemento anterioral final, es decir, �����. El número de intervalos será

���� � � � ���� � ���� ����

Y el número de iteraciones será

���� � � � ���� � ���� ���� � �

Si el bucle es del tipo �������� �� ���, el número de iteraciones sería:

���� � ���� � ���� ���� � �

Estructuras de ControlEstructuras repetitivas → Bucles controlador por contador 169

Ejercicio. ¿Qué salida producen los siguientes trozos de código?

��� �� ������

����� �

��� � � � � � �� ����

����� ����� � ��

���� �� ������

����� �

��� � � � � � �� � � ����

��������

����� �

� ��

����� � � ����

��������

� � � ��

Page 92: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Anidamiento de bucles 170

II.3.3. Anidamiento de bucles

Dos bucles se encuentran anidados, cuando uno de ellos está en el blo-que de sentencias del otro.

En principio no existe límite de anidamiento, y la única restricción que sedebe satisfacer es que deben estar completamente inscritos unos dentrode otros.

ANIDAMIENTO ANIDAMIENTOPERMITIDO NO PERMITIDO

Estructuras de ControlEstructuras repetitivas → Anidamiento de bucles 171

Ejemplo. Imprimir la tabla de multiplicar de los ���� primeros números.

������ ���������

���� ��������� ����

��� �������

����� ��� ���� � ��

��� �� ��

��� �� � � � � ���� � �!!� �

��� �� � � � � ���� � �!!�

��� � "#" � "�" �#� " "�

��� "$�"�

%

%

Salida:

j=1 j=2 j=3

i=1 # � #& � & #� � �

i=2 &# � & &#& � ' &#� � (

i=3 �# � � �#& � ( �#� � )

Page 93: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Anidamiento de bucles 172

¿Qué salida producen los siguientes trozos de código?

���������� ��

�� �� �� � � �� ����

�� �� �� � � � � ����

�������������

���������� ��

�� �� �� � � �� ����

�� �� �� � � � � ����

�������������

����� ��

�� �� � � � � �� � � ����

�� �� � � � � � � ����

��������

���� �� ������

Estructuras de ControlEstructuras repetitivas → Anidamiento de bucles 173

Ejemplo. Imprimir en pantalla los divisores primos del entero �

Algoritmo:

� Entradas: �Salidas: ninguna

� Descripción:

Recorrer todos los enteros menores que �

Comprobar si el entero es primo. En dicho caso, comprobar sidivide a �

Ineficiente. Es mejor el siguiente:

Recorrer todos los enteros menores que �

Comprobar si el entero divide a �. En dicho caso, comprobar siel entero es primo.

Nota. Mejor aún si empezamos desde ���

Page 94: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Anidamiento de bucles 174

� ��

������� � � � � � � � �

�� �������� � ��� � ������� � � � �����������

�� �� � ������� �� ���

������ � !��

��� � �" ��#�$���������

���������� � ��

%&�'� ����������� (� ��� )) ��������

�� �������� � ���������� �� ��

������ � �*'���

�'��

����������++�

,

�� ��������

-�! (( ./�0' ���� . (( ������� (( . ������ * . (( ��

,

,

Estructuras de ControlEstructuras repetitivas → Anidamiento de bucles 175

Ejemplo. El Teorema fundamental de la Aritmética (Euclides 300A.C/Gauss 1800) nos dice que podemos expresar cualquier entero comoproducto de factores primos.

Imprimir en pantalla dicha descomposición.

� �����

��

��

�� �

�� �

� �

Fijamos un valor de ����� cualquiera. Por ejemplo ������

�� ������� � ��� ����� ������� ����� ��� �������

����� � �

����� � ! ����� �� "#

���� $$ ����� $$ % %�

� � � � ������

&

Ahora debemos pasar al siguiente primo ����� y volver a ejecutar el blo-que anterior. Condición de parada: �'������ o bien �'�

(������� � ' �

������� � ��� ����� ������� ����� ��� �������

����� � ��)������ ����� ��*�� +�� �����

¿Cómo pasamos al siguiente primo?

Page 95: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Anidamiento de bucles 176

��������

����� ���� �� ���� ���� � �����

�� �� ������� �� ���� �� � �� �� ����� � �����

Este recorrido implica un bucle, pero no es necesario. Hagamos simple-mente �������:

��

������ � � �

������� � ��� ����� ����� � � �� ���

�������

��

����� � ��

���� �� � � !

���� �� " ����� �� # !

��� $$ ����� $$ % %�

� � � � ������

&

��������

&

¿Corremos el peligro de intentar dividir � por un valor ����� que no seaprimo? No. Por ejemplo, ��'#. Cuando ����� sea 4, ¿podrá ser � divisiblepor 4, es decir �"'��#? Después de dividir todas las veces posibles por2, me queda ��( que ya no es divisible por 2, ni por tanto, por ningúnmúltiplo de 2. En general, al evaluar �"�����, � ya ha sido dividido portodos los múltiplos de �����.

Nota. Podemos sustituir ��� por ������������� (tratando el primer caso������� de forma aislada)

Estructuras de ControlEstructuras repetitivas → Anidamiento de bucles 177

Ampliación:No hay forma de calcular el siguiente primo a uno dado (con una fórmuladirecta). Como mucho, se puede establecer una cota del número de primosque hay menores a uno dado. Este problema está ligado (demostrado porVon Koch en 1901) a la Hipótesis de Riemann, uno de los problemas mate-máticos más importantes sin resolver, y por el cual se ofrece una recom-pensa de 1 millón de dólares (por el Instituto Clay de Matemáticas)Riemann fue un gran matemático, discípulo de Gauss. Entre otras cosas,desarrolló la geometría de Riemann, base fundamental de la teoría de larelatividad de Einstein.

Ampliación:El problema de factorizar un número (expresarlo como producto de factoresprimos) es muy importante en la vida real.Hasta la fecha, no se ha conseguido construir (ni se espera que se consiga)un algoritmo que termine en un tiempo razonable para factorizar un númerocuando éste es grande. Los conceptos de número grande y tiempo razona-ble se presentaron en la página 159.¿Dónde se aplica? En Criptografía (Cryptography), para ocultar nuestrosdatos en Internet (por ejemplo, el número de la tarjeta de crédito). Mientrasno se diseñe un algoritmo en este sentido, nuestros datos bancarios estánbien protegidos de los sniffers.Consultad:������������ �������� ���������������

����������������������������������������

Buscad en Internet: Criptografía asimétrica, Integer factorization, RSA num-bers

Page 96: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 178

II.3.4. Particularidades de C++

C++ es un lenguaje muy versátil. A veces, demasiado · · ·

II.3.4.1. Expresiones y sentencias son similares

El tipo ���� como un tipo entero

En C++, el tipo lógico es compatible con un tipo entero. Cualquier expre-sión entera que devuelva el cero, se interpretará como �����. Si devuelvecualquier valor distinto de cero, se interpretará como ��.

���� ����� ����

����� ��� � ������

����� ��� � ������ �� ������� ������� �����

����� ��� � �� �� ������� ������� � ������� ���

����� ��� � ������ �� ������� ������� ��

����� ��� � ���

����� ��� � �� �� ������� ������� � ���� ���

Nota. Algunos compiladores, al ejecutar ��� �� �����, imprimen en pan-talla un cero, mientras que ��� �� �� imprime un uno.

La dualidad entre los tipos enteros y lógicos nos puede dar quebraderosde cabeza en los condicionales

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 179

��� ���� � �

� �� ���� ��

���� ���� � �� ����� � ����� ��� ��

����

���� ���� � �� ����� �� ��

El operador � tiene más precedencia que . Por lo tanto, la evaluación escomo sigue:� ���� � ⇔ ������� � ⇔ (���� vale 4) ������� � ⇔⇔ ���� � ⇔ � � ⇔ ����

¡Imprime � �� ����� � ����� ��� �!

Solución:

� �� ����� ���

���� ���� � �� ����� � ����� ��� ��

����

���� ���� � �� ����� �� ��

o mejor:

� ����� �� ��

���� ���� � �� ����� � ����� ��� ��

����

���� ���� � �� ����� �� ��

��

��Consejo: No hay que ser rácano con los paréntesis

Page 97: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 180

El operador de asignación en expresiones

El operador de asignación � se usa en sentencias del tipo:

����� � ��

Pero además, devuelve un valor: el resultado de la asignación. Así pues,����� � � es una expresión que devuelve �

������ � ���������� � ����� � ��

Esto producirá fuertes dolores de cabeza cuando por error usemos unaexpresión de asignación en un condicional:

����� � �

�� ������ � ��

�������� ��� �� ������� �� ������ ���� ������

����

�������� �����

�� � ��!�" ����� �� �� � �� �

����� � � devuelve �. Al ser distinto de cero, es ���. Por tanto, se ejecutael bloque �� (y además ����� se ha modificado con �)

� � ��

�� ���#�

��� �� $%&�'(� $ �� )���� �� *�� �� ������

����+

�, � )� - ������.� )/.�.�� � �0.�� � �� 1���� �23���

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 181

El operador de igualdad en sentencias

C++ permite que una expresión constituya una sentenciaEsta particularidad no da beneficios salvo en casos muy específicos y sinembargo nos puede dar quebraderos de cabeza. Así pues, el siguientecódigo compila perfectamente:

��� �������

� �

C++ evalúa la expresión entera � �, devuelve � y no hace nada con él,prosiguiendo la ejecución del programa.

��� �������

������ �� ��

C++ evalúa la expresión lógica ������ �� ��, devuelve �� � y no hacenada con él, prosiguiendo la ejecución del programa.

Page 98: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 182

El operador de incremento en expresiones

�������� �

�� ��������� � �� ���

���� �� �������� �� � �� ����� � � �� ��������

���� �� �������� �� �������

El operador (y ��) forma una expresión: devuelve el valor incrementa-do:

�������� �

�� ��������� �� ���

���� �� �������� �� � �� ����� � � �� ��� �� ����� � �

���� �� �������� �� ����

�Consejo: No usad � ni en la expresión lógica de una sen-

tencia condicional

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 183

II.3.4.2. El bucle ��� en C++

Bucles ��� con cuerpo vacío

El siguiente código no imprime los enteros del 1 al 20. ¿Por qué?

��� �� � �� � � �� ��� �

���� ��

Realmente, el código bien tabulado es:

��� �� � �� � � �� ���

���� ��

Bucles ��� con sentencias de incremento incorrectas

Lo siguiente es un error lógico:

��� ���� � ���� ��� � ��� ��� � �� �� ��� �� ��� � ��� �

������������

equivale a:

��� � ����

��� � ���� � �� !

������������

��� � �

"

Compila correctamente pero la sentencia ��� � � no incrementa ��� (re-cordad lo visto en la página 181) Resultado: bucle infinito.

Page 99: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 184

Modificación del contador

Únicamente mirando la cabecera de un bucle ��� sabemos cuantas itera-ciones se van a producir (recordar lo visto en la página 168). Por eso, enlos casos en los que sepamos de antemano cuántas iteraciones necesi-tamos, usaremos un bucle ���. En otro caso, usaremos un bucle ����� ó� �����.

Para mantener dicha finalidad, es necesario respetar la siguiente restric-ción:

No se debe modificar el valor de la variable controladora,ni el valor final dentro del cuerpo del bucle ���

Sin embargo, C++ no impone dicha restricción. Será responsabilidad delprogramador.

Ejemplo. Sumar los divisores de ����. ¿Dónde está el fallo en el siguien-te código?:

� �� � ��

���� � �������

��� ������ � �� ����� �� ���� � �������� �

�� ����� � ����� �� ��

� �� � � �� � ������

��������

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 185

Supongamos que quiero salir de un bucle ��� cuando se produce unacondición. ¿Cómo lo hago?

Ejemplo. Escribe los enteros entre ��� y ���, hasta llegar al primer múlti-plo de 13:

�� ����

�� ����

��� � �� �� � ���� �� �� �� ���� �� ����� �

��� �� �� �� �� � ��

�� � �� �� � �� �� ��

�� �� � ��� � �� �� ���

Esto funciona pero es una chapuza. Mejor usamos un ���� :

�� ����

�� ����

�� �� � ����

���� � �� �� �� ���� � �� �� � �� !� ���

��� �� �� �� �� � ��

Page 100: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 186

Ejemplo. Comprobar si un número es primo

�������� ����

�� �������� � � ������� � ����� � ����������

� ������ � ������� ���

�������� �����

������� ������ �� ���

Mejor la solución que vimos en la página 158:

�������� ����

������� �

����� �������� � ����� ����������

� ������ � ������� ��

�������� �����

����

����������

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 187

El bucle ��� como ciclo controlado por condición

Si bien en muchos lenguajes tales como PASCAL, FORTRAN o BASIC elcomportamiento del ciclo ��� es un bucle controlado por contador, enC++ es un ciclo más versátil, controlado por condición.

En el caso concreto de C++, su sintaxis es la siguiente:

��� ([<sentencia inicial>];

[<expresión lógica>];

[<sentencia final>])

<cuerpo bucle>

donde,

� <sentencia inicial> es la sentencia que se ejecuta antes de entraral bucle,

� <expresión lógica> es cualquier condición que verifica si el ciclodebe terminar o no,

� <sentencia final> es la sentencia que se ejecuta antes de volverarriba para comprobar el valor de la expresión lógica.

Por tanto, la condición impuesta en el ciclo no tiene por qué ser de laforma �������� < ���, sino que puede ser cualquier tipo de condición.

Page 101: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 188

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 189

Ejemplo. Comprobar si un número es primo. Lo resolvimos en la pági-na 158:

�������� ����

������ �

����� � ������ � ����� �� ����������

�� ������ � ������ ��

�������� ������

����

���������

Con un ��� quedaría:

�������� ����

������ �

��� � ������ �� ������ � ����� �� ��������� ���������

�� ������ � ������ ��

�������� ������

Page 102: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 190

Ejemplo. Escribe los enteros entre ��� y ���, hasta llegar al primer múlti-plo de 13 (lo vimos en la página 185)

��� �� ���

��� �� ���

��� � ���

���� ���� �� ��� �� ��� � �� �� ���

� �� �� ��� �� � �

��� ��

��� �� ���

��� �� ���

� � ���� � ��� ��� �� ��� �� ��� � �� �� � ��� ���

� �� �� ��� �� � �

En los ejemplos anteriores

� � ���� � ��� ��� ����� �� ��� ��� �� � ��� ���

� � ��� �� � � ! �� �� � �� � � �� �"���# �� �� ����

se ha usado dentro del � � dos condiciones que controlan el bucle:

� La condición relativa a la variable contadora.

� Otra condición adicional.

Este código es completamente aceptable en C++.

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 191

En resumen, usaremos un bucle ��� en los casos en losque siempre exista:

� Una sentencia de inicialización del contador

� Una condición de continuación que involucre al con-tador (pueden haber otras condiciones adicionales)

� Una sentencia final que involucre al contador

Page 103: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 192

Pero ya puestos, ¿puede usarse entonces, cualquier condición dentro dela cabecera del ���? Sí, pero no es muy recomendable.

Ejemplo. Construir un programa que indique el número de valores queintroduce un usuario hasta que se encuentre con un cero.

�� �������� ��� ����� � ��� �� � ����� � �� �

�� ������� � ����� �� � �� ���� �� ���

�� ��� ������ �� ��� ���� ���

������ ������ ���

����� ��� �� ����

��� ������

��� ���!����� �" ������

�� �� ������

���!����� � # $�

���� ������ %# $�

�� �� ������

���!����� �&&�

'

��� �� ()� �*� �� � ����� � ����������� � (

�� ���!����� ��

'

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 193

Lo hacemos ahora con un ���:

�� �������� ��� ����� � ��� �� � ����� � �� �

�� ������� � ����� �� � �� ���� �� ���

�� ��� ������ �� ��� ��� ���

������ ������ ���

����� ��� �� ����

��� ������

��� ���!����� �" ������

�� �� ������

��� ����!����� �#$� �����%#$� ���!����� �&&�

�� �� ������

��� �� '(�)� ��� �� � ����� � ����������� � '

�� ���!����� ��

*

Debemos evitar este tipo de bucles ��� en los que la(s) variable(s) queaparece en la condición, no aparece en las otras dos expresiones.

Page 104: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 194

En el anterior ejemplo, si cambiamos los nombres de las variables, ten-dríamos:

��� ��������� ��������� ��������

�����

Y el cerebro de muchos programadores le engañará y le harán creer queestá viendo lo siguiente, que es a lo que está acostumbrado:

��� ��������� ��������� ��������

�����

Esto no quiere decir que, ADEMÁS de la variable contadora, no podamosusar condiciones adicionales para salirnos del bucle. Será algo usual (lohicimos en el ejemplo del primo)

Y ya puestos, ¿podemos suprimir algunas expresiones de la cabecera deun bucle ���? La respuesta es que sí, pero hay que evitarlas SIEMPRE.Oscurecen el código.

Ejemplo. Sumar valores leídos desde la entrada por defecto, hasta intro-ducir un cero.

��� ����� �

��� ������ ����

��� �� �����

��� � �������� �

���� � ���� � �����

��� �� �����

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 195

II.3.4.3. Otras (perniciosas) estructuras de control

Existen otras sentencias en la mayoría de los lenguajes que permitenalterar el flujo normal de un programa.

En concreto, en C++ existen las siguientes sentencias:

���� �������� ��� � ��

Durante los 60, quedó claro que el uso incontrolado de sentencias detransferencia de control era la principal fuente de problemas para los gru-pos de desarrollo de software.

Fundamentalmente, el responsable de este problema era la sentencia���� que le permite al programador transferir el flujo de control a cual-quier punto del programa.

Esta sentencia aumenta considerablemente la complejidad tanto en lalegibilidad como en la depuración del código.

Referencias:

Teorema de Bohm y Jacopini -1966-. Flow diagrams, Turing machines andlanguages only with two formation rules. Communications of the ACM, 1966.Vol. 9, No.5, pp. 366-371

Dijkstra, E.W. Goto statement considered harmful. Communications of theACM, 1968. Vol. 11, No.3, pp. 147-148

Page 105: Fundamentos de Programacion

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 196

Ampliación:Consultad el libro Code Complete de McConnell, disponible en la biblioteca.Incluye numerosos consejos y hábitos aconsejables de programación. Enel tema de Estructuras de Control incluye una referencia a un informe en elque se reconoce que un uso inadecuado de un �����, provocó un apagóntelefónico de varias horas en los 90 en NY.

En FP, no se permitirá el uso de ninguna de las sentenciasanteriores, excepto la sentencia ����� con el propósito

aquí descrito dentro de la sentencia ����.En caso contrario, el Suspenso está garantizado.

Estructuras de ControlEstructuras repetitivas → Particularidades de C++ 197

Bibliografía recomendada para este tema:

� A un nivel menor del presentado en las transparencias:

– Segundo capítulo de Deitel & Deitel

� A un nivel similar al presentado en las transparencias:

– Segundo y tercer capítulos de Garrido.

� A un nivel con más detalles:

– Capítulos quinto y sexto de Stephen Prata.

– Tercer capítulo de Lafore.

Los autores anteriores presentan primero los bucles junto conla expresiones lógicas y luego los condicionales.

Page 106: Fundamentos de Programacion

Tema III

Funciones y Clases

Objetivos:

� Introducir el concepto de función y parámetro para no tener queduplicar código.

� Encapsular datos y funciones en un mismo módulo: la CLASE.

� Construir objetos sencillos que cumplan principios básicos de di-seño.

Autor: Juan Carlos Cubero.

Sugerencias: por favor, enviar un e-mail a ������������ ��������

Funciones y ClasesFunciones → 199

III.1. Funciones

III.1.1. Fundamentos

III.1.1.1. Las funciones realizan una tarea

A la hora de programar, es normal que haya que repetir las mismas ac-ciones con distintos valores. Para no repetir el mismo código, tendremosque:

� Identificar las acciones repetidas

� Identificar los valores que pueden variar (esto es, los parámetros)

� Definir una función que encapsule dichas acciones

Las funciones como ����, �������, etc., no son sino ejemplos de funcio-nes incluidas en ��� y � ��, respectivamente, que resuelven tareasconcretas y devuelven un valor.

Se suele utilizar una notación prefija, con parámetros (en su caso) sepa-rados por comas y encerrados entre paréntesis.

��� ������

������ ������ ������ ����������� ���������

���������� �� ������� � ��� �����

�������� ! �����"����� # �����"������

���������� ! ���������������

Page 107: Fundamentos de Programacion

Funciones y ClasesFunciones → Fundamentos 200

Si queremos calcular la hipotenusa de dos triángulos rectángulos:

������������������������������

��� ������

�� �� ������� ������� ������� �������

������������� �������������

���������� ����������

����������� � ������� � ��� ����

��������� ! ������"������ # ������"�������

������������ ! �$��������������

��������� ! ������"������ # ������"�������

������������ ! �$��������������

������������������������������

%

¿No sería más claro, menos propenso a errores y más reutilizable el códi-go si existiese en alguna biblioteca una función &���������? El fragmentode código anterior quedaría como sigue:

������������������������������

��� ������

�� �� ������� ������� ������� �������

������������� �������������

����������� � ������� � ��� ����

������������ ! &����������������� ��������

������������ ! &����������������� ��������

������������������������������

Funciones y ClasesFunciones → Fundamentos 201

En este ejemplo, �������� es una función que resuelve la tarea de cal-cular la longitud hipotenusa de un triángulo, sabiendo la longitud de loslados.

Podría dar la sensación de que primero debemos escribirel programa con todas las sentencias y luego

construiríamos la función ��������. Esto no deberíahacerse así: el programador debe identificar las funciones

antes de escribir una sola línea de código.En cualquier caso, no siempre se detectan a priori las

funciones, por lo que, una vez escrito el código, sidetectamos bloques que se repiten, deberemos

englobarlos en una función.

Page 108: Fundamentos de Programacion

Funciones y ClasesFunciones → Fundamentos 202

III.1.1.2. Definición

<tipo> <nombre-función> ([<parám. formales>]) �

[<sentencias>]

return <expresión>;

� Por ahora, la definición se pondrá después de la inclusión de bi-bliotecas y antes del ����. Antes de usar una función en cualquiersitio, hay que poner su definición.

� Diremos que<tipo> <nombre-función> (<parám. formales>)es la cabecera (header) de la función.

� El cuerpo de la función debe contener:

���� <expresión>;

donde <expresión> ha de ser del mismo tipo que el especificadoen la cabecera de la función (también puede ser un tipo compati-ble). El valor que contenga dicha expresión es el valor que devuelvela función cuando es llamada.��

��La llamada a una función constituye una expresión.

������ ���� �� es una expresión.

Funciones y ClasesFunciones → Fundamentos 203

������ ������������� ������ �

���� ��������������

� En C++ no se pueden definir funciones dentro de otras. Todas estánal mismo nivel.

� Como norma de escritura de código, escribiremos la primera letrade las funciones en mayúscula.

III.1.1.3. Parámetros formales y actuales

� Los parámetros formales (formal parameters) son aquellos especi-ficados en la cabecera de la función.Al declarar un parámetro formal hay que especificar su tipo de da-to.Los parámetros formales sólo se conocen dentro de la función.

� Los parámetros actuales (actual parameters) son las expresionespasadas como argumentos en la llamada a una función.

Llamada:

<nombre-función> (<lista parámetros actuales>);

Nota. En inglés se usan los términos formal and actual parameters. Hubiese sido

mejor llamarlos parámetros de llamada o algo así.

Page 109: Fundamentos de Programacion

Funciones y ClasesFunciones → Fundamentos 204

������ ������������� ������ �

���� ��������������

��� ���� �

������ ��������� �����

���� � ��

�������� � ����������� � �� �������� � ��

���� �� ��� ������� �� � �� ���� �� � �� � �� ���������

� Flujo de control

Cuando se ejecuta la llamada �������� � ����������� � el flujo decontrol salta a la definición de la función.

� Se realiza la correspondencia entre los parámetros.El correspondiente parámetro formal recibe una copia del paráme-tro actual, es decir, se realiza la siguienteasignación en tiempo de ejecución:

parámetro formal � parámetro actual

En el ejemplo, ������ � �

Esta forma de pasar parámetros se conoce como paso de paráme-tros por valor (pass-by-value).

� Empiezan a ejecutarse las sentencias de la función y, cuando sellega a alguna sentencia ���� <expresión>, termina la ejecuciónde la función y devuelve el resultado de evaluar <expresión> allugar donde se realizó la invocación.

� A continuación, el flujo de control prosigue por donde se detuvo alrealizar la invocación de la función.

Funciones y ClasesFunciones → Fundamentos 205

������ ������������� ������ � ������ � ����

���� ��������������

��� ���� �

������ ��������� �����

���� � ��

�������� � ����������� � �� �������� � ��

���� �� ��� ������� �� � �� ���� �� � �� �

�� ���������

Page 110: Fundamentos de Programacion

Funciones y ClasesFunciones → Fundamentos 206

Ejercicio. Definid la función ��������

���� ��� ��������

���� ��� ������

���� ������ ���

���� � ��������� ��

��� ������

���� � ������ ������ ���� � ���� �

����������� ��������� �

�������!� �� " ��� � ���

���������� # ��������� ������ �������

��������� # ��������� ���� � ���� ��

$$$$$$$$$$$$$

Funciones y ClasesFunciones → Fundamentos 207

� Correspondencia entre parámetros actuales y formales

� Debe haber exactamente el mismo número de parámetros actualesque de parámetros formales.

������ ������������� ������ �

���� �������������

��� ���� �

������ ���������

�������� � ��������� � � �� �� �� �����������

� Debemos garantizar que el parámetro actual tenga un valor correc-to antes de llamar a la función.

������ ������������� ������ �

���� �������������

��� ���� �

������ ��������� �����

�������� � ����������� � �� �� ������

� La correspondencia se establece por orden de aparición, uno a unoy de izquierda a derecha.

�������� ���������

�������� ����� �

����� �����!��� ����

������ "���������� ����#$� ������ ����#% �

���� ����#$ & ����%�

��� ���� �

������ ��#���� � '()� ���#���� � *()�

Page 111: Fundamentos de Programacion

Funciones y ClasesFunciones → Fundamentos 208

���� �� ������ � �� ������������� ������������

���� �� ������ � �� ��������������� ����������

� El parámetro actual puede ser una expresión.Primero se evalúa la expresión y luego se realiza la llamada a lafunción.����������� ����������������� � ����� !��

� Cada parámetro formal y su correspondiente parámetro actual hande ser del mismo tipo (o compatible)

���"� #�����������"� �������$

����� ������ ������

��� %�����$

���"� ���������

��� ����� &�

�������� #���������������

Problema: que el tipo del parámetro formal sea más pequeño queel actual. La conversión de tipos puede que no se realice correcta-mente, por lo que el parámetro formal toma un valor distinto al quepretendíamos y la función devuelve un valor erróneo

��� #����������� �������$

����� ������ �������

��� %�����$

��� ���������

�������� #��������'(((((((((((��

)) ����� "�����

Funciones y ClasesFunciones → Fundamentos 209

� Dentro de una función, se puede llamar a cualquier otra funciónque esté definida con anterioridad. El paso de parámetros entrefunciones se realiza igual independientemente de dónde esté la lla-mada.

�������� ��� ����

�������� ������

����� ��������� ����

����� ���� �������� ��� �����

��� � ��� ������� ����

����� ��������������� ������� ����� � ������

��� � �� ������ ���������� ���� ���� �������

��� �������

����� ���!�"� ���#�"� ���!�$� ���#�$�

����������"� ����������$�

"�������%� �� &�� �� � �� �����

����������" ' �������������!�"� ���#�"��

����������$ ' �������������!�$� ���#�$��

(((((((((((((

Page 112: Fundamentos de Programacion

Funciones y ClasesFunciones → Fundamentos 210

Funciones y ClasesFunciones → Fundamentos 211

� Las modificaciones del parámetro formal no afectan al parámetroactual. Recordemos que el paso por valor conlleva trabajar con unacopia del valor correspondiente al parámetro actual, por lo que ésteno se modifica.

������ ������������� ������ �

������ � ��������������

���� �������

��� ���� �

������ ��������� ���� � ��

�������� � ����������� �

�� ���� ����� ������ �

Ampliación:Algunos lenguajes de programación proporcionan otros métodos de pasarparámetros, en los que una modificación del parámetro formal sí afecta alcorrespondiente parámetro actual. En C++ se utiliza el paso por referencia(pass-by-reference). Se verá en el segundo cuatrimestre.

Page 113: Fundamentos de Programacion

Funciones y ClasesFunciones → Fundamentos 212

III.1.1.4. Datos locales

� Dentro de una función podemos declarar constantes y variables.Estas constantes y variables sólo se conocerán dentro de la fun-ción, por lo que se les denomina datos locales (local data).

� De hecho, los parámetros formales se pueden considerar datos lo-cales.

<tipo> <nombre-función> (<lista parámetros formales>) �

[<Constantes Locales>]

[<Variables Locales>]

[<Sentencias>]

������ <expresión>;

Al igual que ocurre con la declaración de variables del ��, las variableslocales a una función no inicializadas a un valor concreto tendrán unvalor indeterminado (basura) al inicio de la ejecución de la función.

Funciones y ClasesFunciones → Fundamentos 213

Ejemplo. Calculad el factorial de un valor.Recordemos la forma de calcular el factorial de un entero �:

���� � ��

� �� � � � �� � � ����

���� � ���� � ��

Como una función, quedaría:

��� ������� ���� ���

��� ��

��� ���� � ��

� �� � � � �� �� ����

���� � ���� � ��

���� �����

��� �������

��� ���� ��������

��� �� �������� �� �����

��� !! ����

������� � �������������

��� �� ���������� �� � �� ��� �� � � � �� ��������

Page 114: Fundamentos de Programacion

Funciones y ClasesFunciones → Fundamentos 214

Dentro de una función no podemos acceder a los datos locales definidosen otras funciones ni a los de ����.

��� ������� ���� ��

��� �� ���� � ��

��� � �� �� �� �� ���������� ���

�� �� � �� � �� �� ����

���� � ���� ��

��!� �����

"

��� ������

��� ���� �#!�����

� � �� �� �� �� ���������� ���

� � �� �� �� �� ���������� ���

��!� �� $%�&����!'�� ���$�

��� (( ����

�#!���� � �������������

��!� �� $%�������� �� $ �� ��� �� $ � $ �� �#!�����

"

Funciones y ClasesFunciones → Fundamentos 215

En definitiva:

�Cada función tiene sus propios datos (parámetros forma-les y datos locales) y no se conocen en ningún otro sitio.

Page 115: Fundamentos de Programacion

Funciones y ClasesFunciones → Fundamentos 216

Por tanto, los nombres dados a los parámetros formales pueden coincidircon los nombres de los parámetros actuales: son variables distintas.

��� �������� ��� ��� �� � �� ��������� ��

��� ��

��� ���� � ��

��� ���� ����� ����

���� � ���� � ��

������ �����

��� ������

��� � � � ��!������ �� � �� ����� ��

��!����� � �����������

���� �� "�������� �� " �� � �� " � " �� ��!������

#�$���� �� $����� � !�%������&

�������� �� � � '

Funciones y ClasesFunciones → Fundamentos 217

�������� ��� ����

�������� ������

����� ��������� ����

����� ��������������� ������� ����� � ������

��� � �� ��������������� � � ������ ������

��� �������

����� ������� � ����� ����������

��� !�"�� ��#�� � ��� ��� �

��� �� �������

��� !�"�� ��#�� ������ ��� �

��� �� � �����

��������� $ ����������������� � ������

��� !�%� ��������� &��� ����������

Page 116: Fundamentos de Programacion

Funciones y ClasesFunciones → Fundamentos 218

III.1.1.5. La Pila

Cada vez que se llama a una función, se crea dentro de una zona dememoria llamada pila (stack), un compartimento de trabajo asociado aella, llamado marco de pila (stack frame).

� Cada vez que se llama a una función se crea el marco asociado.

� En el marco asociado a cada función se almacenan, entre otrascosas:

– Los parámetros formales.

– Los datos locales (constantes y variables).

– La dirección de retorno de la función.

� Cuando una función llama a otra, el marco de la función llamada seapila sobre el marco de la función desde donde se hace la llamada(de ahí el nombre de pila). Hasta que no termine de ejecutarse laúltima función llamada, el control no volverá a la anterior.

Funciones y ClasesFunciones → Fundamentos 219

�������� ��� ����

����� ��������� ����

��� ���� ��� ���� ���

��� ��

��� ���� � ��

� �� � �� � � �� ����

���� � ���� � ��

��� � �����

��� �� ���� ����� �! ��� ��

��� � ���� ������"����� ���� � � ���� �����# ���

��� �������

��� �������! ���������$! � ������

������� � �� ���� ����������! � �����

��� �������� % � � % � ��� % � % ��������

Page 117: Fundamentos de Programacion

Funciones y ClasesFunciones → Fundamentos 220

Funciones y ClasesFunciones → Fundamentos 221

���� es de hecho una función como otra cualquiera, por lo que tambiénse almacena en la pila. Es la primera función llamada al ejecutarse elprograma.

Devuelve un entero al Sistema Operativo y puede tener más parámetros,pero en FP sólo veremos el caso sin parámetros. Por eso, la hemos de-clarado siempre como:

��� �������

� Si el programa termina sin errores, se debe devolver 0.Puede indicarse incluyendo ��� �� �� al final de ���� (antes de )

En C++, si no se devuelve nada, se devuelve 0 por defecto, por loque podríamos suprimir ��� �� ��

� Si el programa termina con un error, debe devolver un entero dis-tinto de 0.

Page 118: Fundamentos de Programacion

Funciones y ClasesFunciones → Fundamentos 222

III.1.1.6. Ejemplos de funciones

Ejemplo. Comprobar si un número es par.

���� ����� �� � �

� � � � �� �

������ �����

����

������ ������

�� ��� �

�� ����������

���� �����������������

�� �� ����������

���������������� � ����� ��������� �

� ����������������

���� �� ��������� �� � �� �����

����

���� �� ��������� �� � �� ������

De forma más compacta:

���� ����� �� � �

������ � � � �� � �

Funciones y ClasesFunciones → Fundamentos 223

Ejemplo. Comprobar si dos reales son iguales, aceptando un margen enla diferencia de 0,000001

���� �������� � ���� ���� ���� ������

����� �������� � ����� �� ����������

Ejemplo. Comprobar si un número es primo (recordad el algoritmo vistoen la página 158)

���� ����������� �����

���� �!"�����

��� � �����

�!"���� � ����

��� � � ���� � # � � ���� � ��� $$ �!"���� � � ����%%�

�� � ��� & � ���� �� ��

�!"���� � ����

����� �!"�����

Ejemplo. Calcular el MCD de dos enteros.

��� '()���� "������ ��� ���� ���

*+

,��� � � �� � ��� �� ����� "�� �� �� ���

����� ����� -� � ���� ���� .�� -�/

� ���� �� � ������ "�� � ����� ���

� � .�� -� ������� � �

+*

���� .0! � ������ �1 !�1���� ��

��� � ����� �1 �

Page 119: Fundamentos de Programacion

Funciones y ClasesFunciones → Fundamentos 224

�� �������� �� �� �����

��� �

�����

�� �������� � �� �����

������� �� �����

����

������� ��������

������������� �����

�������������� ������

����� �������������� �� �����������������

�� �������� ��

������������� ������

��� �

!

�����

�� ���������"������� � �� ��� ����"������� ���

�������������� �����

��� ��������

!

�����

�������##�

!

!

!

!

������ ����

!

Funciones y ClasesFunciones → Fundamentos 225

Veamos ahora ejemplos de funciones con errores:

��� �������� ��� �� �

��� � �����

���� � ��

��� � � �� � �� �� ���� �

���� � ���� � ��

������ ����� �� ��

La función termina cuando se ejecuta la primera iteración.

Estilo de programación a evitar

��� ����� ���� !�����

��� ��"#�� �� �� ���� �$�

��"#�� � � �����

��� %�!���� � � � %�!���� � !��� && ��"#�� � � %�!�������

�� !��� ' %�!���� �� (�

������ �����

������ ��"#�� ��

Consejo: No introducir sentencias ������ en varios sitios dis-tintos del cuerpo de la función.Dejar un único ������ al final de la función

Page 120: Fundamentos de Programacion

Funciones y ClasesFunciones → Fundamentos 226

���� ����� �� � �

� ������

������ ����� �� ��

La función debe devolver siempre un valor. En caso contrario, el compor-tamiento es indeterminado.

Funciones y ClasesFunciones → Funciones void 227

III.1.2. Funciones void

Ejemplo. Supongamos que en el ���� nos encontramos este trozo de có-digo:

��� �� ��������

��������������������

��� ���� ����������� ����

���� �� ����������������

���� �� ��������� ������ !���������"��

��� ���� ����������� ����

���� �� ����������������

��������������������

¿No sería más fácil de entender si el código del programa principal hu-biese sido el siguiente?

��������������������

��������������������

��������������������

En este ejemplo, ���������� resuelve la tarea de realizar la presenta-ción del programa por pantalla, pero no calcula (devuelve) ningún valor,como sí ocurre con las funciones �#�� o $��������. Por eso, su llamadaconstituye una sentencia y no aparece dentro de una expresión.Caso conocido: �%�����������Este tipo particular de funciones que no devuelven ningún valor, se defi-nen como sigue:

Page 121: Fundamentos de Programacion

Funciones y ClasesFunciones → Funciones void 228

���� <nombre-función> (<lista parámetros formales>) �

[<Constantes Locales>]

[<Variables Locales>]

[<Sentencias>]

Obsérvese que no hay sentencia ����. La función ���� termina cuandose ejecuta la última sentencia de la función.

El paso de parámetros y la definición de datos locales sigue las mismasnormas que el resto de funciones.

Para llamar a una función ����, simplemente, ponemos su nombre y lalista de parámetros actuales con los que realizamos la llamada:

���� �� ������������ ���������������� ����� ���������������������

���������������

�� �������

�� ��������������

����� ������������������

���������������

�� ������������������������ �������������������

������������������������

Funciones y ClasesFunciones → Funciones void 229

�������� ��� ����

�������� ������

����� ��������� ����

����� ���� �������� ��� �����

��� � ��� ������� ����

����� ��������������� ������� ����� � ������

��� � �� ������ ���������� ���� ���� �������

!�� " ������������� ������������

��� ��

# ��$%� �$���������� � � �

��� &'�������������&�

��� &" � ��� �(��� �� ) ������ *�&�

# ��$%� �$���������� � � �

��� &'�������������&�

��� �������

����� ���%� ���+� ����������

" ����������,��

��� �� ���%�

��� �� ���+�

��������� $ �������������%����+��

��� &'�-� ��������� !��� & ����������

Page 122: Fundamentos de Programacion

Funciones y ClasesFunciones → Funciones void 230

Llamadas entre funciones ����.

���� ��������� ���� �������� ��

��� ��

��� �� � �� � �� �������� � ����

���� �� �����������������

���� � ����������� �������� ��

��������� ��������� ��

���� �� � ��!���� "# ��� � $��!������%���

��������� ��������� ��

O incluso:

���� ������& ��� �� ���� ����� ��� �� ��

��� ��

��� �� � � � � �� ����� ��� �� � ����

���� �� ����

���� ��������� ���� �������� ��

��� ��

��� �� � �� � �� �������� � �����

���� �� ���� �� ������& ��� �� ��'��

���� � ����������� �������� ��

��������� ��������� ��

���� �� � ��!���� "# ��� � $��!������%���

��������� ��������� �� �

Funciones y ClasesFunciones → Documentación de una función 231

III.1.3. Documentación de una función

Hay dos tipos de comentarios:

� Descripción del algoritmo que implementa la función

� Describen cómo se resuelve la tarea encomendada a la función.

� Se incluyen dentro del código de la función

� Sólo describimos la esencia del algoritmo (tema II)

Ejemplo. El mayor de tres números

��� ���� ���� � ��� ��� ��

��� ����

�� �������� �� ������ ����� � � �� ���

�������� �� ������ ����� ��� � �

��

�� �����

��� � ��

����

��� � �

�� �������

��� � ��

������ ����

Page 123: Fundamentos de Programacion

Funciones y ClasesFunciones → Documentación de una función 232

� Descripción de la cabecera de la función

� Describen qué tarea resuelve la función.

� También describen los parámetros (cuando no sea obvio).

� Se incluyen fuera , justo antes de la cabecera de la función

�� ������� �� ���� � ���� �������

��� ��� ���� �� ��� �� ��� ���

��� ���

�� �������� �� ���� ����� � � �

�������� �� ���� ����� �� � �

��

�� ������

�� � ��

����

�� � ��

�� ������

�� � ��

������ ���

Funciones y ClasesFunciones → Documentación de una función 233

Incluiremos:

� Una descripción breve del cometido de la función.�

Consejo: Si no podemos resumir el cometido de una funciónen un par de líneas a lo sumo, entonces la funciónes demasiado compleja y posiblemente debería di-vidirse en varias funciones.

� Una descripción de lo que representan los parámetros (salvo queel significado sea obvio)

También incluiremos las restricciones que deben satisfacer los pa-rámetros para que la función pueda ejecutarse sin problemas.

Dichas restricciones se denominan precondiciones (precondi-tions) de la función.

Por ejemplo, si trabajamos con el tipo ���, para garantizar elcómputo correcto del denominador en la expresión

⎛⎝ a

b

⎞⎠ =

a!

b!(a − b)!

debemos obligar a que a y b sean menores de 8

�� ���� ����� �� ��� �

�� ����������� � � ����� �� �

��� ����� ������ � ��� ���

���� � ��� �� ���� ��� ���� � � ��� �� �����

Page 124: Fundamentos de Programacion

Funciones y ClasesFunciones → Documentación de una función 234

En el examen es imperativo incluir la descripción delalgoritmo.

Ampliación:Consultad el capítulo 19 del libro Code Complete de Steve McConnell sobrenormas para escribir comentarios claros y fáciles de mantener.

Funciones y ClasesFunciones → Ámbito de un dato 235

III.1.4. Ámbito de un dato

Ámbito (scope) de un dato (variable o constante) � es el conjunto de todasaquellas funciones que pueden acceder a �.

El ámbito depende del lugar en el que se declara el dato.

� Lo que ya sabemos:

Datos locales (declarados dentro de una función)

� El ámbito es la propia función.

� No se puede acceder a � desde otras funciones.

Nota. Lo anterior se aplica también, como caso particular, a la función����

Parámetros formales de una función

� Se consideran datos locales de la función.

Page 125: Fundamentos de Programacion

Funciones y ClasesFunciones → Ámbito de un dato 236

� Lo nuevo (ni bueno ni malo):

Datos declarados dentro de un bloque

� El ámbito es el propio bloque

����� ���������

� ��

������������

��� �� ���� ����� �����

������������

En este caso, el ámbito de la variable termina con la llave � que cierra laestructura condicional, repetitiva, etc.

Consejo: No abusar del uso de las variables definidas en unbloque. Restringidlo, por ahora, a variables auxilia-res y contadores

Funciones y ClasesFunciones → Ámbito de un dato 237

Debemos tener cuidado con la declaración de variables con igual nombreque otra definida en un ámbito superior.Prevalece la de ámbito más restringido → prevalencia de nombre (namehiding)

��� ��������� �������� �����

��� ����� �� �� ���� ���

���� � ��

� �� ��������

��� ���� � �� �� �� ���� ���

���� � ���� � ���� �� �� ���� ���

������

����� �����

��� �������

��� ��� � ! ��������

������� � ��������� ����������

"��� �� #���� ���� # �� ��� �� # � # �� ��������

�� $����� � �������� �� ��%����&

�� ���� ���� � � &��

Page 126: Fundamentos de Programacion

Funciones y ClasesFunciones → Ámbito de un dato 238

� Lo nuevo (muy malo):

Datos globales (global data)

� Son datos declarados fuera de las funciones y del main.

� El ámbito de los datos globales está formado por todas las fun-

ciones que hay definidas con posterioridad

El uso de variables globales permite que todas las funciones las puedanmodificar. Esto es pernicioso para la programación, fomentando la apari-ción de efectos laterales (side effects).

Ejemplo. Supongamos un programa para la gestión de un aeropuerto.Tendrá dos funciones: ����������� y ������ ����. El primero contro-la las cintas transportadoras y como máximo puede gestionar 50 maletas.El segundo controla los vuelos en el área del aeropuerto y como máximopuede gestionar 30. El problema es que ambos van a usar el mismo datoglobal �� para representar dichos máximos.

Funciones y ClasesFunciones → Ámbito de un dato 239

�������� ��� ����

����� ��������� ����

��� ���� �� �� ������ ������� ����

�� ���� �����

��� ����������������

��� !"� �� � #$%��� ���� ��#

�% �&���������'����� ����

(������� �������)

����

'����� $�� ����������������

*

��� +�� ���������

�% �&�������'����� ����

(������� �����)

�����

'����� $�� ��������������

���� ���� � ���

*

*

��� �������

��� ,"� �� � �-��� �.�� �� �����

���� ���� %�����

/0��� �#���� ������

���������������� �� $%��� ���� ��� ��� !"

+�� ���������

*

Page 127: Fundamentos de Programacion

Funciones y ClasesFunciones → Ámbito de un dato 240

El que un lenguaje como C++ permita asignar un ámbito global a unavariable, no significa que esto sea adecuado o recomendable.

El uso de variables globales puede provocar gravesefectos laterales, por lo que su uso está completamente

prohibido.

Nota. El uso de constantes globales es menos perjudicial ya que, si nopueden modificarse, no se producen efectos laterales

Funciones y ClasesFunciones → Las funciones y los principios de programación 241

III.1.5. Las funciones y los principios de progra-mación

¿Cuándo podemos decir que hemos construido software de calidad?

� No debe tener errores.

� Debe ser fácil de mantener y reutilizar en otros sitios.

Para conseguirlo, debemos respetar ciertas normas o principios de pro-gramación. Hemos visto el principio transversal de sencillez (página 156)y el de una única vez -no duplicar código- (página 88)

Los lenguajes de programación proporcionan mecanismos de encapsu-lación (encapsulation) de código, para no tener que repetirlo.

Las funciones son un mecanismo (pero no el único) de encapsulación.Definimos una única vez la función y la llamamos donde sea necesario,con distintos parámetros actuales. Esto hace que el código sea:

� Menos propenso a errores

Después de un ��������� del código a repetir, si queremosque funcione con otros datos, debemos cambiar una a una to-das las apariciones de dichos datos, por lo que podríamos ol-vidar alguna.

� Más fácil de mantener

Ante posibles cambios futuros, sólo debemos cambiar el códi-go que hay dentro de la función. El cambio se refleja automáti-camente en todos los sitios en los que se realiza una llamadaa la función

Page 128: Fundamentos de Programacion

Funciones y ClasesFunciones → Las funciones y los principios de programación 242

Otro principio esencial de programación es el siguiente:

Principio de Programación:

Ocultación de información (Information Hiding)

Al usar un componente software, no deberíamos tenerque preocuparnos de sus detalles de implementación.

El ámbito de los datos definidos en las funciones es un mecanismo (perono el único) para cumplir el principio de ocultación de información. En lallamada a una función, por ejemplo:

�������� � �������� ����� ������

sólo nos preocupamos de saber su nombre y cómo se utiliza (los pará-metros y el valor devuelto), pero no de saber cómo realiza su tarea.

¿Qué pasaría si los datos locales fuesen accesibles desde otras funcio-nes?

� Código propenso a errores, ya que podríamos modificar los datoslocales por accidente y provocar errores (lo mismo que ocurre conlos datos globales)

� Código difícil de mantener, ya que no podríamos cambiar la defini-ción de una función A, suprimiendo, por ejemplo, alguna variablelocal de A a la que se accediese desde otra función B.

Ampliación:A lo largo del curso y de la carrera, se irán introduciendo otros principios.Por ejemplo, una forma más general de una única vez se denomina DRY (Donot Repeat Yourself) y hace alusión a no repetir (además de comportamien-tos) otros conceptos como por ejemplo restricciones lógicas.

Funciones y ClasesFunciones → Las funciones y los principios de programación 243

Ejemplo. Recordad la definición de la función ����������� vista en lapágina 219

��� �������������� �� ��� ��

���� ��������������������� � ��������������

Es una implementación ineficiente, pues la fracción puede simplificarse.

a!

b!(a − b)!=

a(a − 1) · · · (a − b + 1)(a − b)!

b!(a − b)!=

a(a − 1) · · · (a − b + 1)

b!

Cambiemos la implementación de la función como sigue:

��� �������������� �� ��� ��

��� �������� �������

������� � ��

������ � ��

�� ��� ��� � ���� � ����

������ � ���������

������� � ���������������

���� ���������������

Al no cambiar la cabecera de la función, no tenemos que cambiar nadaen ningún sitio en el que sea llamada.

Page 129: Fundamentos de Programacion

Funciones y ClasesFunciones → Las funciones y los principios de programación 244

En la siguiente sección introducimos las clases. Proporcionan un meca-nismo complementario que permite cumplir los principios de programa-ción:

� Una única vez: Encapsulando datos y funciones en un mismo sitio.

� Ocultación de información: Definiendo nuevas reglas de ámbito pa-ra los datos.

Funciones y ClasesClases → 245

III.2. Clases

III.2.1. Motivación. Clases y Objetos

Las funciones pueden usarse desde cualquier sitio tras su declaración(puede decirse que son funciones globales (global functions)) y se co-munican con el resto del programa a través de sus parámetros y del re-sultado que devuelven (siempre que no se usen variables globales)

La Programación procedural (Procedural programming) establece técni-cas para el correcto diseño de una solución utilizando funciones.

El diseño de una solución a un problema de complejidad mediana se com-plica al tener que trabajar con multitud de funciones hermanas, todas almismo nivel.

La Programación dirigida a objetos (Object oriented programming) (PDO)surgió para resolver este problema, abordando la solución a un problemade programación de una forma distinta.

En vez de identificar tareas a resolver (funciones), en PDO seidentifican objetos que contienen datos y funciones. Las funcio-nes contenidas en objetos se les llama métodos (methods). Éstos

actúan sobre los datos miembro

Page 130: Fundamentos de Programacion

Funciones y ClasesClases → Motivación. Clases y Objetos 246

Sobre los nombres:

� Programación estructurada (Structured programming). Metodolo-gía de programación en la que la construcción de un algoritmo sebasa en el uso de las estructuras de control vistas en el tema II,prohibiendo, entre otras cosas, el uso de estructuras de saltos ar-bitrarios del tipo ����

� Programación modular (Modular programming): Cualquier metodo-logía de programación que permita agrupar conjuntos de senten-cias en módulos o paquetes.

� Programación procedural (Procedural programming). Metodologíade programación modular en la que los módulos son las funciones.

Muchos libros denominan, desafortunadamente, a la programaciónprocedural, programación estructurada.

� Programación orientada a objetos (Object oriented programming).Metodología de programación modular en la que los módulos sonobjetos.

Nota. No se usa el término programación funcional (functional program-ming) para referirse a la programación con funciones, ya que se acuñópara otro tipo de programación, a saber, un tipo de programación decla-rativa (declarative programming)

Funciones y ClasesClases → Motivación. Clases y Objetos 247

Objeto: una ventana en Windows

� Datos: posición esquina superior izquierda, altura, anchura, es-tá_minimizada

� Métodos: Minimiza(), Maximiza(), Agranda(int tanto_por_ciento),etc.

Objeto: una cuenta bancaria

� Datos: identificador de la cuenta, saldo actual, descubierto que sepermite

� Métodos: Ingresa(double cantidad), Retira(double cantidad), etc.

Objeto: un triángulo rectángulo

� Datos: los tres puntos que lo determinan A, B, C

� Métodos: ObtenerHipotenusa(), ObtenerSegmentoAB(), etc.

Objeto: una fracción

� Datos: Numerador y denominador

� Métodos: Simplifica(), Súmale(Fracción otra_fracción), etc.

Page 131: Fundamentos de Programacion

Funciones y ClasesClases → Motivación. Clases y Objetos 248

Una clase (class) es un tipo de dato definido por el programador pararepresentar una entidad, es decir, objetos que comparten una serie decaracterísticas.

Un objeto (object) es un dato cuyo tipo de dato es una clase. También sedirá que un objeto es la instancia (instance) de una clase.

����� �������

��

� � ��� ��

������� � ��������� ��� ���������������

������� ������������� ��� ���������������

����� ��� ���� ����� �� �� �����

��

� � ��� ��

��� ���� ����� � ����� ��� �� �� � ������

��� ���� ����� �������� ��� �� �� ���� ������

Los objetos � ����� �� y �������� �� existirán mientras esté ejecutándo-se ��� .

Funciones y ClasesClases → Encapsulación 249

III.2.2. Encapsulación

� En Programación Procedural, la encapsulación se materializa al in-cluir en el mismo componente software (la función) un conjunto deinstrucciones.

� En PDO, la encapsulación se materializa al incluir en el mismo com-ponente software (la clase) los datos y los métodos (funciones queactúan sobre dichos datos)

Una clase se compone de:

� Datos miembro (data member): son datos definidos en la clase.

Todos los objetos que pertenecen a una misma clase contienendichos datos, pero tendrán un valor distinto en cada objeto.

Determinan el estado (state) de cada objeto.

� Funciones miembro (member functions) o métodos (methods): sonfunciones que pertenecen a la clase.

La definición de los métodos es la misma para todos los objetos.

Determinan el comportamiento (behaviour) de todos los objetos dela clase.

Page 132: Fundamentos de Programacion

Funciones y ClasesClases → Encapsulación 250

����� �������

�����

��� �����

���� ����������

����

��

��� ������

������� ����������

�������������� � ��

���������������������

����

Funciones y ClasesClases → Encapsulación 251

Page 133: Fundamentos de Programacion

Funciones y ClasesClases → Encapsulación 252

III.2.2.1. Datos miembro

Desde el ���� o desde otros objetos, accederemos a los datos y métodosde los objetos a través del nombre del objeto, un punto y el nombre deldato o método.

Los datos miembro representan el estado del objeto en cada momento,es decir:

� Cada objeto tiene sus propios datos miembro.

� Los datos miembro no se comparten entre objetos.

Ejemplo. Cuenta bancaria.

Nota. Esta clase tiene problemas importantes de diseño que se irán arre-glando a lo largo de este tema.

������ ��� �����

������ � ������

� ��� ��� ��� ��

��� ��������������

�������

���� ����

����� �����������

��

��� �������

������������� ������

����� �����������������

���� ���� �� �������

���� �� � �!������ ���������� � � ����� � �� ��������

��� �� �����������������

Funciones y ClasesClases → Encapsulación 253

����������������� ������������������

�� � ���� ����������� ��� �� �����������������

���� �� ����������� ������ ������� � ��������� ��

��� �� ��������

����������� ��������

���� �� ����������� ������ � ��������� ��

��� �� ��������

����������� ����������� � ��������

���� �� ����������� ������ � �������� ��

��� �� ��������

����������� ����������� � ��������

�������������� ������������

���������������� !!!!� �� �� "� ����� � ������

Page 134: Fundamentos de Programacion

Funciones y ClasesClases → Encapsulación 254

III.2.2.2. Métodos

� El comportamiento de los métodos es el mismo para todos los ob-jetos. Pueden modificar el estado del objeto sobre el que actúan.

� Los datos miembro se comportan como datos globales dentro delobjeto, por lo que son directamente accesibles desde cualquier mé-todo definido dentro de la clase y no hay que pasarlos como pará-metros a dichos métodos.

Por tanto, ¿los métodos de las clases en PDO suelen tener menosparámetros que las funciones globales usadas en ProgramaciónProcedural?

¡Sí, por supuesto!

Pero habrá muchos casos en los que los métodos necesiten infor-mación adicional que no esté descrita en el estado del objeto (porejemplo, la cantidad a ingresar o retirar).

Funciones y ClasesClases → Encapsulación 255

Ejemplo.

����� ������������ �� �� �����

�������

������ ������

����� �������������

���� �������������� ��������

����� � ����� � ��������

���� ����������� ��������

����� � ����� � ��������

��

�� !�����

������������ ���"������ �� �� �� ��#��

������������ ���"������ �� �� ��� ��#��

���"�����$����� � %&�

���"�����$������������ � '&(&&&)*+'�

���"�����$��������(+��

���"�����$����� � ,)&�

���"�����$������������ � '&,&&*+)('�

���"�����$��������*+��

���"�����$ �����,+��

$$$$$$$$$$$

Page 135: Fundamentos de Programacion

Funciones y ClasesClases → Encapsulación 256

Para representar las clases se utiliza una caja con el nombre de la clase,debajo los datos miembro y debajo otra caja con los métodos. Pondre-mos un signo � para indicar que son públicos (posteriormente se veránlos privados)

Funciones y ClasesClases → Encapsulación 257

Ejemplo.

����� ������� � � ���

���� ��

������ ���� ���� ���� ����

������ ��� �����

���� �������� ����!���� ���� "

���� ����!���� ������

#

#�

�� ���

������� � � �� ���������

��������$��� % &$'�

��������$��� % ($)�

��������$��� % '$(�

��������$��� % �$&�

��� ** +,��� �� ��� ������ % + ** ��������$��� �����

Page 136: Fundamentos de Programacion

Funciones y ClasesClases → Encapsulación 258

Ejercicio. Definir sendos métodos ���������������� y �������� ������

para trasladar un segmento un número de unidades.

Funciones y ClasesClases → Encapsulación 259

� Notación

Usaremos nombres para denotar las clases y verbos para los métodos.

No existe un consenso entre los distintos lenguajes de programación,a la hora de determinar el tipo de letra usado para las clases, objetos,métodos, etc. Nosotros seguiremos el siguiente:

� Tanto los identificadores de las clases como de los métodos empe-zarán con una letra mayúscula.

Si el nombre es compuesto usaremos la primera letra de la palabraen mayúscula: ������������

� Los identificadores de los objetos, como cualquier otro dato, em-pezarán con minúscula.

Si el nombre es compuesto usaremos el símbolo de subrayado pa-ra separar los nombres: ��������� �����

Page 137: Fundamentos de Programacion

Funciones y ClasesClases → Encapsulación 260

Ejemplo. Controlemos ingresos únicamente positivos y retiradas de fon-dos inferiores al saldo.

�������� ��� ����

�������� �� ����

����� ��������� ����

����� ����������� ���

�������

����� �����

�� ��� ����������� �

��

��� �������

����������� �� �������

����� ��� ��� ��� ����

����������� � �

��� �� ��� ���

�� ���� ��� �

�������!�� ������� ����

��� �� ��� ����

�� � ��� ���� "" ��� ���������������

�������#��� �� ��� �����

Cada vez que realicemos un ingreso o retirada de fondos, habrá que rea-lizar las anteriores comprobaciones.

Solución: Lo programamos únicamente una vez dentro del método:

����� ����������� ���

Funciones y ClasesClases → Encapsulación 261

�������

���� ����

������ �����������

��� ����������� ����������

�� ��������� � ��

���� � ���� � ��������

��� ���������� ����������

�� ��������� � � �� �������� � �����

���� � ���� ��������

��� !������

"����#������� �����

���� �����$ �������

�����%���� � �

��� �� �����

�����%�������������

��� �� �������

�����%��������������

�Los métodos permiten establecer la política de acceso alos datos miembro.

Page 138: Fundamentos de Programacion

Funciones y ClasesClases → Encapsulación 262

III.2.2.3. Llamadas entre métodos dentro del propio objeto

Ya sabemos cómo ejecutar los métodos de un objeto desde fuera delobjeto.

¿Pero pueden ejecutarse desde dentro del propio objeto? Por supuesto.

Todos los métodos de un objeto pueden llamar a los métodos del mismoobjeto. La llamada se realiza por el nombre del método, sin anteponer elnombre del objeto.

Funciones y ClasesClases → Encapsulación 263

Ejemplo. Aplicar un interés a la cuenta bancaria.

����� ������������ �� �� �����

�������

������ ������

����� �������������

���� ��������������������� ��� �������������

������� ������ ������������ � !""#"��

$

���� �������������� ��������

�� �������� % "�

����� & ����� ' ��������

$

���� (����������� ��������

�� �������� % " )) ������� � ������

����� & ����� � ��������

$

$�

�� *�����

������������ ���������� �� �� �� ��+��

������������ ���������� �� �� ��� ��+��

���������#����� & ,"�

���������#������������ & -"."""/01-�

���������#��������.1��

���������#����������������������/��

��� �� ���������#������ �� �," ' .1� !#"/

$

Page 139: Fundamentos de Programacion

Funciones y ClasesClases → Encapsulación 264

Ejercicio. Implementar el método �������� para que traslade el segmentotanto en horizontal como en vertical.

����� ��� ���������

�������

����� ���� ���� ���� ����

����� ���� �����

� ��� � � ����� ! ����"���� ! ���� #

���� ! ����"���� ! ������

$

%��� ��������&���'�� �������� ���������

��� ( ��� # ��������

��� ( ��� # ��������

$

%��� ��������)� ���������� ���������

��� ( ��� # ��������

��� ( ��� # ��������

$

%��� ��������� �� ** +� %� ���� �

** � ,���'�� ��

$

$�

Funciones y ClasesClases → Ocultación de información 265

III.2.3. Ocultación de información

� En Programación Procedural, la ocultación de información se con-sigue con el ámbito local a la función (datos locales y parámetrosformales).

� En PDO, la ocultación de información se consigue con el ámbito lo-cal a los métodos (datos locales y parámetros formales) y ademáscon el ámbito ������� en las clases, tanto en los datos miembrocomo en los métodos.

Ampliación:En muchos textos académicos (no digamos en la web) suelen confundirselos términos encapsulación y ocultación de información. El término encap-sulación también suele utilizarse en un contexto más restrictivo para referir-se a la encapsulación ofrecido por la PDO. Puede verse una referencia muycompleta en:���������� ������ �����������

Page 140: Fundamentos de Programacion

Funciones y ClasesClases → Ocultación de información 266

III.2.3.1. Ámbitos público y privado

Al declarar los miembros de una clase, se debe indicar su ámbito (scope),es decir, desde dónde se van a poder utilizar:

� Ámbito privado (Private scope).

– Se especifica con la declaración ������� (este es el ámbito pordefecto si no se pone nada)

– Los miembros privados sólo se pueden usar desde dentro delobjeto. No son accesibles desde fuera.

– Desde dentro de cualquier método del objeto se acceden porsu nombre.

� Ámbito público (Public scope).

– Se especifica con la declaración ����

– Los miembros públicos son visibles dentro y fuera del objeto.

– Desde dentro de cualquier método del objeto se acceden porsu nombre y desde fuera, hay que anteponer el nombre delobjeto seguido de un punto.

� Otros ámbitos que no se verán en esta asignatura.

Acceso a los datos miembro:

� Todos los métodos de una clase A (independientemente de si sonpúblicos o privados) , pueden acceder a los datos miembro de A(independientemente de si son públicos o privados).

� Todos los métodos de una clase A (independientemente de si sonpúblicos o privados), pueden llamar a los métodos de A (indepen-dientemente de si son públicos o privados).

Funciones y ClasesClases → Ocultación de información 267

En la representación gráfica de las clases con cajas se utiliza un signopara los miembros privados. La gráfica de la izquierda sería una represen-tación con el estándar UML (Unified Modeling Language) puro. Nosotrosusaremos una adaptación como aparece a la derecha.

Page 141: Fundamentos de Programacion

Funciones y ClasesClases → Ocultación de información 268

¿El ámbito ������ rompe la ocultación de información?

� No, si hablamos de métodos

� Sí, si hablamos de datos miembro.

Por lo tanto habrá que evitar el ámbito público en los datos miembro.Veamos ejemplos que lo justifiquen.

Ejemplo. ¿Cual es el problema en este código?

��� ����

���������� ������

���������� � ���

��������������������

���������� � ���������� � ���

Estamos permitiendo acceder al saldo de dos formas, directamente a tra-vés del dato miembro o a través del método ������. Por tanto, corremosel peligro de poner

���������� � !"����

El programador tiene la libertad de hacerlo de las dos formas (la mala yla buena)

Solución: Cambiamos el ámbito público de los datos miembro a privado.Pero, entonces, debemos añadir:

� Métodos para modificar los datos miembro (aquellos que sedeseen modificar desde fuera)

� Métodos para obtener el valor actual de los datos miembro (aque-llos a los que se desee acceder desde fuera)

Funciones y ClasesClases → Ocultación de información 269

Esto nos obliga a escribir más líneas de código, pero es conveniente quelo hagamos, ya que así controlamos desde dónde se puede manipular elvalor de los datos con los que trabajamos (algo que nos será muy útilpara localizar posibles errores).

Salvo casos muy justificados, no definiremos datosmiembro públicos. Siempre serán serán privados.

El acceso a ellos desde fuera de la clase se hará a travésde métodos públicos de la clase.

Page 142: Fundamentos de Programacion

Funciones y ClasesClases → Ocultación de información 270

Funciones y ClasesClases → Ocultación de información 271

�� ���������� �� ����� �� ����������

�����������������

��� �� �������

����������������������

���� �� �������������� �� �� �������� ��� � �� ������

���� �� �������������!���������

Page 143: Fundamentos de Programacion

Funciones y ClasesClases → Ocultación de información 272

Lo que C++ permite:

Lo que nosotros haremos:

Interfaz (Interface) de una clase:Es el conjunto de métodos públicos de dicha clase.

Funciones y ClasesClases → Ocultación de información 273

Ejemplo. Vamos a prohibir la construcción de segmentos degenerados(con un solo punto).

����� ������� � � ���

���� ��

������ ���� ���� ���� ����

���������

��

�� ���

������� � � �� ���������

������ �� ������� ��� �� �����������

������ ������� ��� �����������

��������

�!��� ������� �� "" ������� �� ##

�� ���������� "" �������������

������������ " �� ������� ���

������������ " �� �����������

������������ " ������� ���

������������ " �����������

�������

Problema: La comprobación de igualdad de coordenadas la debemos ha-cer SIEMPRE, antes de crear el objeto segmento. Esto, obviamente violael principio de una única vez.

Solución: Lo encapsulamos en un método público ��$��������� queaccederá a los datos privados.

%� � ��$���������������� �� ������� ��� ������ �� �����������

������ ������� ��� ������ �����������

Al ser ahora los datos privados, debemos proporcionar los métodos quedevuelvan su valor.

Page 144: Fundamentos de Programacion

Funciones y ClasesClases → Ocultación de información 274

����� ������� � � ���

�� ����

������ ���� ���� ���� ����

���� ��

�� � ������������������� �� ������� ���

������ �� �����������

������ � ������� ���

������ � ���������� �

� �!��� ������� �� "" � ������� �� ##

�� ���������� "" � ���������� �

��� " �� ������� ���

��� " �� �����������

��� " � ������� ���

��� " � �����������

$

$

������ %� ��&��� ��� �

���� ����

$

������ %� ��%������� �

���� ����

$

������ ' ��&��� ��� �

���� ����

$

������ ' ��%������� �

���� ����

$

( )�� �*���� )�� ��� +�������� +�������,�� -��� � +�������.�� ���

� ���/� 0

$�

Funciones y ClasesClases → Ocultación de información 275

��� �������

����� ������� ���������� ����������������

�������������������������� ���� ���� �����

�������������������������������� ���� ���� �����

���� ! ! ����������"����#���������

����������$�������%���&��������

���� ! ! ����������"����#���������

'

Observad que a través del método �����������, obligamos al progra-mador a asignar un valor a los cuatro puntos a la misma vez. En esteejemplo, parece que es lo adecuado ya que el estado de un segmentorequiere, al menos, de la existencia de los dos puntos (4 valores).

Page 145: Fundamentos de Programacion

Funciones y ClasesClases → Constructores 276

III.2.4. Constructores

III.2.4.1. Constructores por defecto (sin parámetros)

Revisemos el código de la página 270.

������������ �������

� ���� ���� �

����������������� �� ���� ��� ���� ���� ���� �

Necesitamos inicializar saldo a 0.

Todas las acciones que queramos realizar en el momentode construir un objeto, se incluyen en el constructor (cons-tructor) de la clase.

� Se define dentro de la clase, en la sección �����.

� Puede verse como un método especial � � que se llama, obligato-riamente, igual que la clase. Pero no se pone � �.

� Cuando se cree un objeto, el compilador ejecutará las instruccio-nes especificadas en el constructor.

� Se le pueden pasar parámetros. Si no se le pasan parámetros, se ledenomina constructor por defecto (default constructor).

Funciones y ClasesClases → Constructores 277

����� ������������

�������

������ ������

����� �������������

�������

�������������� �� �� ���������

����� � ��

��� ���� �� � ���� �� ������!

��

�� ������

������������ ������

��� �� �����"#������� �� $������ � ���

Una alternativa para la inicialización de los datos miembro es utilizarla lista de inicialización del constructor (constructor initialization list).Son construcciones del tipo ����%�������! ������� �������!� separa-das por coma, antes del paréntesis del constructor, y con dos puntos alinicio:

�������

��������������

� �������� �� ����� � ��

Esta es la forma recomendada en C++ de inicializar los datos miembro.

Page 146: Fundamentos de Programacion

Funciones y ClasesClases → Constructores 278

Ampliación:Con los tipos de datos integrados (���� ����, etc) no hay diferencia en-tre la asignación ���� � y la inicialización �������. Pero cuando losdatos miembro son objetos, sí la hay. Consultad, por ejemplo:���������������������������������������������

En la mayor parte de los lenguajes (Java, C#, etc) no hay lista de iniciali-zación, ya que el tratamiento de los datos miembro en dichos lenguajes esdistinto. En C++, al declarar dentro de una clase un dato miembro de otraclase, se crea el objeto automáticamente. En los otros lenguajes, no.En Java, por ejemplo, para dar un valor inicial a los datos miembro se utili-zan los inicializadores de instancia (instance initializers).

Funciones y ClasesClases → Constructores 279

Si no definimos ningún constructor, C++ proporciona un constructoroculto -siempre sin parámetros- que, simplemente, no hace nada, peropermite crear objetos. A este constructor se le suele denominar cons-tructor de oficio. No confundir con constructor por defecto que es todoaquel constructor que no tiene parámetros.

III.2.4.2. Constructores con parámetros

Si queremos obligar a crear un objeto con ciertos valores iniciales,

podemos añadir parámetros al constructor:

����� ������������

�������

������ ������

����� �������������

�������

������������������� ��������������

���������������������

��� ���� �� ������ �� �������

��

�� ������

�� ������������ ������ � !���� ���������"�

�� #� $���� �������� ������� �� ���������%

�� �&& �� ����������� �� ��������� ��� ������

������������ ����������'�� �� (���� ������� � '

������������ ����������)*'���� (���� ������� � )*'

Page 147: Fundamentos de Programacion

Funciones y ClasesClases → Constructores 280

Ejemplo. Si queremos, podemos añadir parámetros al constructor delejemplo del segmento:

����� ������� � � ���

�� ����

������ ���� ���� ���� ����

���� ��

������� � � ��������� �� ������� ��� ������ �� �����������

������ � ������� ��� ������ � ������������

�� ������������ ������� ��� �� �����������

� ������� ��� � ������������

!

"#��������� �� ��� � $ �� �� ����������%

�� � �� ���������������� �� ������� ��� ������ �� �����������

������ � ������� ��� ������ � ������������

� �&��� ������� �� '' � ������� �� ((

�� ���������� '' � �������������

��� ' �� ������� ���

��� ' �� �����������

��� ' � ������� ���

��� ' � �����������

!

!

")� ���� �� �*���� � ���+�%

!�

�� ���

������� � � �� ��������� ,, "- )���� ���� ��� $

������� � � �� �����������./0� 1/2� 0/1� �/.�� ,, 34

������� � � �� �����������./0� 1/2� ./0� 1/2��

,, �� ���� �� ��5��

,, ���� ��� ���� � ����� � ��

,, � ����� �� ���� ��� 6���� � �������

Funciones y ClasesClases → Constructores 281

En la página 277, indicábamos que se recomienda usar la lista de inicia-lización. Sin embargo, en el ejemplo anterior hemos usado una llamada aun método de la clase (�����������) en vez de la lista de inicialización.Esto es correcto ya que hay ciertas condiciones (establecidas en el con-dicional del método �����������) bajo las cuales no queremos dar unvalor inicial a los datos miembro.

Esto nos lleva a otra pregunta: ¿Debemos permitir crear un objeto cuyoestado no sea válido? Es decir, que los datos miembro esenciales delobjeto no tengan un valor asignado. Realmente no deberíamos permitirlo.La solución pasará por lanzar una excepción, tal y como se verá en eltema V.

���� ����������� ������ ����������� ������ ��������������

������ ��������� ������ �������������

�� � ���������� �� �������� ��

������������� �� ��������������

��� � �����������

��� � ��������������

��� � ���������

��� � ������������

���

!��"� �� ����#��$�%

Page 148: Fundamentos de Programacion

Funciones y ClasesClases → Constructores 282

III.2.4.3. Sobrecarga de constructores

¿Y si queremos permitir la creación de un objeto de varias formas distin-tas? Podemos usar varias versiones del constructor, pero deben diferen-ciarse en:

� O bien en el número de parámetros

� O bien en el tipo de los parámetros

����� ������������

�������

������ ������

����� �������������

�������

��������������

���������

������������������� ��������������

���������������������

��� ���� �� ������ �� �������

��

�� ������

������������ ������ �������! "����� ���������

������������ ������������� �������! #������ ���������

������������ ����������$%��� �������! #������ ���������

Funciones y ClasesClases → Constructores 283

En cualquier caso, para no complicar la clase ������������, en las pá-ginas siguientes optaremos por el uso de un único constructor, al quepasaremos el saldo inicial de la cuenta. El código completo de la clasequedaría:

����� ������������

������

������ ������

���� ����������

������

������������������� �����������

������������������

���� ������������

���� ����������

��� ������������������ �����������������

��������� � �����������������

������ �������

���� ������

��� ������������� ��������

� �������� � ��

����� � ����� ��������

��� !���������� ��������

� �������� � � "" ������� # ������

����� � ����� $ ��������

��

Page 149: Fundamentos de Programacion

Funciones y ClasesClases → Constructores 284

Ampliación:Otra forma de implementar la clase anterior sería utilizando un constructorcon un parámetro por defecto/opcional (default/optional parameter). Sim-plemente, en la declaración de un método o constructor, se especifica unvalor concreto para un parámetro. Éste será el valor que tomará el paráme-tro (de ahí el nombre por defecto) en el caso de que no se pase nada comoparámetro actual.

����� ������������

�� ����� ��� ������ �

������������������� ������������� � ��

���������������������

���������

��

�� ������

������������ ������� ����� �� �������

������������ ������ �� �������� ������������� � �

Nota. Los parámetros por defecto no están disponibles en Java, y hay querecurrir a la sobrecarga de constructores, o utilizar recursos más avanzadoscomo el patrón de diseño Builder.

Ampliación:Supongamos que dos sobrecargas del constructor tienen en común un con-junto de instrucciones. ¿Puede un constructor llamar al otro como si se tra-tasen de métodos usuales? Lamentablemente, en C++ no se podía hacer,por lo que había que definir un método privado con las instrucciones quese repiten y llamarlo dentro de los constructores. Afortunadamente, eso hacambiado en el nuevo estándar de C++ 11 y un constructor sí puede llamara otro.Por cierto, cuando se vea herencia, un constructor de una clase derivada sípuede llamar al constructor de la clase base. Es más, es obligatorio cuandoel constructor de la clase base tiene parámetros.Una página interesante FAQ sobre constructores en C++:!����"""������!��������##$��%$���������!��&��%$'���

Funciones y ClasesClases → Diseño de una clase 285

III.2.5. Diseño de una clase

Conceptos fundamentales vistos hasta ahora en la construcción de unaclase:

� Ámbitos ������� y ����.

� Encapsulación de datos y métodos dentro de una clase.

Ahora bien, ¿cuanto metemos en una clase? ¿Qué preferimos: menosclases que hagan muchas cosas distintas o más clases que hagan cosasconcretas? Por supuesto, las segundas.

III.2.5.1. Principio de Responsabilidad Única

Principio en Programación Dirigida a Objetos.

Principio de Responsabilidad Única

(Single Responsability Principle)

Un objeto debería tener una única responsabilidad, la cualdebe estar completamente encapsulada en la definición

de su clase.

A cada clase le asignaremos una única responsabilidad. Esto facilitará:

� La reutilización en otros contextos

� La modificación independiente de cada clase (o al menos paquetesde clases)

Page 150: Fundamentos de Programacion

Funciones y ClasesClases → Diseño de una clase 286

Heurísticas:

� Si para describir el propósito de la clase se usan más de 20 pala-bras, puede que tenga más de una responsabilidad.

� Si para describir el propósito de una clase se usan las conjuncio-nes y u o, seguramente tiene más de una responsabilidad.

Ejemplo. La siguiente clase tiene dos responsabilidades: gestionar las

operaciones básicas de movimientos de saldo Y gestionar las transac-

ciones

Funciones y ClasesClases → Diseño de una clase 287

Mejor usamos dos clases:

� Responsabilidad de ������������: gestionar las operaciones bá-sicas de movimientos de saldo.

� Responsabilidad de ������� �: gestionar una transacción banca-ria.

Page 151: Fundamentos de Programacion

Funciones y ClasesClases → Diseño de una clase 288

Ejemplo. ¿Es correcto este diseño?:

����� ������������

�������

������ ������

����� �������������

�������

������������������� ��������������

���������������������

����� ��������������

����� �������������

���� �������������������� �������������������

������������ � �������������������

������ �������

����� ������

���� ��������������

��� �� !������ � �� ������

���� ���������������������

��� �� !������������� � �� �������������

��

La responsabilidad de esta clase es gestionar los movimientos de una

cuenta bancaria Y comunicarse con el dispositivo de salida por defec-

to. Esto viola el principio de única responsabilidad. Esta clase no podráreutilizarse en un entorno de ventanas, en el que ��� no funciona.

Funciones y ClasesClases → Diseño de una clase 289

Jamás mezclaremos en una misma clase métodos decómputo con métodos que accedan a los dispositivos de

entrada/salida. La violación de esta norma supone elsuspenso automático.

Nota. El principio de responsabilidad única se viola con mucha más fre-cuencia de lo que sería deseable. La separación básica de C-E/S no serespeta en multitud de libros de texto.

¿Qué hacemos entonces para notificar que ha habido un problema en laejecución de un método?

���� �������� �� ����������

�� ��������� � ��

���� � ���� � ���������

�� � �� ��������� � ������ ���������

Esto nunca lo haremos. Ningún método de la clase � ����������� debeacceder al periférico de entrada o salida.

Resolveremos este problema cuando veamos el tratamiento de errores yexcepciones en el tema V.

���� �������� �� ����������

�� ��������� � ��

���� � ���� � ���������

������� �!��"��

Page 152: Fundamentos de Programacion

Funciones y ClasesClases → Diseño de una clase 290

III.2.5.2. Cohesión de una clase

Un concepto ligado al anterior es el de cohesión (cohesion), que midecómo de relacionadas entre sí están las funciones desempeñadas por uncomponente software (paquete, módulo, clase o subsistema en general)

Por normal general, cuantos más métodos de una claseutilicen todos los datos miembros de la misma, mayor serála cohesión de la clase.

Ejemplo. Queremos gestionar la nómina de un trabajador.

� El salario base se calcula en función de su categoría laboral y delos años de antigüedad.

� El trabajador recibe un complemento por número de horas extra-ordinarias trabajadas. La cuantía por hora se calcula en función desu categoría laboral.

Puede apreciarse que hay grupos de métodos que acceden a otros gru-pos de datos miembro. Esto nos indica que pueden haber varias respon-sabilidades mezcladas en la clase anterior.

Tendremos que encapsular cada una de las responsabilidades (grupos)en clases distintas (este ejemplo se ve con detalle en el tema V)

����������

������� ���

Funciones y ClasesClases → Diseño de una clase 291

�����

������� ����

�������

Ampliación:Se han diseñado numerosas métricas de cohesión, es decir, medidas nu-méricas que cuantifican el grado de cohesión de un componente software.Buscad en Internet class cohesion measure o measure of cohesion. La ma-yor parte de estas medidas se construyen basándose en el número de datosmiembro a los que se accede desde los distintos métodos.

Page 153: Fundamentos de Programacion

Funciones y ClasesClases → Registros 292

III.2.6. Registros

En algunas (pocas) ocasiones, la clase que queremos construir es tansimple que no tiene métodos (comportamiento) asociados. Únicamentesirve para agrupar algunos datos.

����� ������

������

��� ��������

��� ��������

��

Para estos casos, usamos mejor un tipo específico proporcionado porC++ (también habitual en los lenguajes de programación): el tipo ������

������ ������

��� �������� �� �� �� ������ �� �����

��� ��������

��

Todos los datos miembro son públicos y se acceden con la notación pun-to, como en las clases.

��� �������

����� ����

����������� � ��

����������� � �

C++ también permite introducir datos privados e incluso métodos en unregistro, pero nosotros nunca lo haremos. Dejaremos el tipo ������ paraaquellos (pocos) casos en los que únicamente queremos agrupar algu-nos datos, sin un comportamiento asociado.

Funciones y ClasesClases → Datos miembro constantes 293

III.2.7. Datos miembro constantes

¿No sería deseable obligar a que en la creación de la cuenta, se le asigneun identificador y ya no se pueda cambiar? Pasamos el identificador alconstructor y suprimimos el método ��������������

�� ����������

�������

���� � � ���

������ ������������

��� ��

���������������� ����������������� ���� � � ������� �

�� ���� ������� ��

�����������������������������

� �

�� � !���� �������������� �� " ����� ���

#$�� !����� ������������ � ��� ������� %���� �� ��&�'

��

��� �����

������ �����������������

���� � �������� �������

��� ## ()��������� � ����������� �� ����� (�

�� '' �����������������

��� ## ()��������� ����� ���� �������� (�

�� '' ��������

��������� ���������������������� ���������

��� ## ()��������� ����� �������� (�

�� '' ��������

����*����������������

Page 154: Fundamentos de Programacion

Funciones y ClasesClases → Datos miembro constantes 294

���� �� ���������� � ���� � ��� � ��

��� �� ��� � �

����� ����� ���� � ��

���� �� ����������� �� � � �� ����� ��������� �����

���� �� ���� ��� � � �� ����� �� ������

���� �� �������

��������� ������

La solución anterior es adecuada, pero ¿no deberíamos obligar (además)a que el programador no pudiese cambiar por accidente (dentro de laclase ����� �� � ) el dato miembro privado ��������� ��?

Tenemos que declararlo como una constante.

Tipos de constantes:

� Constantes a nivel de objeto (object constants): Cada objeto deuna misma clase tiene su propio valor de constante.

� Constantes estáticas (static constants) o constantes a nivel de cla-se (class constants): Todos los objetos de una clase comparten elmismo valor de constante.

Funciones y ClasesClases → Datos miembro constantes 295

III.2.7.1. Constantes a nivel de objeto

Las constantes a nivel de objeto se declaran dentro de la clase y se

definen (se les asigna un valor) en el constructor (obligatoriamente en

la lista de inicialización). Cada objeto de una misma clase tiene su propiovalor de constante.

����� ������������

�������

������ ������

���� ����� �������������

�������

������������������ ������������������� ������ ��������������

����������������������

��������������������������������

���������� �����

������������ ! "�� ��� ���"� ## $���� ���������%� �&�

'''''''''''

## $� ����� (�)����������� �� *� ���������

��

�� ������

������������ ����������"+,-.,,/0-0,.,,,,.-12"� .,,��

'''''''''''

Page 155: Fundamentos de Programacion

Funciones y ClasesClases → Datos miembro constantes 296

Funciones y ClasesClases → Datos miembro constantes 297

����� ������� ���� ��

���� ������ �����������������

������

���� ������ ����������� �����

�������!������ �������" ������ � �������#

�����������������!�������#"

����������� ����!� �������#

$

$�

�� %���!#

������� �����&� �!'()" *(+#" � �����&� �!)(," -(.#�

�����&� �(���������������� / .(+� 00 ����� ��%�����1�

00 !���� � 2 � �#

�����&� �(����������� ���� / .(+� 00 ����� ��%�����1� !� �#

��� 33 �����&� �(����������������� 00 ����� ��%�����1�

00 !���� �#

��� 33 �����&� �(����������� ����� 00 �%��%� *(+

��� 33 � �����&� �(����������� ����� 00 �%��%� -(.

Page 156: Fundamentos de Programacion

Funciones y ClasesClases → Datos miembro constantes 298

III.2.7.2. Constantes estáticas (a nivel de clase)

En este caso, todos los objetos de una clase comparten el mismo valorde constante.

En UML, las constantes estáticas se resaltan subrayándolas.

Constantes estáticas NO enteras

� Se declaran dentro de la definición de la clase:

����� ����������� �

������ ����� ����� ��������� �

��

� Se definen fuera de la definición de la clase:

����� ����� ����������� ����������� � ����� �

Funciones y ClasesClases → Datos miembro constantes 299

����� �����������

� �����

���� ���� ������ �����������������

�������

���� ���� ������ ���������� !�����

"�

���� ������ ���������������������������� # $%&�

���� ������ ���������������������� !���� # '%(�

�� )���*+�

���������� �����,��- � ����,���

�����,��%���������� !���� # .%(� // � � ��)������0�

��� 11 �����,��%���������� !����� // �)� �)� '%(

��� 11 � ����,��%���������� !����� // �)� �)� '%(

�� es el operador de resolución de ámbito (scope resolution operator).Se utiliza, en general, para poder realizar la declaración de un miembrodentro de la clase y su definición fuera. Esto permite la compilación se-parada (separate compilation). Se verá con más detalle en el segundocuatrimestre.

Opinión personal:Separar la declaración y la definición rompe el principio DRY (Donot repeat yourself) ya que una modificación en la declaración obli-ga a una modificación de la definición (para mantener la coheren-cia). Esto era necesario antiguamente cuando se compilaba un con-junto de funciones o clases y se proporcionaba al cliente el ficherode texto con las cabeceras, pero no el código fuente, sino el com-pilado.Java utiliza variables de entorno para no tener que separar declara-ción y definición.En .NET se hace a través de referencias a los ensamblados quecontienen la definición de las clases.

Page 157: Fundamentos de Programacion

Funciones y ClasesClases → Datos miembro constantes 300

����� ������������

�������

������ ������

���� ����� �������������

���� ���� ����� �������

�������

������������������ ������������������� ������ ��������������

����������������������

������������������� � �������������������

����� ��������������

����� �������������

������ �������

����� ������

���� �������������� ��������

�� �������� � �

����� ! ����� � ��������

���� "����������� ��������

�� �������� � ## ������� $ ������

����� ! ����� % ��������

���� &�����������'����������� �������������

������� ������ ( ������������ ) * + ��

��

���� ����� �������������������� ! ,- .* ./*,�

�� 0�����

������������ ����������,.1 * *.23,� * ��

Funciones y ClasesClases → Datos miembro constantes 301

������ ����������� ������

������ �������� ���������

��� �� ����������� �� ����������� �� �� ������ ��

�� �� ����������� ������

��� �� ����������� ������� ������ � ��������� ��

�� �� ��������

������������� ���� ����������������� ������ ���������

��� �� ����������� ������� � ��������� ��

�� �� ��������

���� �����������������������

��� �� ����������� ������� � �������� ��

�� �� ���������

���� �����������������������

��� �� �������������� � � �� ���� ��������������������

��� �� ��� ���� � � �� ���� ������ �������

!

Ejercicio. ¿Qué cambios habría que hacer en la clase para permitir queuna cuenta pudiese tener un descubierto limitado?

Page 158: Fundamentos de Programacion

Funciones y ClasesClases → Datos miembro constantes 302

Ampliación:Podríamos haber definido un método privado y llamarlo en la lista de inicia-lización:

����� ������������

�������

������ ������

���� ����� �������������

���� ���� ����� �������

����� �������������������������� ��������������

����� ������ � ��������������

�������

������������������ �������������������

������ ��������������

����������������������

������������������������������������������������������

������������

��

���� ����� �������������������� !"#$%##&'!�

Esto resulta especialmente útil en aquellos casos en los que debemos rea-lizar inicializaciones más complejas que una simple asignación.

Funciones y ClasesClases → Datos miembro constantes 303

Constantes estáticas enteras

� O bien como antes:

����� ������������

�������

���� ���� �� �������������������

�������

���� ���� �� ������������� !����

"�

���� �� ��������������������������� !��� # $�

���� �� �������������������������������� # %�

� O bien se definen en el mismo sitio de la declaración:

����� ������������

�������

���� ���� �� ������������������ # $�

�������

���� ���� �� ������������� !��� # %�

"�

Ampliación:C++ también permite definir variables estáticas. Son variables que puedenmodificarse (y utilizarse) desde cualquier objeto de la clase en la que sedefinen. Al igual que ocurría con las variables globales cuando veíamos lasfunciones, debemos evitar este tipo de ámbito.Por otra parte, también se pueden definir métodos estáticos, que sólo pue-den actuar sobre datos estáticos. Este tipo de métodos son similares a lasfunciones globales, por lo que su uso debe estar limitado a aquellos (pocos)casos en los que es preferible la definición de dichos tipos de funciones, envez de la creación de una clase.

Page 159: Fundamentos de Programacion

Funciones y ClasesClases → Datos miembro constantes 304

Bibliografía recomendada para este tema:

� A un nivel menor del presentado en las transparencias:

– Capítulo 3 (para las funciones) y primera parte del capítulo 6(para las clases) de Deitel & Deitel

� A un nivel similar al presentado en las transparencias:

– Capítulos 4, 5 y 6 de Mercer

– Capítulo 4 de Garrido (sólo funciones, ya que este libro no in-cluye nada sobre clases)

� A un nivel con más detalles:

– Capítulos 10 y 11 de Stephen Prata.

Tema IV

Vectores y Matrices

Objetivos:

� Introduciremos los vectores de C++ que nos permitirán almacenarconjuntamente datos del mismo tipo.

� Los vectores de C++ son potentes pero peligrosos. Por ello, defini-remos nuestra propia clase �������� para trabajar con vectores deforma segura.

De esta forma, afianzaremos los conceptos vistos en el tema deClases.

� Construiremos distintos métodos de la clase ��������.

� Veremos varios algoritmos de búsqueda y ordenación.

� Introduciremos los vectores de varias dimensiones.

� Daremos un breve resumen de las clases estándar ����� y �����.

Autor: Juan Carlos Cubero.

Sugerencias: por favor, enviar un e-mail a ��������������������

Page 160: Fundamentos de Programacion

Vectores y MatricesFundamentos → 306

IV.1. Fundamentos

IV.1.1. Introducción

IV.1.1.1. Motivación

Un vector (array) es un tipo de dato, compuesto de un número fijo decomponentes del mismo tipo y donde cada una de ellas es directamenteaccesible mediante un índice.

Ejemplo. Leed notas desde teclado y decid cuántos alumnos superan lamedia

�������� ��� ����

����� ��������� ����

��� �������

��� �������

����� ����� ����� ����� ������

��� ���� ���� ��� �� ��

��� �� �����

��� ���� ���� ��� �� ��

��� �� �����

��� ���� ���� ��� �� ��

��� �� �����

����� � ����� ���� ����� ! �"#�

������ � #�

�$ ����� � ������

������ �

Vectores y MatricesFundamentos → Introducción 307

�� ������ ����

����������

�� ������ ����

����������

���� �� ������ ��������� � � �� ���� �� �����

���� �� ������� �� � ������ ��� �������� �� ��������

Problema: ¿Qué sucede si queremos almacenar las notas de 50 alum-nos? Número de variables imposible de sostener y recordar.

Solución: Introducir un tipo de dato nuevo que permita representar di-chas variables en una única estructura de datos, reconocible bajo unnombre único.

notas[0] notas[1] notas[2]

notas= 2.4 4.9 6.7

Page 161: Fundamentos de Programacion

Vectores y MatricesFundamentos → Introducción 308

IV.1.1.2. Declaración

<����> <�����������>�< ������������>��

� <����> indica el tipo de dato común a todas las componentes (ele-ments/components) del vector.

� < ������������> determina el número de componentes del vector,al que llamaremos tamaño (size) del vector. El número de compo-nentes debe conocerse a priori y no es posible alterarlo durante laejecución del programa. Pueden usarse literales ó constantes en-teras (��, ���, ...), pero nunca una variable

��

��No puede declararse un vector con un tamaño variable

��� ������

���� ��� ���������� �� !�

��"#$� ��������������� ����

%

�Consejo: Fomentad el uso de constantes para especificar el

tamaño de los vectores.

� Las componentes ocupan posiciones contiguas en memoria.

���� ��� ���������� �� !�

��"#$� ��������������� ����

���� ? ? ?

Vectores y MatricesFundamentos → Operaciones con Vectores 309

Otros ejemplos:

��� �������

��� ��� � ����������� � ���

��� ������� � ���

��� � �! "���"��� ��" �#� �����������$� %% �"" �&

'� �����#(�$� %% �"" �&

)�" �*+#,$� %% �"" �&

'� - �"#�������$� %% �""" � �!����.�&

&&&&&&&&&&&&&&

/

IV.1.2. Operaciones con Vectores

IV.1.2.1. Acceso

Dada la declaración:<��!> <�� ���0���">#<����1>$�

A cada componente se accede de la forma:

<Identificador de vector> # <índice> $

0 ≤ índice < ����1

� El índice de la primera componente del vector es 0.El índice de la última componente es <����1>23.

Page 162: Fundamentos de Programacion

Vectores y MatricesFundamentos → Operaciones con Vectores 310

����� ��� ����� ��� � ��

������ ����������� �����

�����

�������� �������� ��������

� � �

? ? ?

�������� y ���������� no son componentes correctas.

� Cada componente es una variable más del programa, del tipo indi-cado en la declaración del vector.

Por ejemplo, �������� es una variable de tipo ������.

Por lo tanto, con dichas componentes podremos realizar todas lasoperaciones disponibles (asignación, lectura con ���, pasarlas co-mo parámetros actuales, etc). Lo detallamos en los siguientes apar-tados.

Vectores y MatricesFundamentos → Operaciones con Vectores 311

IV.1.2.2. Asignación

� No se permiten asignaciones globales sobre todos los elementosdel vector. Las asignaciones se deben realizar componente a com-ponente.

��� �������

��� ��� � ��������� � � ��

����� ������ ��������� ���

���� � �� �� ���! "" #$$$ �� �%����&�

� Asignación componente a componente:

<Ident. vector> � < índice> � = <Expresión>;

<Expresión> ha de ser del mismo tipo que el definido en la decla-ración del vector (o al menos compatible).

��� �������

��� ��� � ��������� � � ��

����� ������ ��������� ���

�����'� � ()��

��� � � '�

������� � ()��

����

�����'� �����*� �����+�

� � �

5.3 ? ?

Page 163: Fundamentos de Programacion

Vectores y MatricesFundamentos → Operaciones con Vectores 312

��� �������

��� ��� � ��������� � � ��

����� ������ ��������� ���

����� ��������

������� � �������� ����� � �����

�� !! �������� "### �$%�& '������ ����#�

(# ���� � � � � � ! � ��������� � � �))�

�� ** ��������

������� � �������� +& ,� ����� �� -��#

.

¿Y si accedemos a una componente no reservada?

�����/0� � 1� 2����� �### %#�-� �� �3���$�4

Veamos por qué:

IV.1.2.3. Representación en memoria

El compilador trata a un vector como un dato constante que almacena ladirección de memoria dónde empiezan a almacenarse las componentes.En un SO de 32 bits, para guardar una dirección de memoria, se usan 32bits (4 bytes).

��� �������

����� -��#����

-��#��� � 5&0�

-��#�/� � 6&1�

-��#�7� � 8&7�

Vectores y MatricesFundamentos → Operaciones con Vectores 313

Es como si el programador hiciese la asignación siguiente:

������ � ������

Realmente, dicha asignación es realizada por el compilador que declara������ como un dato constante:

�� ��� ���������� �� ���������� �� ������ � ������

������ � �������� �� ����� ������������ ������ � ����

��������� � ��!� �� ��������

Para saber dónde está la variable ��������, el compilador debe dar dossaltos, a partir de la dirección de memoria 0010002. Cada salto es de 8bytes (suponiendo que los �� ��� ocupan 8 bytes). Por tanto, se va a lavariable que empieza en la dirección 0010018

Page 164: Fundamentos de Programacion

Vectores y MatricesFundamentos → Operaciones con Vectores 314

En general, si declaramos

�������� ���� ���������

para poder acceder a ���� ������, el compilador dará un total de����� saltos tan grandes como diga el ��������, a partir de la primeraposición de ����, es decir:

���� ������ ≡ ���� � ����� � ������������ ������

��� �����!

���� ��� ����"#�"$���% & '�

��(�)� ���� ����"#�"$���%��

���� *+� & ,� -- .����)� ����� /��� �� �0�(�1�2

Para aumentar la eficiencia, el compilador no compruebaque el índice de acceso a las componentes esté en el rangocorrecto, por lo que cualquier modificación de una compo-nente inexistente tiene consecuencias imprevisibles.

Vectores y MatricesFundamentos → Operaciones con Vectores 315

Ampliación:Un método típico para introducir virus es, precisamente, aprovecharse deque con este tipo de vectores, no se comprueba durante la ejecución elcorrecto acceso a las componentes. La idea consiste en introducir códigode ejecución en dichas zonas de memoria (a las que no debería tenerseacceso) y cambiar la dirección de retorno de la función o método al iniciode dicho código intruso. Buscad en Internet desbordamiento del búfer de lapila (stack buffer overflow). Muchos gusanos (worms) utilizan este método(por ejemplo, el bien conocido Blaster)

Page 165: Fundamentos de Programacion

Vectores y MatricesFundamentos → Operaciones con Vectores 316

IV.1.2.4. Lectura y escritura

La lectura y escritura se realiza componente a componente.

Para leer con ��� o escribir con ���� todas las componentes utilizaremosun bucle, como por ejemplo:

������ ����� ���

����� ������� ���

��� �������

����� ��� ������������� !"�

��#� �����$�������������%& ����

'� ���� � "� � � �������������� �((��

���� �� )*�� ���� ���� � ������ ) �� � �� )+ )�

��� �� �����$�%�

,

��� "�

'� ���� � "� � � �������������� �((��

��� ��� ( �����$�%�

,

��� ��� - ��������������

���� �� ).���� ) �� ����

,

Vectores y MatricesFundamentos → Operaciones con Vectores 317

IV.1.2.5. Trabajando con el vector

No es necesario utilizar todas las componentes del vector. Los huecossuelen dejarse en la zona de índices altos. ¿Cómo sabemos en cada mo-mento cuántos huecos hay?

� O bien ponemos un valor especial en la última componente utiliza-da

� O bien usamos una variable entera, ���� que indique el número decomponentes usadas. Los índices de las componentes utilizadasirán desde 0 hasta ������.

������ �� �������

����� �������� ���

��� �������

��� ��� ���������� �! " �##�

��� ������ ����

�$�� � ���%���������� �!&' �����

�� �� ()��� �*� �� �+��� � ����� � ������ � , (

�� ���������� �! �� (�- (�

�� �� ������ ����

./0��� ������� ��� � � 11 ������ ��� � ���������� �!��

2 � ���� �"#� � � ������ ���� �33��

�� �� (� ��%( �� � �� (& ��� (�

�� �� � ���%�&�

.

Page 166: Fundamentos de Programacion

Vectores y MatricesFundamentos → Operaciones con Vectores 318

��������

� �� � � � �� � � ����� ���� �����

����� � ����� � �������

����� � ����������� ����

��� �� �� ������ � �� ����� �� � ���

����� ��

IV.1.2.6. Inicialización

C++ permite inicializar una variable vector en la declaración.

� � �����!���"#$#%��

inicializa ��������"# �����&��$# �����'��%

� � �����(���!#$��

inicializa ��������!# �����&��$ y el resto se inicializan a cero.

� � �����(������

inicializa todas las componentes a cero.

� � �����(���)��

inicializa la primera a 8 y el resto a cero.

� � ��������&#!#*��

automáticamente el compilador asume � � �����!�

Vectores y MatricesLa clase MiVector → 319

IV.2. La clase MiVector

Inconvenientes de los vectores de C++:

� Permiten acceder a zonas de memoria no reservadas

� Debemos mantener con una variable aparte el número de compo-nentes utilizadas

Solución: Creemos nuestra propia clase ��������. Nos planteamos quéinterfaz debería tener

����������������� ������ �������

��������������������

��������������������

���������������� ���

������������������� �� ��

Podemos dejar huecos involuntariamente:

����������������� ������ �������

��������������������

��������������������

���������������� ���

������������������� �� � � � �

Para evitar este problema, mejor usamos un método ���!� (podríamoshaber optado por otra política, como por ejemplo, sólo permitir insertaral principio)

��������������� �������

����������!�������

����������!�������

����������!��� ���

����������!������

Page 167: Fundamentos de Programacion

Vectores y MatricesLa clase MiVector → 320

Una primera versión (para enteros):

����� ������� ��

�������

���� � � � ������� � �� �

� ���������������������

� ������������

�� ����

������� �!"

������������!�" �#

� ���$�������!" � %%% #

��� � ����!� ���" � %%% #

� &��'� !� � ����" � %%% #

#�

� '�� !"�

������� � �����

����%� ����!("�

����%� ����!)*"�

����%� ����!+"�

,� !� � � �� � - ����%���$�������!"� �.."

�� -- ����%&��'� !�" -- / /�

����%������������(� � *� 00 &��� �'������1

����%������������2�� � *� 00 &��� �'������1

#

Vectores y MatricesLa clase MiVector → 321

A destacar:

� La variable ������������ como cualquier dato miembro, será li-berada por el compilador cuando el objeto de la clase � ���������

deje de existir.

� Debemos fijar de antemano el tope de componentes con la cons-tante �������. Esto supone una restricción importante ���

La solución pasa por usar vectores dinámicos (dynamic arrays)(segundo cuatrimestre)

� Sabemos que las constantes estáticas enteras se declaran dentrode la clase pero pueden definirse (darles un valor) dentro o fuera.Pero si son usadas para dimensionar un vector, deben definirseobligatoriamente dentro de la clase.

Page 168: Fundamentos de Programacion

Vectores y MatricesLa clase MiVector → 322

Definamos los métodos:

����� ������� ��

�������

���� � � � ������� � �� �

� ���������������������

� ������������

�� ����

������� �!"

������������!�"

� #

� ���$�������!"�

���� ������������

#

��� � ����!� ���"�

�% !����������� & �������"�

������������������������ � ����

�����������''�

#

#

� (��)� !� � ����"�

���� ������������� ������

#

#�

¿Debería añadirse el siguiente método? Obviamente no. La gestión de����������� es responsabilidad de la clase, y ha de actualizarse au-tomáticamente, nunca de forma manual.

��� *����$�������!� ������"�

����������� � �������

#

Vectores y MatricesLa clase MiVector → 323

Si queremos un vector de caracteres:

����� ���������������

�������

���� ��� �� ������� � ���

���� ���������������������

�� ��� ���!����

� "����

���������������#$

���� ���!���#�$ %

�� ���&���!���#$

�� �� ��� ���!����

%

��� ������#���� � ��$

�' #��� ���!��� ( �������$

��������������� ���!���� � � ���

��� ���!���))�

%

%

���� *��+��#�� ������$

�� �� ��������������������

%

%�

Los lenguajes de programación ofrecen recursos para no tener que es-

cribir el mismo código para tipos distintos :

� Plantillas (Templates) en C++

� Genéricos (Generics) en Java y .NET

Por ahora, tendremos que duplicar el código �,#

Page 169: Fundamentos de Programacion

Vectores y MatricesAlgoritmos de Búsqueda → 324

IV.3. Algoritmos de Búsqueda

Al proceso de encontrar un elemento específico en un vector se denomi-na búsqueda.

� Búsqueda secuencial (Linear/Sequential search). Técnica más sen-cilla.

� Búsqueda binaria (Binary search). Técnica más eficiente, aunquerequiere que el vector esté ordenado.

IV.3.1. Búsqueda Secuencial

� El vector no se supone ordenado.

� Si el elemento a buscar se encuentra en el vector, devolvemos laposición correspondiente. En caso contrario, devolvemos un valorimposible de posición (por ejemplo, -1)

Vectores y MatricesAlgoritmos de Búsqueda → Búsqueda Secuencial 325

����� ���������������

�������

���� ��� �� ������� � ���

���� ���������������������

�� ��� ���!����

� "����

#####################################

�� $��%����� ������� &���� " ����'

####

(

(�

�� %���&'

��������������� �������

�� �����������

������#������&)�)'�

������#������&))'�

������#������&)�)'�

������#������&)�)'�

���������� � ������#$��%����� �������&)�)'�

�* &���������� �� +,'

� -- ./�� �������.�

����

� -- ./�0������ �� �� �����1� . -- �����������

(

Page 170: Fundamentos de Programacion

Vectores y MatricesAlgoritmos de Búsqueda → Búsqueda Secuencial 326

Algoritmo:

�� ����������� � ��� ������� �� ������

� ������� �� �� ��������� � ������� ������ �

�� ������� �� ������� ��� �� �����

������� ������� ����� �� �������� � �� �� ��� ��������

��� �����������������

������

����� ����� ��� � � !�" # $%&

�'� ������( �����)� � !�"*&

��� ���(����+���&

�����

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

��� -�����"�������� .�'� ��������

��� ��������� # ���&

��� � # %&

/'�� .� 0 ���(����+��� 11 2����������

�� .������( �����)�* ## �������

��������� # ����&

���

�33&

�� .����������

������ �&

���

������ ��&

4

4&

Vectores y MatricesAlgoritmos de Búsqueda → Búsqueda Secuencial 327

Observad que también podríamos haber puesto lo siguiente:

��� �������������� � �� ��������

�����

� ��� �� � ���������������� �� �����������

�� ������������ �� �������

����

Como la llamada al método �������� conlleva una recarga computacio-nal, preferimos trabajar dentro de los métodos de la clase, accediendodirectamente al vector privado con la notación corchete.

Consejo: Procurad implementar los métodos de una clase lomás eficientemente posible, pero sin que ello afec-te a ningún cambio en la interfaz de ésta (los proto-tipos de los métodos públicos)

Page 171: Fundamentos de Programacion

Vectores y MatricesAlgoritmos de Búsqueda → Búsqueda Secuencial 328

Versión con un bucle ���:

����� ������ ����������

�������

����� ����� �� ������� � ���

���� ��������������������� �

�� ������!��"�����

�!#���

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

�� %�&�����!������ '���� #!�����(�

#��� ���������� � ������

�� �

��� ' � � � ) ������!��"���� ** +���������� � ,,(�

� '#!����� �� �������������� (

���������� � ��!��

-

� '����������(

���!�� ./�

����

���!�� ./�

-

-�

El anterior código no es muy elegante. El bloque que busca el elementodebería proporcionar directamente la posición (y no uno más). Podemosusar una variable auxiliar ��������������:

Vectores y MatricesAlgoritmos de Búsqueda → Búsqueda Secuencial 329

����� ���������������

������������������������������������

�� ����������������� ����� �������

�� ������� � ������

�� �����������

�� ��� � � � � � � ������� ��� !! "������� � �##�

�� ������� �� $�������$��%�&�

������� � ����

���������� � ��

'

'

�� ���������

����� �����������

����

����� ()�

'

'�

Tanto la versión con bucle *���� de la página 326 como ésta son perfec-tamente válidas.

Batería de pruebas:

� Que el valor a buscar esté.

� Que el valor a buscar no esté.

� Que el valor a buscar esté varias veces (devuelve la primera ocu-rrencia).

� Que el valor a buscar esté en la primera o en la última posición.

� Que el vector esté vacío o tenga una única componente.

Page 172: Fundamentos de Programacion

Vectores y MatricesAlgoritmos de Búsqueda → Búsqueda Secuencial 330

A veces, podemos estar interesados en buscar entre una componenteizquierda y otra derecha, ambas inclusive.

����� ���������������

�������

���� ��� �� ������� � ���

���� ���������������������

�� ��� ���!����

� "����

#####################################

�� $��%����� �������&��� '�� ����!��( �� �������( ���� " ����)

�� � � ����!���

"� ������� � *�����

+���� '� ,� ������� -- .�������)

�* '�������������� �� " ����)

������� � � ��

����

�//�

�* '�������)

�� �� ��

����

�� �� 01�

2

2�

Vectores y MatricesAlgoritmos de Búsqueda → Búsqueda Secuencial 331

La clase puede proporcionar los dos métodos ��������������� y�������������������. Pero para no repetir código, cambiaríamos la im-plementación del primero como sigue:

�� ��������������� ���� ��������

���� ������������������� �� ��������������� � �� ��������

Hasta ahora, nos quedaría:

Page 173: Fundamentos de Programacion

Vectores y MatricesAlgoritmos de Búsqueda → Búsqueda Binaria 332

IV.3.2. Búsqueda Binaria

Precondiciones de uso: Se aplica sobre un vector ordenado.

La cabecera del método no cambia, aunque para destacar que no es unabúsqueda cualquiera, sino que necesita una precondición, cambiamos elnombre del identificador.

����� ���������������

������������������������������������

�� ��������������� ����� �������

�����

Algoritmo:

�� ������ � ������ �� ������ �� �� ������ ���

���� �� ���� ��� �����

�� ��������� �� ����� ������� �� �������

�� � ���� �� �������� �� ���� ��� ����

�� �� ��� ����� ����������

�� ����� �� ����� �� �� ���� �������������

Vectores y MatricesAlgoritmos de Búsqueda → Búsqueda Binaria 333

Ejemplo. Buscar el 40

604025185 6 7 8

dch=8izq=5

centro=6

60407 8

dch=8izq=7

centro=7

0 1 2 3 4 5 7 86

−8 60402518124 5 9

centro=4

dch=8izq=0

40 > 25

40 > 12

Encontrado

Page 174: Fundamentos de Programacion

Vectores y MatricesAlgoritmos de Búsqueda → Búsqueda Binaria 334

����� ���������������

�������

���� ��� �� ������� � ���

���� ���������������������

�� ��� ���!����

� "����

#####################################

�� $ �% ���$������ &���� " ����'

�� �!%�( ����( �����

�!%� � ��

���� � ��� ���!���)*�

���� � &�!%�+����',-�

.���� &�!%� /� ���� 00 ����������������� 1� " ����'

�2 &" ���� / �����������������'

���� � ����)*�

����

�!%� � ����+*�

���� � &�!%�+����',-�

3

�2 &�!%� 4 ����'

�� �� )*�

����

�� �� �����

3

3�

Vectores y MatricesAlgoritmos de Búsqueda → Otras búsquedas 335

IV.3.3. Otras búsquedas

Ejemplo. Calcular el mínimo elemento de un vector.

� � �������������

Mejor que devolver el elemento �, devolvemos su posición �

Consejo: Cualquier método que busque algo en un vector,

debe devolver la posición en la que se encuentra yno el elemento en sí.

� ��� �������������������

��������

������ ����� ��� ������ � !"#

���� ������$������%������ &#

��� ���� $'�� �(���#

�'� ���

��������������������

����� $'�� �(����"�

�)

��� *�����������+���� ,,,, )

,,,,,,,,,,,,,,,,,

)#

��� +������

������������������ �����#

��� ���$+���+�#

�����,������-�-�#

,,,,,,,,,

���$+���+� � �����,*�����������+���#

Page 175: Fundamentos de Programacion

Vectores y MatricesAlgoritmos de Búsqueda → Otras búsquedas 336

Algoritmo:

����������� ��� � �� ������ ����� �

������� �� ��� �� ����� �� ���� �����

�� �������� �� �� ���� �� ��� � �� �������

����� ����� � ���� ����!

����� �"

� � �� ��� �� #���$�% & '�(

�)�� ��� �*�������#���$�%�(

�� ��*� �������(

��+���"

,,,,,,,,,,,,,,,,,

�� -�����������!

�� ������*���(

�)�� ���(

��� & ��� �*���������(

������*��� & �(

.� ��� � & /( � 0 ��*� ������� ( �11�!

�. ���� �*��������� 0 ����!

��� & ��� �*���������(

������*��� & �(

2

2

�� ��� ������*���(

2

2(

Vectores y MatricesAlgoritmos de Búsqueda → Otras búsquedas 337

Ejemplo. Calcular el mínimo elemento de un vector, pero pasándole almétodo las componentes ���� y ���� donde se quiere trabajar.

� � ���� �� ���� ������ ������

����������������������� devuelve la posición � (índice del vector)

����� �������������������

�������

������ ����� ��� !"�"#$% � �&'

���� ������(�������)!"�"#$%*'

��� �����(+���������'

�+����

,,,,,,,,

-- ������� & .� ���� .� ���� . �����(+���������

��� ��������������/������� ���� ��� ������

��� ��������(������'

���� ������'

������ � ������(�������)����*'

��������(������ � ����'

�� ��� � � ����01 ' � .� ���� ' �00�

� ������(�������)�* . ��������

������ � ������(�������)�*'

��������(������ � �'

2

���+�� ��������(������'

2

2'

Page 176: Fundamentos de Programacion

Vectores y MatricesAlgoritmos de Búsqueda → Otras búsquedas 338

��� �������

���� ����������� �������

��� � ������� �

�������������������

���������

� ������� � �������� ���� ����� �����������

Vectores y MatricesOtros métodos de la clase MiVector → 339

IV.4. Otros métodos de la clase MiVector

Ejemplo. Insertar un elemento en una posición concreta de un vector.

� � ����������� �� ��� ������ � � ����������� � �

� � ������������

��� ����������������� �

��������

����� ��� � ��� ������� � � !

�"�� ������������#�$�������%!

��� �����������&�#� !

��'����

(((((((((

���# �� �������� �� ��� ������� �"�� ������������((()

(((((((((

)!

��� *�����

����������������� ��#���!

��#���(����#��+�+!

��#���(����#��+�+!

��#���(����#��+�+!

��#���(����#��+�+!

��#���(�� ������� +�+!

Page 177: Fundamentos de Programacion

Vectores y MatricesOtros métodos de la clase MiVector → 340

Algoritmo:

�������� ��� � ��� ������� ���������� ������������

��� ��� ��� �� �

���� � �������

����

�� ������������� � ����

¿Dónde está el error en el algoritmo anterior?

�������� ��� � ��� ������� ����� � ��� �� ������

��� ��� ������������

���� � �������

����

�� ������������� � ����

��� ����������������

�����!

����� ����� ��� "#�#$%& � '(�

��� ������� ������"#�#$%&��

��� ����)���*����

)+��!

,,,,,,,,,,

���� %��������� ������������- ��� �����)����

��� ���� � � ����)���*��� � � . ������������ � ����

������� �������� � ������� �����������

������� ������ ������������� � �����)����

����)���*������

/

/�

Vectores y MatricesOtros métodos de la clase MiVector → 341

Batería de pruebas:

� Que el vector esté vacío

� Que el elemento a insertar se sitúe el último

� Que el elemento a insertar se sitúe el primero

� Que el número de componentes utilizadas sea igual al tamaño

Un análisis de estos casos nos lleva a proponer la siguiente mejora:

����� ���������������

�������

���� ��� �� ������� � ���

���� ���������������������

�� ��� ���!����

� "����

##########

��� ������$�� �����������% ���� ������ ��&

�' $��� ���!��� ( ������� )) ����������� *� �

)) ����������� (� ��� ���!���&

'� $�� � � ��� ���!��� � � * ����������� � �++&

�������������� � �������������+,��

������������������������ � ������ ���

��� ���!���--�

.

.

Page 178: Fundamentos de Programacion

Vectores y MatricesOtros métodos de la clase MiVector → 342

Sobre las precondiciones de los métodos

Dentro de un método, ¿debemos comprobar siempre que se satisfacensus precondiciones? Depende.

� La comprobación supone una carga computacional adicional

� Sin embargo, puede evitar errores graves

Consejo: Si la violación de una precondición de un métodopuede provocar errores de ejecución graves, dichaprecondición debe comprobarse dentro del méto-do. En otro caso, puede omitirse.

����� ���������������

���������

��� ����������� �����

�� ������������ � ��������

����������� �����������! " ����#

�����������$$#

%

%

���� &��'����� �������

����� ����������� ������!#

%

%#

Si no comprobamos que existan componentes sin usar, la ejecución de������ podría acceder a componentes no reservadas con el peligro queeso conlleva.

Vectores y MatricesOtros métodos de la clase MiVector → 343

���� ��������� � �����

�������������������� ���������� � � ����

������ ������������

Si el índice pasado a �������� no es correcto, devolverá un valor basura,pero no corremos el peligro de modificar una componente no reservada.

��� ����������� �������

�� ����� �� !! ����� "� ������ ���������� ##$� �� ��������

��� �� ���������������������

Por la misma razón, decidimos no comprobar las precondiciones dentrode los métodos:

��� %������& ����������� ��� ��������' ��� �������' ��� ( �����

��� %������)������������� ����' ��� �����

Lo mismo ocurrió con

��� * �+ ���*������ ��� ( �����

Además, en este caso, comprobar la precondición de que el vector estéordenado es una operación muy costosa.

Por contra, sí comprobamos la precondición en el método

���� ,��������� ������������' ��� ������� ����

para impedir insertar en componentes no reservadas.

Page 179: Fundamentos de Programacion

Vectores y MatricesOtros métodos de la clase MiVector → 344

Por ahora, nos quedaría:

Vectores y MatricesOtros métodos de la clase MiVector → 345

��� �������������� ���� ���� �������� ��� �������� ��� ��������

��� � � ��������

���� ��������� � �����

����� �� �� ������� !����������

�� �"���������"��#�$ �� �������

��������� � �����

����

�%%�

�� �����������

������ ��

����

������ &'�

��� �������������� ���� ��������

������ �������������� ���� �(� �������������� & '� ��������

��� ��������)����� �������� ���� ��� �����

��� ����������������

��� �������

������ � "���������"��#���$�

��������������� � ����

��� ���� � � ���%' � � �� ��� � �%%�

�� �"���������"��#�$ � ��������

������ � "���������"��#�$�

��������������� � ��

������ ����������������

Page 180: Fundamentos de Programacion

Vectores y MatricesOtros métodos de la clase MiVector → 346

��� ��������������

������ �������������������� ��������������������

��� ��������������� ����� ��������

��� ����� ����� �������

���� ��

���� �������������������

������ �����!�����"#�

$���� ����� % ���� && '������(��'���)������* + ��������

�, �������� % '������(��'���)������*�

���� ���������

����

���� ������!��

������ �����!�����"#�

�, ����� - �����

������ ���

����

������ �������

'��� .���������� (������������� ���� '��������'��

�, ����������������� % /001.2 && (������������ - �

&& (������������ % �����������������

,�� ���� � ���������������� � � - (������������ � ����

'������(��'���)�* '������(��'���)���*�

'������(��'���)(������������* '��������'��

Vectores y MatricesOtros métodos de la clase MiVector → 347

�����������������

Page 181: Fundamentos de Programacion

Vectores y MatricesAlgoritmos de Ordenación → 348

IV.5. Algoritmos de Ordenación

La ordenación es un procedimiento mediante el cual se disponen los ele-mentos de un vector en un orden especificado, tal como orden alfabéticou orden numérico.

� Aplicaciones:

Mostrar los ficheros de un directorio ordenados alfabéticamente,ordenar los resultados de una búsqueda en Internet (PageRank esun método usado por Google que asigna un número de importanciaa una página web), etc.

� Técnicas de ordenación:

– Ordenación interna: Todos los datos están en memoria princi-pal durante el proceso de ordenación.

◦ En la asignatura veremos métodos básicos como Inser-ción, Selección e Intercambio.

◦ En el segundo cuatrimestre se verán métodos más avan-zados como Quicksort o Mergesort.

– Ordenación externa: Parte de los datos a ordenar están en me-moria externa mientras que otra parte está en memoria princi-pal siendo ordenada. Se verán en el segundo cuatrimestre.

� Aproximaciones:

Supondremos que los datos a ordenar están en un vector.

– Construir un segundo vector con las componentes del primero,pero ordenadas

– Modificar el vector original, cambiando de sitio las componen-tes. Esta aproximación es la que seguiremos.

Vectores y MatricesAlgoritmos de Ordenación → 349

�������� ��� ����

����� ��������� ����

����� ������ �� ���� ���

� ������

������ ���� ��� ������� � !�

�"� ���� #� ����$%�

��� ����#�����&����

��'����

(((((((((

��� � ����)*�

(((((((

+

+�

��� ����)*�

������ �� ���� �� �������

������(������),",*�

������(������),,*�

������(������),�,*�

������(������),�,*� -- .� ,", ,, ,�, ,�,

������(� ����)*� -- .� ,�, ,", ,�, ,,

(((((((

+

Page 182: Fundamentos de Programacion

Vectores y MatricesAlgoritmos de Ordenación → Ordenación por Selección 350

Idea común a algunos algoritmos de ordenación:

� El vector se dividirá en dos sub-vectores. El de la izquierda, conten-drá componentes ordenadas. Las del sub-vector derecho no estánordenadas.

� Se irán cogiendo componentes del sub-vector derecho y se colo-carán adecuadamente en el sub-vector izquierdo.

Ordenación por selección (Selection sort): En cada iteración, se selec-ciona la componente más pequeña del sub-vector derecho y se coloca alfinal del sub-vector izquierdo.

IV.5.1. Ordenación por Selección

Algoritmo:

�������� ����� �� ������� � ����� �� �

���� � �������� ������ �� ���� ������

�� ��������� �������� ��� �� ����������

���� � ����������������� ����� ���������

����������� � ����� ��� � �������

Vectores y MatricesAlgoritmos de Ordenación → Ordenación por Selección 351

7823 45 8 32 56

8 23 3245 78 56

238 32 78 45 56

8 5623 32 45 78

8 7823 32 45 56

8 45 23 32 5678

Tras la pasada 5

Tras la pasada 4

Tras la pasada 3

Tras la pasada 2

Tras la pasada 1

Vector Original

Page 183: Fundamentos de Programacion

Vectores y MatricesAlgoritmos de Ordenación → Ordenación por Selección 352

En el bucle principal no es necesario recorrer todos los elementos de �,ya que si sólo queda 1 componente, el vector está ordenado. Por lo tanto,el bucle principal será de la forma ������������������

��� ���� ������� ������

��������

����� ���� ��� ������� � ���

�� �� ����������!�������"�

��� ��������������

���� ����� �#$����#����������%��� �����&��� �������' ��� ���� �(�

�� ����� �#$���

����� �#$�� � �� ����������!�������"�

�� ����������!�������" � �� ����������!���� �"�

�� ����������!���� �" � ����� �#$���

)

��$� �

���� ���������*�� ���&(�

��� ���#���

+�� &��� ������ � ������������������ � ����,,(�

���#�� � %��� �������#�-���� &����' �������������./(�

����� �#$����#����������%��� ����� &����' ���#��(�

)

)

0000000000000

Nota. Podríamos optar por elevar a público el método que intercambia po-siciones. Pero entonces deberíamos comprobar (dentro de dicho método)el cumplimiento de las precondiciones (posiciones en el rango adecua-do). Para una operación tan costosa como la ordenación, conllevaría unarecarga excesiva (e innecesaria si nos preocupamos de definir adecuada-mente los métodos que utilizan el método para intercambiar posiciones)

Vectores y MatricesAlgoritmos de Ordenación → Ordenación por Selección 353

Batería de pruebas:

� Que el vector esté vacío

� Que el vector sólo tenga una componente

� Que tenga un número de componentes par/impar

� Que el vector ya estuviese ordenado

� Que el vector ya estuviese ordenado, pero de mayor a menor

� Que el vector tenga todas las componentes iguales

� Que tenga dos componentes iguales al principio

� Que tenga dos componentes iguales al final

� Que tenga dos componentes iguales en medio

Nota. Esta batería también es aplicable al resto de algoritmos de ordena-ción

Applet de demostración del funcionamiento:

��������������� ��� ���������

Page 184: Fundamentos de Programacion

Vectores y MatricesAlgoritmos de Ordenación → Ordenación por Inserción 354

IV.5.2. Ordenación por Inserción

Ordenación por inserción (Insertion sort): El vector se divide en dos sub-vectores: el de la izquierda ordenado, y el de la derecha desordenado.Cogemos el primer elemento del subvector desordenado y lo insertamosde forma ordenada en el subvector de la izquierda (el ordenado).

Nota. La componente de la posición (primer elemento del subvectordesordenado) será reemplazada por la anterior (después de desplazar)

Algoritmo:

Vectores y MatricesAlgoritmos de Ordenación → Ordenación por Inserción 355

45 8 32 56

23 5678 8 32

56

8 78

45

23 45 78 8 32 56

8 23 45 78 32 56

8 23 32 45 78

23 32 45 56

23 78 Vector Original

Tras la pasada 1

Tras la pasada 2

Tras la pasada 3

Tras la pasada 4

Tras la pasada 5

Page 185: Fundamentos de Programacion

Vectores y MatricesAlgoritmos de Ordenación → Ordenación por Inserción 356

����� ���������������

�������

���� ��� �� ������� � ���

���� ���������������������

�� ��� ���!����

� "����

#############

��� ������������������$%

�� �!��& ��

���� ��������!���

'� $�!�� � (� �!�� ) ��� ���!���� �!��**%

��������!�� � �������������!����

'� $� � �!��� �+� ,, ��������!�� ) �������������-(�� �--%

�������������� � �������������-(��

�������������� � ��������!���

.

.

.�

Vectores y MatricesAlgoritmos de Ordenación → Ordenación por Intercambio Directo (Método de la Burbuja) 357

IV.5.3. Ordenación por Intercambio Directo (Mé-todo de la Burbuja)

Ordenación por intercambio directo (burbuja) (Bubble sort): Al igual queantes, a la izquierda se va dejando un subvector ordenado. Desde el finaly hacia atrás, se van comparando elementos dos a dos y se deja a laizquierda el más pequeño (intercambiándolos)

Algoritmo:

�� ������ � ����� �� ������ ����

�� �� ������ ���� � � � �� �� ������������� � �

����� � ������ � �� ����� � �

� ����� �� �� � �������� ������

�� �� ������ �

�� ���� � ������ ������ �����

Page 186: Fundamentos de Programacion

Vectores y MatricesAlgoritmos de Ordenación → Ordenación por Intercambio Directo (Método de la Burbuja) 358

Primera Pasada

7823 45 8 32 56

7823 45 8 32 56

7823 45 8 32 56

23 32 5645788

32 5645788 23

No intercambiar

No intercambiar

Intercambiar

Vector Original

7823 32 568 45

Intercambiar

Intercambiar

Proceso

Durante Pasada 1

Tras la pasada 1

Vectores y MatricesAlgoritmos de Ordenación → Ordenación por Intercambio Directo (Método de la Burbuja) 359

Resto de Pasadas

8 7823 32 45 56

8

7823 45 8 32 56

8 23

238 32

8 23 32 45

32 78 45 56

7845 56

56 78

23 78 45 32 56

Tras la pasada 5

Tras la pasada 4

Tras la pasada 3

Tras la pasada 2

Tras la pasada 1

Vector Original

Page 187: Fundamentos de Programacion

Vectores y MatricesAlgoritmos de Ordenación → Ordenación por Intercambio Directo (Método de la Burbuja) 360

� Primera Aproximación

����� ���������������

�������

���� ��� �� ������� � ���

���� ���������������������

�� ��� ���!����

��� ������"#���"����������$�������%�� ����!��& �� �������'

���� ������"#���

������"#�� � ����������������!����

����������������!��� � ���������������������

�������������������� � ������"#���

(

� #����

)))))))))))))

��� ����������* �# +�%'

�� �!��& ��

,� %�!�� � �� �!�� - ��� ���!���� �!��..'

,� %� � ��� ���!���/0 � �1�!�� � �//'

�, %�������������� - �������������/0�'

������"#���"����������$�������%�& �/0'�

(

(�

Mejora. Si en una pasada del bucle más interno no se produce ningún in-tercambio, el vector ya está ordenado. Lo comprobamos con una variablelógica.

Vectores y MatricesAlgoritmos de Ordenación → Ordenación por Intercambio Directo (Método de la Burbuja) 361

� Segunda Aproximación

����� ���������������

�������

���� ��� �� ������� � ���

���� ���������������������

�� ��� ���!����

��� ������"#���"����������$�������%�� ����!��& �� �������'

(((((((((((((

)

� #����

(((((((((((((

��� ����������* �# +���+���%'

�� �!��& ��

#� ��"#��

��"#� � � ��

,� %�!�� � �� �!�� - ��� ���!��� .. ��"#�� �!��//'

��"#� � ,�����

,� %� � ��� ���!���01� � 2 �!��� �00'

�, %�������������� - �������������01�'

������"#���"����������$�������%�& �01'�

��"#� � � ��

)

)

)

)�

Page 188: Fundamentos de Programacion

Vectores y MatricesLas clases ������ y ����→ 362

IV.6. Las clases ������ y ����

IV.6.1. La clase ������

Las plantillas (templates) permiten crear clases que trabajan con variostipos de datos, tal y como ya indicamos en la página 323. Podríamos defi-nir nuestra propia plantilla �������� para trabajar en una misma clase conenteros, caracteres, etc. Esto se verá en el segundo cuatrimestre.

C++ ofrece una plantilla estándar llamada ������ que permite trabajar convectores de forma segura, y con capacidad dinámica. Pertenece a la bi-blioteca estándar STL (Standard Template Library). Debemos incluir labiblioteca ������:

������ ��������

Para definir un objeto de la clase ������, se especifica el tipo base delvector:

�� ������

������ �������� ��������������

������ ���� ��������������

������ ��������� ����������������

���������

La plantilla ������ proporciona métodos para añadir componentes, acce-der a ellas, etc. A diferencia de los vectores que hemos visto (declaracióncon corchete), cuando se añaden o suprimen componentes, se reajustael tamaño de forma automática.

Vectores y MatricesLas clases ������ y ����→ La clase ������ 363

Resumen de los métodos que usaremos:

��� �����. Añade un elemento.

����. Devuelve el número de elementos que, en ese momento, es-tán siendo utilizados.

��������. Devuelve el máximo número de elementos que, en esemomento, están reservados para poder utlizarse.

��������. Elimina el último elemento.

���� y ����. Devuelven el primero y último elemento respectiva-mente.

�����. Nos dice si el vector está vacío.

�����. Borra todos los elementos.

Hay dos formas de acceder a las componentes:

� Con notación corchete:Cuando se accede a una componente que está por encima de������, el comportamiento es imprevisible.

� Con el método ��:Cuando se accede a una componente que está por encima de������, se produce un error en tiempo de ejecución (salta una ex-cepción)

Page 189: Fundamentos de Programacion

Vectores y MatricesLas clases ������ y ����→ La clase ������ 364

���� �� ����������

���� �� ��������

�� �������� ����

�� ������

������ ��� ���� ��������������

��������������� �������������

��������������� ���������� ��

�� � �� !"#���$� ��� �� ��� ������ % ! �� ����������������&���� ''(

�� � �� !"#���$� �)*��� ��� ������ % ! �� ���������������������+��� ''�%(

,�� ��� �%- � � � ����������������&��� � �..�

�� � �� !"/���� � ������0 ! �� � �� ! % !

�� ������������������� �� ! % ! �� �������������1�2�

������������������������� '' 3����� �� 4����� ��� � %� 5�&�%6

������������������������� '' 3����� �� 4����� ����� %� 5�&�%-

������������������������� '' 7� � ��+ ��������8

'' ���� � �� ���� �� �4 �����

'' �������������1-2 % �� '' 9������� � �*���� %� :�����������

'' �� � �� �����������������-�� '' 9������� � �*���� %� 3���� �;�� ��0

��������������� ��������6��(��

�����������������-� % 6<�(� '' �� �����= ������� ������� � �

'' �������� ���� ����,������

'' 3��� �� ������� ���> � �� ��� ���� �

'' ��,������ � �� �������� � � ����0�

'' ?� ����� �� ��� �� ,��� + ����

�� � �� !"@������ % ! �� ��������������,������

�� � �� !"A����� % ! �� ���������������������

B

Vectores y MatricesLas clases ������ y ����→ La clase ������ 365

Muchos métodos de ������ usan o devuelven iteradores (iterators), queno se ven hasta el segundo cuatrimestre. Estos iteradores permiten re-correr de una forma genérica un conjunto de datos.

La STL proporciona otras plantillas importantes como �����, ���, etc.También se verán en el segundo cuatrimestre.

Podríamos usar un objeto de la clase ������ como vector privado denuestra clase ��������. De esa forma, ya no sería necesaria el límite deelementos impuesto por la constante estática �������.

Observad que la interfaz no varía nada, por lo que los antiguos clientesde la clase �������� pueden seguir usándola tal y como lo hacían antes.Sólo hemos cambiado la implementación interna. Nos quedaría:

Page 190: Fundamentos de Programacion

Vectores y MatricesLas clases y → La clase 366

Vectores y MatricesLas clases ������ y ����→ La clase ������ 367

����

����� ��

�� ���������������� ����� ���������

����� ����������������������� �������������� ��!��� �� ���������

�� �������"����������� �!��� �� ������

�� ��������������

���� ������

����� # ��������������$�!��%�

������������� # �!���

&�� ��� � # �!��'� � � (# ���� � �''�

�& ���������������$�% ( �������

����� # ��������������$�%�

������������� # ��

����� ��������������

�� �������"�������

����� �������"����������� �������������� ��!��� ���

�� )��*����)����� ����� ���������

�� �!*�� ����� ������

�!*� # ��

���� # �������������� ��!��� ��

����� # ��!*�'�����+,�

-���� ��!*� (# ���� .. ��������������$�����% /# �������� �

�& �������� ( ��������������$�����%�

Page 191: Fundamentos de Programacion

Vectores y MatricesLas clases ������ y ����→ La clase ������ 368

��� � ��������

����

��� � ��������

����� � ���� ���� ����

�� ���� � ��� �

����� ���

����

����� ������

���� ����� ��� ��� �������! �� � � ��� �����"

�� ��� ��� � ������ ���� ��#�������

�� ���� ������� �� $ %% ��� ������� &� ��� ����"

��� ��� � � ��� ��� � � � ��� ������� � ����

������ ���� ��'�( � ������ ���� ��'���(�

������ ���� ��'��� �������( � � ��� �����

���� )��� ��� *���������"

�� ��� +��

�� ��� ��� � ������ ���� ��#�������

��� ��� ��� � $ � ��� & ��� ��� � ��� ���"

��� +� � ,������-��+�.��� ���� ! ��� ��� � ���

����� +/� 0�+������ � ,�������� ���� ! ��� +���

���� )��� ��� ���������"

�� ��� ! ��

Vectores y MatricesLas clases ������ y ����→ La clase ������ 369

���� � ����������

�� ������� � ������ ���������������

��� ����� � �� ���� � �������� ��������

� ��������� � ������ ��������������

��� �� � ����� ��� � ��������� � ������ ���������!��� �!!�

������ ���������� � ������ ���������!���

������ ���������� � � ����������

"

"

���� #���� ��� $%�&%'����

�� ����( ��

&��� ��)&���

�� ������� � ������ ���������������

��)&�� � ��%��

��� ����� � �� ���� � ������� ��)&��� ��������

��)&�� � ������

��� �� � �������!�� � � ����� �!!�

�� ������� ���������� � ������ ���������!����

*�����)&��+�)������ � ,����������( �!���

��)&�� � ��%��

"

"

"

"�

Page 192: Fundamentos de Programacion

Vectores y MatricesLas clases ������ y ����→ La clase ���� 370

IV.6.2. La clase ������

El tipo ���� usado hasta ahora es, realmente, una clase.

Al igual que ocurre con la plantilla ������, a los elementos se accede através de la notación corchete o el método ��.

Los siguientes métodos realizan la misma función que en la plantilla������:

��� ��������� ����� �� ������ �� ��� �����

Otros métodos interesantes:

����. Hace lo mismo que ����.

� ��. Añade una cadena al final de otra.

�����. Inserta una subcadena a partir de una posición.

�� ����. Reemplaza una serie de caracteres consecutivos por unasubcadena.

�����. Borra un número de caracteres, a partir de una posición.

���. Encuentra un carácter o una subcadena.

������. Obtiene una subcadena.

������� ����������

������� ��������

������� ������

��� ���� ��� ����

�� ������

���� ������

���� �����������

Vectores y MatricesLas clases ������ y ����→ La clase ���� 371

����� ���������� ��

���������� �������������

������������������������� �� ������������

������������������������ �� ���������� �����������

������������� ! ��� ��� �� ��� � �� ���"� � #� ������� �

�� $����� %$

�� ���������� �� �����������

�����&� ' ���� �� ���������� �� �����������

����������(� ��� �� ���������� � �����������

���������#����� ! ! ��� #���� �� ���������� �� #� �����������

�������������)! (�� �� ���������� �� �����������

�� �����������������

���������������� ������*��������� �� �

���������������� ������*�������� �� ) ������� ��������� �� ���

���������������� ������*������! +�� �� � ������� ��������� �� ���

�� � ������ �� #� ������+

���������������� �������*�������� �� � ,#���� ��������� �� ���

�� $���� *��$

���������������� �������*������! -�� �� ) ,#���� ��������� �� ���

�� ������� ���� #�� ����� %!-

���������� �������������� ! �� �� ���� ./���� #� �������� 0��

�� ��1 ���� #�� ����� � ! � 2

�����

3

Page 193: Fundamentos de Programacion

Vectores y MatricesVectores de varias dimensiones: Matrices → 372

IV.7. Vectores de varias dimensiones: Ma-trices

IV.7.1. Declaración

Supongamos una finca rectangular dividida en parcelas. Queremos alma-cenar la producción de aceitunas, en TM.

La forma natural de representar la parcelación sería usando el conceptomatemático de matriz.

4.5 5.9 1.2

9.1 0.4 5.8

Para representarlo en C++ podríamos usar un vector �������:

9.1 0.4 5.8 4.5 5.9 1.2

pero la forma de identificar cada parcela (por ejemplo ���������) es pocointuitiva para el programador.

Vectores y MatricesVectores de varias dimensiones: Matrices → Operaciones con matrices 373

����� �� ���������������� ���������������������������

Como con los vectores, el tipo base de la matriz es el mismo para to-das las componentes, ambas dimensiones han de ser de tipo entero, ycomienzan en cero.

�� ������

���� �� ����������� !�

���� �� ����������� "�

��#$%� �� ��%����������������������������

&

IV.7.2. Operaciones con matrices

IV.7.2.1. Acceso y asignación

���������'� ����!�

0 ≤ ��i < �������i

���������'� ����!� es una variable más del programa y se com-porta como cualquier variable del tipo de dato base de la matriz.

Page 194: Fundamentos de Programacion

Vectores y MatricesVectores de varias dimensiones: Matrices → Operaciones con matrices 374

Por ejemplo, para asignar una expresión a una celda:

������������� ������� = < �������>�

< �������> ha de ser del mismo tipo de dato que el tipo base de lamatriz.

Ejemplo.

�� ������

����� �� ������� !�" # ��

����� �� ������� $�" # %�

��&'(� �����(��������� !�"��������� $�"��

�����(��)��)� # *+,� -- $��������

�����(��)��� # ,+.� -- $��������

�����(�����)� # /+�� -- ���� (�0��1 !(� � �� �����+

�����(��)��%� # /+�� -- ���� (�0��1 $�(&��� % �� �����+

�����(��)��)� # *� -- $�������1

-- $����0 �&���2���1 ��&'(�#��

3

Vectores y MatricesVectores de varias dimensiones: Matrices → Operaciones con matrices 375

IV.7.2.2. Gestión de componentes útiles con matrices

Por cada dimensión necesitamos gestionar una variable que indique elnúmero de componentes útiles.

�������� ��� ����

����� ��������� ����

��� �������

���� ��� ����������� !" ��������#�� $�

��� �����%������� ����" ��������������� �����

��� %��" ���

��&�� �� ����'�����������('��������#��(�

��&�� � �������

���������� ���� )�

����#���� ���� *�

% �%�� + � %�� �����%������� ���� � %��,,�

% ��� + � �� ��������������� ���� � ��,,��

��� -��� ���� �� � �����.� �� �� �� �� �� ���� -

%�� -"- ���

��� �� � �������

�� ����'%��('��( � �������

/

��� -0�1��� ��� ������20�-�

Page 195: Fundamentos de Programacion

Vectores y MatricesVectores de varias dimensiones: Matrices → Operaciones con matrices 376

��� ���� � � ��� ���� ����� ������� �������

��� ���� � � ��� ���� �������� ������� �������

���� ������������� �� �� �� �� ������� �

��� ��� ��� � ! �

���� �������"���#"���#

$

���� ����

$

$

Nota. Podemos poner directamente: ��� !! �������"���#"���#

Vectores y MatricesVectores de varias dimensiones: Matrices → Operaciones con matrices 377

IV.7.2.3. Inicialización

En la declaración de la matriz se pueden asignar valores a toda la matriz.Posteriormente, no es posible: es necesario acceder a cada componenteindependientemente.

La forma segura es poner entre llaves los valores de cada fila.

��� �������� ������ �������� �� ���� ������� � �

�� � � �

Si no hay suficientes inicializadores para una fila determinada, los ele-mentos restantes se inicializan a 0.

��� �������� ��� �������� �� ���� ������� � � �

�� � � �

Si se eliminan las llaves que encierran cada fila, se inicializan los elemen-tos de la primera fila y después los de la segunda, y así sucesivamente.

��� ��������� �� � �� �� ��� �� ���� ������� � � �

�� � � � �

�� � � � �

Page 196: Fundamentos de Programacion

Vectores y MatricesVectores de varias dimensiones: Matrices → Operaciones con matrices 378

IV.7.2.4. Representación en memoria

Todas las posiciones de una matriz están realmente contiguas en memo-ria. La representación exacta depende del lenguaje. En C++ se hace porfilas:

� contiene la dirección de memoria de la primera componente.

Para calcular dónde se encuentra la componente ������� el compiladordebe pasar a la segunda fila. Lo consigue trasladándose tantas posicio-nes como diga ������ ��, a partir del comienzo de �. Una vez ahí, salta2 posiciones y ya está en �������.

Conclusión: Para saber dónde está �������, el compilador necesita sabercuánto vale ������ ��, pero no ��������. Para ello, da tantos saltoscomo indique la expresión �������� �� � �

Vectores y MatricesVectores de varias dimensiones: Matrices → Operaciones con matrices 379

Ejemplo. Buscar un elemento en una matriz.

�������� ��� ����

����� ��������� ����

��� �������

���� ��� ����������� !" ��������#�� $�

��%�� �&�����������'&��������#��'�

��� (��������� ��" ������������ ��" �����(������"

��������������" (��" ���

��%�� %������

%� ����� ���

��

��� )��� ���� �� ���� �� (����* )�

��� �� �����(�������

+,-��� ������(������ . // �����(������ � �������������

��

��� )��� ���� �� ���� �� �������* )�

��� �� ���������������

+,-��� ��������������� . // �������������� � ��������#����

Page 197: Fundamentos de Programacion

Vectores y MatricesVectores de varias dimensiones: Matrices → Operaciones con matrices 380

��� ���� � � ������� ����� � ������

��� ���� � � ������� �������� � �������

���� ����������� �� �������� ��

��� ��� ��� ��� �

��� �� �����������

���� � ��������!�� �������� � "������ �

��� �� "������

����������������

��� ���� � � #���������� $$ ��� ���� ����� � �������

��� ���� � � #���������� $$ ��� ���� �������� � ������

�� ������������ �� "��������

���������� � ����

���� ���������� � ���

������� ���������� � ���

�� ������������

���� � �%������� ���������� �� �� &�����'� �

���� ���������� ��� ������� ���������� ����

����

���� � �%������� �� ���������� ��

Importante: la variable ���������� ha de ser la misma en los dos bucles.

Vectores y MatricesVectores de varias dimensiones: Matrices → Más de dos dimensiones 381

IV.7.3. Más de dos dimensiones

Podemos declarar tantas dimensiones como queramos. Sólo es necesa-rio añadir más corchetes.

Por ejemplo, para representar la producción de una finca dividida en 2×3parcelas, y dónde en cada parcela se practican cinco tipos de cultivos,definiríamos:

����� ��� ���� � ��

��� � � ��

������������ � ��

������ !"���!#���� $#��� �$#������������$�

%% ���&�!��'� !� "�(�" �����)� �� �! !"���! *��

!"���!#*$#�$#+$ � ,-��

Page 198: Fundamentos de Programacion

Vectores y MatricesVectores de varias dimensiones: Matrices → La clase MiMatriz 382

IV.7.4. La clase MiMatriz

Una matriz tiene los mismos problemas de acceso a componentes noreservadas que los vectores. Para evitarlo, debemos construir nuestrapropia clase ��������.

¿Cuál sería la interfaz de la clase ��������?

� Podemos establecer un tope fijo de columnas en el constructor yañadir elemento a elemento hasta llegar a dicho tope, en cuyo caso,pasaríamos automáticamente a la siguiente fila:

Vectores y MatricesVectores de varias dimensiones: Matrices → La clase MiMatriz 383

� En vez de añadir carácter a carácter, sería interesante añadir filasenteras:

Para ello necesitamos saber cómo se pasa un objeto como pará-metro y cómo un método puede devolver un objeto. Lo vemos enel siguiente tema.

Page 199: Fundamentos de Programacion

Vectores y MatricesVectores de varias dimensiones: Matrices → La clase MiMatriz 384

Bibliografía recomendada para este tema:

Los libros suelen introducir el concepto de vector antes de ver las clases.En este caso, los autores muestran cómo pasar los vectores como pará-metros a las funciones. Esta forma de trabajar implica que también hayque pasar como parámetro el número de componentes útiles. En definiti-va, corresponde a una filosofía de programación procedural y no orienta-da a objetos.

Los libros que lo hacen al revés (introduciendo primero las clases y luegolos vectores) utilizan la clase estándar ������.

La aproximación seguida por nosotros es distinta pues, habiendo intro-ducido primero las clases, optamos por el uso del vector clásico de C++,para ver su manejo en memoria y para ilustrar la construcción de nuestrapropia clase �������.

Por tanto, la bibliografía recomendada para este tema pasa por la consul-ta de fuentes que detallen los algoritmos de búsqueda y ordenación deuna forma genérica (hablando de un conjunto de elementos, en vez deun array de C++) En este sentido, una referencia bastante adecuada esWikipedia (pero la versión en inglés)

���� ���������������� ���� ������������������������

���� ���������������� ���� ��������������������������

Tema V

Clases (Segunda parte)

Objetivos:

� Ver cómo gestiona C++ el copiado entre objetos y sus implicacio-nes en el diseño de clases.

� Empezar a diseñar clases que colaboran entre sí para poder resol-ver problemas más complejos.

� Introducir el concepto de excepción y ver cómo se aplica en la ges-tión de errores.

Autor: Juan Carlos Cubero.

Sugerencias: por favor, enviar un e-mail a ������������ ��������

Page 200: Fundamentos de Programacion

Clases (Segunda parte)Copiando objetos → 386

V.1. Copiando objetos

V.1.1. Operador de asignación

V.1.1.1. Funcionamiento del operador de asignación

C++ permite asignar objetos entre sí a través del operador de asignación(assignment operator) �

Este operador lo define automáticamente el compilador para cualquierclase, y funciona como si trabajásemos con tipos básicos:

������ � �����������

� Ambos objetos han de ser de la misma clase.

� Se realiza una copia de todos los datos miembro, tanto los privadoscomo los públicos.

� No tiene sentido hablar de copiar los métodos. ¡Ya estaban dispo-nibles!

� El programador puede definir otro comportamiento. Se verá en elsegundo cuatrimestre al ver la sobrecarga (overloading) del opera-dor de asignación.

Clases (Segunda parte)Copiando objetos → Operador de asignación 387

����� �������

���� ��

�� �������

������

�� �������

���������� ���� �� ���

�������������

����������

�� ���������

�� ��� �������

�� ���������

�� ��� �������

��

�� ������

������� ��������� � ��������

� �� � ����

��� !"�������� �� ���� ! ���#���������� $$ �

��� !"��%����� �� ���� ! ���#���������� $$ �

��� !"�������� �� � ��� ! � ��#���������� $$ �

��� !"��%����� �� � ��� ! � ��#���������� $$ �

Nota. Recordemos que jamás usaremos datos miembro públicos. El an-terior es un ejemplo para mostrar los efectos del operador de asignación.

Page 201: Fundamentos de Programacion

Clases (Segunda parte)Copiando objetos → Operador de asignación 388

V.1.1.2. El operador de asignación y los datos miembro constantes

¿Qué pasa cuando una clase contiene datos miembro constantes?

� Una constante estática es la misma para todos los objetos de unaclase. Por tanto, éstas no dan problemas en la asignación entreobjetos.

����� ���������������

�������

���� ��� �� ��� � ���

���� �����������������

�� ������������

�������

��������������� !

������������ �!

"

#################

"�

�� $��� !

��������������� ������% ����������

������#&����� ''!�

������#&����� '�'!�

������#&����� '�'!�

������#&����� '�'!�

��������� � ������� (( )� ������ *� +�� �� ������

(( �� ��,���% �� �����% �� $��$�

(( ���� �� �� �-��

Clases (Segunda parte)Copiando objetos → Operador de asignación 389

� Una constante no estática es propia de cada objeto. ¿Qué sentidotiene cambiar su valor con la constante de otro objeto? Ninguno.�

�C++ NO permite asignar objetos entre sí cuando la clasecontiene datos miembro constantes no estáticos

����� ������������

�������

���� ����� �������������

�����������

�������

������������������ ������������������� ������ ��������������

����������������������

��������������������������������

�����������

��

�� ������

������������ ��������� �������������� !!!!��

������������ �����������"�� �������������� #!!!!��

��������� $ ������ %% &���� �� ���������'�� �� ����

%% �� ����� ���� ������� ��������

Nota. Cuando se define una clase con datos constantes no estáti-cos, Visual Studio da un aviso durante la compilación, indicandoque no se pudo generar el operador de asignaciones.

Page 202: Fundamentos de Programacion

Clases (Segunda parte)Copiando objetos → El constructor de copia 390

V.1.2. El constructor de copia

C++ permite inicializar un objeto con los datos de otro:

����� �������

�����

������� ���� ��������� ����� �

�����

��

��� ������

������� �������������

������� ����������� ����������� � �� �� ����������� �� ����

En la sentencia ������� ����� �� ������ ���, el compilador llamaautomáticamente al llamado constructor de copia (copy constructor). Esun constructor que recibe como parámetro un objeto de la misma clase yes proporcionado automáticamente (de oficio) por el compilador.

El constructor de copia realiza la asignación de los datos miembro quetenía ����� �� a ����� ��. Es como si fuese una asignación del tipo����� �� � ����� ��.

�� �������

������������� ����� �� ����

����������������� ����������������� �����������������

������������� ��������������

��� � ���������������� �������

!� ��� � � "� � # ���� �$$�

��� ## �����%��������� ## & &�

Clases (Segunda parte)Copiando objetos → El constructor de copia 391

En resumen, C++ proporciona dos constructores de oficio:

� Un constructor sin parámetros. Se usa para poder crear objetos deuna clase que no incluya la definición explícita de ningún construc-tor.

� Un constructor con un único parámetro y cuyo tipo es la mismaclase que se está definiendo. Se usa para inicializar un objeto conlos datos de otro objeto de la misma clase.

Es como si fuese una asignación del tipo ����������� � �������. Perohay diferencias entre el operador de asignación y el constructor de copia:

� El operador de asignación es invocado cuando ya tenemos creadosdos objetos y ejecutamos la sentencia �������� � ��������

� El constructor de copia es invocado en el momento de la declara-ción del objeto, justo en el momento en el que se va a crear éste.

Veremos otros sitios en los que el compilador también invoca au-tomáticamente al constructor de copia.

Por esta razón, si un objeto tiene datos constantes, sí podemos inicializarotro objeto con los datos del primero (porque todavía no tenía definida laconstante):

����� ������������

��������

���� ����� ������������

�����������

�� ���� �

����������� �����!������� � ���� �� ������!" �####

����������� �������������� $$ ��������

��������� � ���� $$ %���� �� ���������&

Page 203: Fundamentos de Programacion

Clases (Segunda parte)Copiando objetos → El constructor de copia 392

Pero si al final, el operador de asignación y el constructor de copia hacenlo mismo (copiar los datos miembro), sólo que en sitios distintos ¿dón-de está entonces la diferencia? (aparte de lo que hemos visto sobre losdatos constantes)

C++ permite redefinir ambos. Pero además, pueden redefinirse de for-ma distinta. Así pues, podríamos tener distintos comportamientos parael mismo concepto de asignación. Esto no es coherente y es una seriacrítica a C++.

C++ distingue entre “asignación” de objetos a través de � y“asignación” de objetos a través del constructor de copia.

Esto sólo da problemas.

Clases (Segunda parte)Copiando objetos → Copiar o no copiar: He ahí el dilema 393

V.1.3. Copiar o no copiar: He ahí el dilema

El problema de copiar objetos (independientemente de que C++ distingaademás entre operador de asignación y constructor de copia) es aún másproblemático de lo que hemos visto. Las cosas se complicarán cuando sevea el concepto de puntero y se distinga entre copia superficial (shallowcopy) y copia profunda (deep copy).

Java, �� y Visual Basic.NET resuelven el problema utilizando únicamentereferencias a objetos. Al hacer una asignación no se realiza una copia detodos los datos de un objeto sino que simplemente se copia su direcciónde memoria. Esto lo podremos hacer también en C++ usando punteros.De esta forma, no será necesario definir operadores de asignación pro-pios ni constructores de copia.

En resumen:

� La asignación entre objetos se realiza a través del operador deasignación y del constructor de copia.

� En principio, el comportamiento básico de ambos es el mismo (secopian los datos miembro) y así lo supondremos en esta asignatu-ra.

Sin embargo, el programador puede cambiar dicho comportamien-to y, además, de forma independiente (lo cual no es recomendable).

� Lo usual será utilizar punteros a objetos y copiar los punteros, envez de recurrir a la copia entre objetos.

Page 204: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → 394

V.2. Trabajando con varios objetos

V.2.1. Pasando objetos como parámetros

¿Podemos pasar un objeto como parámetro por valor a un método? Sí,porque acabamos de ver que es posible la asignación entre objetos. Elparámetro formal recibirá una copia del actual. Esta copia se realiza através del constructor de copia visto anteriormente.

����� �������

��

����� ��������

�������

���� ���������������� �����������������

��

��� ������

������� ������������������� ��

�������� ��������!����

��������!������������������������������

En tiempo de ejecución se invoca automáticamente al constructor de co-pia: ����������������������������������

�Al pasar los objetos como parámetros, se invoca al cons-tructor de copia

Clases (Segunda parte)Trabajando con varios objetos → Pasando objetos como parámetros 395

Ejemplo. La ecuación de una recta viene dada en la forma

Ax + By + C = 0

es decir, todos los puntos (x, y) que satisfacen dicha ecuación formanuna recta.

Queremos definir la clase ����� y ver si contiene a un punto.

Page 205: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Pasando objetos como parámetros 396

�������� ��� ����

����� ��������� ����

�� ��������������� ��� ����� � � �

��� � ��������� � � �����

����� !���"#�

� �$���%

����� ��������

����� �������

������%

!���"#������ �������!���� ����� ������!����

���& ������� ��������!���� ������!�����

$�� ���& ������� ������ �������!���� ����� ������!�����

������� � �������!����

������ � ������!����

����� '��(���������

��� � ��������

����� '��) ���������

��� � �������

����� *�����

� �$���%

����� (� +� &� ,, (- . +/ . & � 0

������%

*���������� ���1-� ����� ���1/� ����� ���1�������

Clases (Segunda parte)Trabajando con varios objetos → Pasando objetos como parámetros 397

������������� ������ � ������� �����������

���� �������������������� ����� � ������ ������� ������ �����������

�� �� ������ �� � �� ������ �� ����

� � ����� �

� � �������

� � ����������

������ ����������������

!���! ��

������ ����������������

!���! ��

������ ����������������

!���! ��

������ "!��#�#������� ��

!���! �$� $ %� � & ��

������ ����#������� ���

!���! �$� $ �%� � & ��

������ '���������

!���! $�&��

���� �������'���() ������

!���! ��*+�#���� % ����, ������#�� -

� % ����, ��"!��#�#�� - � � ���

��

Page 206: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Pasando objetos como parámetros 398

��� �������

���� ��������� ���

����� ����������� �� ����� �� �� � �� � �� � �

��! ���������

�������� � ��������"#����������������

�$ ����������

��� %% &'�(� ����� �������� �! ����&�

�!)�

��� %% &'�(� ����� �� �������� �! ����&�

��� %% &'�'�&�

)�)����&��)�&��

*

El parámetro formal ���� recibirá una copia del parámetro actual������, que se creará a través del constructor de copia.

Clases (Segunda parte)Trabajando con varios objetos → Pasando objetos como parámetros 399

Un método puede recibir como parámetro un objeto de la MISMA clase

Ejercicio. Comprobar si dos puntos son iguales.

Con una función sería:

���� �������� � ���� ������ ���� ���������

����� ������������������ �� ����

���� ���������������������� ��������� ������� ������������

����� ����������������� !�"��#$���� ���������� !�"��#$����

%% ����������������� !�&� � ��� ���������� !�&� � ����

Pero no estamos viendo programación orientada a funciones sino orien-tada a objetos ¿Cómo se definiría el método dentro de la clase?

���� �������� � ���� ������ ���� ���������

����� ������������������ �� ����

#��� ��������

��$'�(

���� ��#$��

���� �� � �

����$#(

������� � ���� ��#$������� ���� �� � ������

��)��� � � ���#$������� �� � �������

'�$ ��)��� � � � ���� ��#$������� ���� �� � �������

��#$� � ��#$�������

�� � � �� � ������

Page 207: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Pasando objetos como parámetros 400

������ ������ ���

������ ��� �

������ �������� � ���

������ ����� � �

���� ���� �� �������� ������������

������ ������� ��� ��� � ���������� ������ ��� !!

������ �������� � � ���������� �������� � �����

��

��� " �����

���� ������ ���

������� ���������# $� % ���

������� �����������# $� % #��

������ �� & �������� ���� �� �������������

La función ������ �� entre dos ������ sí la mantenemos como funciónglobal ya que es muy genérica, reutilizable en muchos sitios y los pará-metros son tipos básicos.

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 401

V.2.2. Objetos declarados localmente en un mé-todo y métodos que devuelven objetos

Dentro de un método podemos declarar objetos

� El objeto se creará en la pila, dentro del marco del método.

� Como cualquier otra variable local (automática), existirá mientrasse esté ejecutando el método. Cuando termine la ejecución del mé-todo, automáticamente se libera la memoria asociada al objeto

����� �������� ��

����� ��������

��� ����������

�������� ������ �

También podemos declarar un vector local clásico dentro de un método:

����� �������

��� ��������

��� ������������ ������� ��

��� �� �������

pero:

Page 208: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 402

Un método NO puede devolver un vector clásico

����� �������

�� � �������� �� ����� �� ����������

�� ������ �������� �

������

��� � �������

!

Un método SÍ puede devolver un objeto

Se declara local al método y se devuelve una copia.

����� ����"�����

������

#�"����� ��������

#�"����� �$%���"������

������

��� � �$%���"����� �

!

Al ejecutar la sentencia ��� � también se produce una llamada al cons-tructor de copia, ya que es necesario crear un objeto temporal con losdatos del objeto local, para así poder realizar la devolución del objeto.

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 403

Ejemplo. Progresión geométrica: añadimos un método que calcule losprimeros términos. Devuelve un vector de ������ (usamos la implemen-tación de ������ ������ que usa internamente la clase estándar �����)

���� ������ �������

��������

����� �������� ��������������

�������

������

��� ������������������

������ ���������������������

������ ��!�������� �������

������ ������������������������

���� "������������ �������

�����������������#���$��������

��� %��!���&������� �������� ��������' ��� �����#�' ������ ��������

�������

�������

��

���� %��(������)��!������

��������

������ ���!������!����

������ ������

������

%��(������)��!������������ ���!������!�������(������'

������ ���������(�������

����!������!�������!������!�������(�������'

���������������(�������

� �

Page 209: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 404

������ ��������� ��

������ �����������

������ ����� ��

������ ������

������ ����� �� ���

������ ���������� � ��� ������ �����

������ �������� �� ������

������ ���������� � ����� ������������ ���������

!"�#���$������ ������������ �� ������

!"�#���$������ �������

%�� �� & �� '& ���� � ((�

������)*���� ����� ���

������ �������

��

�� �� ��

!"�#���$������ ��������������

���+�����,�����#� ���+����� -).� .)/��

������������� & ���+�����)������������ 0��

)))))))))))))

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 405

También podríamos haber construido el objeto vector, usando el cons-tructor de copia proporcionado de oficio por el compilador:

��� �������

�� ����� �� ���� ��� ��������� �����

��� �������� � ��� ���� ����� ���� ������� ��� ������ ���

�������������

Asignaremos el objeto devuelto por un método:

� O bien a través del operador de asignación (si estádisponible)

��! ������� " # ��! ������� $�� ��%����

� O bien a través del constructor de copia:

&��� " ��! ������� " ���! ������� $�� ��%�����

Page 210: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 406

Si hubiésemos preferido devolver un objeto de la clase estándar ������,el código sería muy parecido:

��� ������� �����������

��������

������ �������� ����������� ��� � ������

������ �������� ��������

��� �� � � � �� � �� ���� � ����

���������� !���"������ ������

����� ��������

#

� � ��� ���

������ �������� �������!����� ��

������� ���������� �������� �$�%& %�'��

�������!����� � � �������� ������������ ��(��

Ejercicio. ¿Cómo sería a través del constructor de copia?

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 407

Ejercicio. Añadimos un método a la clase ��������������� que devuel-va un vector con los índices de aquellas componentes que sean mayús-culas.

���� �������� �������

�������

������ ����� ��������������

�������

��� ����������������

������ ���������������������

���� !�������� �������

�����������������"���#��������

������

���� ����������������

�������

������ ��"�� ��������������

�������

�������� ������ $����������%���������

�������� ������ �����������&%�������

��� ���� ' ���������������������

(�� ���� � ' )� � � ����� �**��

�"� ������ ' �������������������

�( � ������ �' +!+ ,, ������ �' +-+�

�����������&%�������!��������

������ �����������&%�������

Page 211: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 408

������

��

��� �����

�� ��������������� �������

�� ������������ ����������������������

�����������������

�����������������

�����������������

�����������������

��������������������� � ����������������������������

��� ���� � ��������������������������� ����!�����

"�� ��� � � #� � $ ����� �%%

���� $$ ������������������������������� $$ & &�

Ejercicio. ¿Cómo sería a través del constructor de copia?

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 409

Ejemplo. En el tema III, habíamos definido la clase ������������ de lasiguiente forma (observad que NO tiene un constructor por defecto):

��� ������� ������� � ���� ���� � ���� �

���� ������������� �� �����

� ��� �������������

� ���!

���� � "#�� $#�� "#%� $#%�

��� �!

����������������� � ����#������� ���� � ����#��������

���� � ��� #������� ���� � ��� #���������

���&��������������#������� ����#��������

��� #������� ��� #���������

�� ���&�������������� � ����#������� ���� � ����#��������

���� � ��� #������� ���� � ��� #���������

� �' �������� �������#������ � ��� #������� ((

������� �������#������� � ��� #��������� ��

"#� � ����#�������

$#� � ����#��������

"#% � ��� #�������

$#% � ��� #��������

���� � )���������

���� �*���"#% � "#��+�"#% � "#�� ,

�$#% � $#��+�$#% � $#����

�� -�� ���.�/���� ����� � ���������

"#� � "#� , ��������

"#% � "#% , ��������

�� -�� ���0���� ����� � ���������

$#� � $#� , ��������

$#% � $#% , ��������

���� � 1���2��������

Page 212: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 410

������ ���

��� �� �����������������

������ ���

��� �� ������ ��������

������ ���

��� �� ����������������

������ ���

Podemos usar la definición de la clase ������� de la página 399 y añadirun método a la clase ����� para que obtenga el segmento incluido en larecta delimitado por dos valores de abscisas:

����� ��������

������

����� ������

��!���"

������������

� ���"

������������

#��$������������ #��$�������� �� � ������������% ��� �� � ������&������

��� �� ��������������� ' ���������� �������������

��� �� ���������&���� ' ���������� ������&�����

#��$������������ ���$������ ������������% ���������������%

� ������&����% ���������&�����

������ ���$����

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 411

¿Cómo sería la llamada en el ����? Observad que no podemos hacer losiguiente:

��� �������

��� ��� ������� �� �����

�������������� ������� �� ����� �����������

������ ��� ����!��������!"� #!$��

ya que el segmento no tiene un constructor por defecto (sin parámetros).Por tanto, tenemos que recurrir a construir el segmento a partir de larecta, y asignarlo utilizando el constructor de copia:

��� �������

��� ��� ������� �� ����� �� �% & �' � �� (

�������������� ���������� ����!��������!"� #!$��� �� )����!�����

���� ** +,�-������� ������ + ** ������!-����������

Page 213: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 412

Sabemos que no podemos mezclar en una misma clase cómputos conE/S. ¿Cómo encapsularíamos la tarea de leer o imprimir los datos miem-bro de una clase? Con clases específicas que implementen dichas res-ponsabilidades.

Ejemplo. Definimos clases para leer e imprimir puntos y rectas:

�������� ��� ����

����� ��������� ����

����� �������

� ������ �����

��

����� ������

� ������ �����

��

����� ���� �������

� ������

�� ��� ��������

�������

���� ��������� ��� ������� ��� ��� ����!

�������� �������� ��� ��� ����!

� �

��� "�� ���#������$�� ����!�

��� ��������

����� ����!�

����� %& '& (�

��� �� %� ��� �� '� ��� �� (�

����� �����%& '& (!�

��� � �����

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 413

��

����� ����� ���

�������

����� ��������

� �����

����� �������� �������������������

�������� ��������������������

� �

��� �����������������������

� �� ��������

� � ! ������

� ��� �������" ��������

��� ## ��������

��� ## ��������

� � ! � ���������" ���������

�� �� � ��

��

����� �������� ���

� �����

��� ��������� � ! � ���

� �� $�$ �� � �%&�'�������� �� $"$

�� � �%&�(��������� �� $�$�

��

����� �������)�����

� �����

��� ������� �)��� ���������

� �� �������%&�*�+������'�� �� $ , - $ ��

�������%&�*�+������.�� �� $ / - $ ��

�������%&�*�+������*�� �� $ 0 1$�

Page 214: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 414

��

��� �����

��� ���������

������������ ����������������������������� �� ��� �����������

�� ���������

������������ ����������������������������� �� ���� ������������

�� � ���������

�������������� �������������������

�������������� �������������������

���������������������������� �!��������

�����"# ��������� ��������������������� $$ %���������� �� �����

���������������������������� �!��������

����� ���������� ��������������������� $$ %���������� �� �����

�������� & ����������%�����������������

���� '' ����� ����� ��

�������������������������������������

�� ���������

���� '' � �������� � ����� ��

� ��

���� '' � �� �������� � ����� ��

������������������������������������

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 415

Un método de una clase C puede definir y/o devolver un objeto de laMISMA clase C

����� �������

������� ����� �

������� ������

������

����� ������

Page 215: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 416

Ejercicio. Dado un vector de caracteres, construir otro vector nuevo conlos caracteres del actual pasados a mayúsculas:

����� ���������������

�������

���� ������ ������������

�������

������������

��� ����������� �����

����������������������������

��������������� !������

��������������� ���"�#�������

�� �� $ ��������������%����

&���� � $ '� � � ��� �((�

���"�#���������������������������������������

����� ���"�#�������

��

�� "�����

��������������� ������) �������"�#�������

��������������**��

��������������*�*��

�������"�#������ $ ������� !�������

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 417

Ejemplo. Supongamos una recta dada por Ax + By + C = 0.La ecuación de un recta perpendicular a la anterior y que pase por unpunto (x0, y0) es:

y − mx + mx0 − y0 = 0

dónde m es la pendiente de la nueva recta e igual al opuesto de la inversade la pendiente de la otra recta, es decir: m = B/A

����� ������

�� ���� �� �� ��� �����

����� ����������� �������� �����������������

������ ������ � ��

������ ������������� � � !"#�

������ �����$ � %������������� ��

������ �������� � ���������������&'��#�������� ( ������������� �

% ���������������&'��)���������

����� �����������������$* ������* ����������

���� ������������

+

+�

��� ������

������� ���������,* -��

����� ����������* -* %���� "" �$ . -� % �� � /

����� �������������������������������&�����������������������

&&&&&&&&&

+

Page 216: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 418

Ejemplo. Añadimos a la clase �������� un método para sumarle otra frac-ción.

��� ����� ������� ��� ��������� �� ������� ������

���� �������������� ��������������

��� �������� ���

!!!!!!!!!!!!!!!

������ ���

"

����� ���������

������#

��� ���������� �����������

�����#

������������ ������������������� ��� ����������������������

�� ��������������������� $% &��

��������� % ������������������

����������� % ��������������������

"

�����

��������� % &

����������� % &

"

"

��� '�����������

������ ���������

"

��� ��������������

������ �����������

"

���� '������(����

��� ���

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 419

��� � ������� ���� ����� �����

��� ��� � ��� ��������

����� ��� � ����� ��������

�� ���� �� ��� ���� ��� ��� ������

�� �� ���� ����

�� �� ������ ����

�� ���� ��� � ��� ��� � ��� ��� ���������� ����� �

����� ��� � ��� ��� ��������� ����� �

�� ������ ��� � ����� ��� � ��� ��� ���������� ������

�� ���� �� ��� ���� ���� �� ������ �����

�� ����� �! ���

���� �� �

��

�� � ����

�� ��� �������� ���� ��� ���������� ����

��� ��� �������� ���� ��� ��� ���������� ����

����" ��� #����� ��� � $%&������ � ��� ��� '( $�

����" ��� #������� ��� � $%&������ � ����� ��� '( $�

��� )) ��� #����� ����

�� (( ��� �������� ����

��� )) ��� #������� ����

�� (( ��� ���������� ����

��� )) ��� #����� ����

�� (( ��� ��� �������� ����

��� )) ��� #������� ����

Page 217: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 420

��� �� ��������������� �������

�������� ���������� ������������� �������

�������������� ��������

�������� ������������������������� �������

��������������� ��������

�������� �� ���������� �������������� ����������������

���� �� ������������ �� �� �� �� �

�� �� ������������� �������� �� � � �

�� �� ��������������� ���������

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 421

Es preferible construir la clase �������� con los métodos

��� ��������

�������

�������� � ����������� �������������� ���� �

�������� � ����������������� �������������� ���� �

��

que una clase específica para realizar operaciones con dos fracciones:

��� ���������������

��������

�������� ������������

�������� ��������������

� �����

��������������� ��������� �����������������

�������� ����������� � ��

� ������������������������������

������������������������� � ��

�������� � ����

��� ���� ���� ��� ������� ��� ���

���� ���� �� ! �����������������" ���� ���� #

����������� � ��$������� ���� %

�����������������$������� ���� #

����������� � ��" ���� ���� �

��� ������� �� ! �����������������$������� ���� #

��������������$������� �����

�������� ��� ���� ���� ��� ��� ������� ����

���"������&����

��� �� ���

��

Page 218: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 422

Si tuviésemos que definir una clase �������� para cada clase � sobre laque quisiésemos realizar operaciones con pares de objetos, el código secomplicaría innecesariamente.

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 423

Ejemplo. En la relación de problemas III se construyeron las clases�������� y �������������. Añadir un método a �������� para que de-vuelva un vector de enteros con los dígitos del primero.

������ � ��� ��� ������������� � � � �� �� ��

���� ��������������

��������

����� ���� ��� ��� � ���

��� ����������� �!���"�

��� ������#����$� ���

�#%���

�������������&'

�������#����$� ��&�'

� �

��� (����)����$� ��&'�

���#�� ������#����$� ���

��� *��� �&��� �#���'�

++++++++

��� ���,����&��� �� ��'�

++++++++

++++++++

��

���� ���������

��������

��� �������

�#%���

��������&��� #��������'

�������&#��������'�

Page 219: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 424

��� ������

��� �� �������

���� ��� ����������

�������

��������������� ���������

��������������� ����������

��������

��� �� ����������

��

��� �����

�������� ���������������� �

��� ���������!���������������

��������������� ������� "" ������ ���� ��� !��#������

������ $ ����������������������� "" �!���%�� %� ��������&�

���������!�������������� $ ������������'����(�%���

)�� ��� �$*� �+���������!��������������� �,,

�� � ++ ���������������� ++ - -�

Otra forma de construir el objeto ������ (usando el constructor de copia):

��� �����

�������� ���������������� �

��� ���������!���������������

��������������� ����������������������������� ""������ ���� %� ��!��

+����� %� �&%��� �� ���.�/

Clases (Segunda parte)Trabajando con varios objetos → Objetos declarados localmente en un método y métodos quedevuelven objetos 425

Una posible implementación del método ��������:

������������� �������� ��

������������� ����������

�� ���� � ������ � ���

�� ������������ � �������

��������������� ������

������������ � ������������ � ���

���� ������������ � ���

���� � ������������ � ���

��������������� ������

������������ � ������������ � ���

!

����������"������ ��

���#�� ����������

!

Page 220: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Objetos como datos miembro de otros objetos 426

V.2.3. Objetos como datos miembro de otros ob-jetos

¿Un objeto puede ser dato miembro de otro objeto? Por supuesto.

� Como cualquier otro dato miembro, C++ permite que sea privado opúblico. Nosotros siempre usaremos datos privados.

� Su uso sigue las mismas normas de programación que cualquierotro dato miembro. Sólo usaremos objetos como datos miembro,cuando esté claro que forman parte del núcleo de la clase.

� La clase del objeto contenido debe declararse antes que la clasedel objeto contenedor.

� La clase contenedora y la clase contenida no pueden ser la misma(con punteros sí se puede)

� En el objeto de la clase contenedora se crea una instancia de laclase contenida.

����� �������������

���� ������ � �������

��

����� ����������������

����� � �������

������������ �����������

��

Ya lo usamos en la página 366 cuando declaramos un objeto ����� den-tro de nuestra clase ���������������:

����� ����������������

������

����� ����� �������������

Clases (Segunda parte)Trabajando con varios objetos → Objetos como datos miembro de otros objetos 427

¿Qué ocurre cuando el constructor de la clase contenida tiene paráme-tros? Hay que crear el objeto con los parámetros adecuados. ¿Dónde?En la lista de inicialización del constructor.

����� �������������

�����

�������������� ���������

������

����� ������ � �������

��

����� ����������������

�����

�� ������������ �������������� ���� ��� ���!�

������������ �����������

�����

�����������������

�������������� �� "������ �� ��������� ��� ��#�����

� �

��������

��

Page 221: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Objetos como datos miembro de otros objetos 428

En vez de construir el objeto interno en la clase contenedora, tambiénpodríamos construir el objeto fuera y pasarlo como parámetro al cons-tructor. En dicho caso, debemos inicializar el dato miembro en la lista deinicialización, asignándole una copia del objeto pasado como parámetro(el compilador invoca al constructor de copia)

����� �������������

�����

�������������� ���������

������

����� ������ � �������

��

����� ����������������

�����

������������ �����������

�����

���������������������������� ������

������������������ �� ������ �� ��������� �� �� �

� �

��������

��

Clases (Segunda parte)Trabajando con varios objetos → Objetos como datos miembro de otros objetos 429

Ejemplo. Recordad la clase ������������ que contenía como datosmiembro las 4 coordenadas (��� ��) de los dos puntos que delimitan elsegmento. En su lugar, podríamos haber declarado dos puntos dentro delsegmento. Usamos la clase ������� tal y como aparece en la página 399.

����� ��������

��� ��� � �����

��

����� �������������

������

������� �����

������� �����

�� ���

�������������������� ����������� ������� ����������

����� ����������� � !! ��������� �� ����

���� ����������� !! ��������� �� ����

������� "��#���� �

���� �����

������� "��$���� �

���� �����

��� �� %������� �

��� �� ��������� ���� & ����'"��( ����� )����'"��( ����� �

��� �� ��������������� & ����'"��#������� )����'"��#������� �

���� �*����������� ���� + ��������� ����

,

��������������� + ��������������� �

Page 222: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Objetos como datos miembro de otros objetos 430

����������

��

��� �����

� ����� ���������� ����

� ����� ��������� ����

���������������� �������� ������� ������

El método que, a partir de una recta, devolvía el segmento delimitado pordos valores de abscisas podría haberse definido como sigue;

���� � ������

������

��

���� !� ���

"��#���$

������������

" %�� $

������������

���������������� ���������� %�� �%� ���&������� �� %�� �%� ���&������

�� %�� ��������&������ ' (��������%� ���&�������

�� %�� ��������&����� ' (��������%� ���&������

� ����� "��&�������%� ���&������� ��������&�������

� ����� "��&������%� ���&������ ��������&������

���������������� ��������"��&������� "��&������

��� �� ���������

��

Clases (Segunda parte)Trabajando con varios objetos → Objetos como datos miembro de otros objetos 431

Ejemplo. Añadimos una fecha de apertura a la cuenta bancaria.

����� ������

��� ��

�������� �� ���� ���� �����

������

�������������� �� ������� �������� �� ������� �������� �� ��������

���� ��������� ��

���� ������������� ��

���� �������� �� ����������� � �����

���� �������� �� ���������� � !���

�������� �� ����������"� # � �$�� %�$��$��$��$��$��$��$��$��$��$�&�

'' (���� �� )��� � *�������

��������� � � �������� + , �� � -- ������� + ��� .� �� //

������� + ,�� �� ��

������������� � � �� 0� ������ --

������ 0� ����������"������ 1 �# --

� 0� ������ -- ������ 0� � --

����������� 0� ������� --

������� 0� ������������

�� �������������� ���

�� ������� �� �

�� ���������� ���

�� ������� 2 ��

������������� � � ������

&

����

�� ������� 2 %�

������������� � � ������

&

Page 223: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Objetos como datos miembro de otros objetos 432

�� ��������������� �

�� � ������

��� � �������

�� � ������

�������� ��� ������ �

������ ���

�������� ��� ������� �

������ ����

�������� ��� ������� �

������ ���

��

���� �����������

������

!��� ������������

��"�� ����

���� ������ ������������

����� ���� ������ #�����

��"���

����������������� �����������������$ ��"�� ����������$

!��� �����������������

�������������� $

������������#���� % ����������������� $

����������������������������� && ��������� �� ���

� �

������ #����������� �

������ ������������

Clases (Segunda parte)Trabajando con varios objetos → Objetos como datos miembro de otros objetos 433

������ ������

�� ��� ������

���� ������������� ��� �����

�� ��� ���� � �

����� � ����� � ��� �����

���� �� ��������� ��� �����

�� ��� ���� � � �� ��� ���� � �����

����� � ����� � ��� �����

��

���� � ���� ��� �!�������""��!���� � #$�%& �%'& #�

�� (����

)��*� ���+���*�&$, &&, $�&&�

��� �!������� ���� �#-. �&����&%/0#, $���, ���+���*��

11111111

Page 224: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Vectores de objetos. Matrices 434

V.2.4. Vectores de objetos. Matrices

V.2.4.1. Usando vectores clásicos

Para crear un vector clásico de objetos, se usa la notación habitual:

����� ��� ����� ���

������ �������������������������

Recordemos que el compilador crea un objeto cuando se declara:

����� �������

��������

��

��� ���!"�

������ �������

��������

Lo mismo ocurre con las componentes de un vector; se crean en el mo-mento de definir el vector:

����� �������

��������

��

��� ���!"�

����� ��� ����� ���

������ ������������������������� ## $% &� ����� �� �������

��������

Clases (Segunda parte)Trabajando con varios objetos → Vectores de objetos. Matrices 435

Por lo tanto, la clase debe proporcionar un constructor por defecto, esdecir, sin parámetros.

� O bien porque no tenga ningún constructor definido, y sea el pro-porcionado de oficio por el compilador.

� O bien porque esté definido explícitamente en la clase.

Si la clase no tiene constructor por defecto, hay que crear los objetos enla misma declaración del vector:

����� �������

�����

����������� ���������

�������

��

��� ������

����� ��� ������� � ��

������� ������ !� ��"����#�������$ � ����������% ��������&���

��������

Page 225: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Vectores de objetos. Matrices 436

V.2.4.2. Usando la plantilla ������

Podemos usar la plantilla ������ donde el tipo base es una clase:

��� �����

��������

��

��� ������

������ ������� ��������������������� �� �� � ���� ��� !� ������

�� �� �����

����� "���������

���������������������#"$����%�"����������

��������

En este caso, al definir el vector, no se crea ningún objeto de �����. Porlo tanto, la clase ����� no está obligada a proporcionar un constructorpor defecto (sin parámetros).

Clases (Segunda parte)Trabajando con varios objetos → Vectores de objetos. Matrices 437

V.2.4.3. El operador de asignación y los vectores

����� �������

��

� � ��� ��

�� �� � � ������� � ���

������� ������������ ����!�������"� ## $% &� ���� �� �� ����

������� ' ��� ����

������������ ����!�" � ' ��� ���� ## ���( ���) � ��� �� ����

Si tenemos un vector de objetos y queremos asignarle aalguna componente un objeto, el tipo base del vector debeproporcionar un operador de asignación (tanto si usamosvectores clásicos como si usamos la plantilla ������)

� Ya sea el proporcionado de oficio por el compilador.

� Ya sea el sobrecargado por el programador (la so-brecarga del operador de asignación se verá en elsegundo cuatrimestre)

Recordemos que en el caso de que hayamos definido un dato miembroconstante (no estático) en una clase, el compilador no puede proporcio-nar de oficio un operador de asignación por defecto (ver página 389) Enestos casos, no podremos utilizar dicha clase como tipo base de un vec-tor (clásico o la plantilla ������), produciéndose un error de compilación.

Page 226: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Vectores de objetos. Matrices 438

V.2.4.4. Matrices

Una vez que sabemos definir objetos dentro de otros, podemos definiruna clase matriz obligando a que únicamente puedan añadirse filas ente-ras. Para ello, definiremos en la sección ������� un vector de vectores.

�� �������� ���������

��������

����� ���� ��� ������������ � ���

�������� �������� ������������ �!������������"� ##�� ����� �� �$%���&

��� '���(����� ��

�($���

�������� ��������)*

�'���(����� �)�*

� +

��� ���,����� �)*�

���(�� '���(����� ��

+

�-�� .������)��� '��/ ��� ��(���*�

���(�� ������������ �!'��"0.������)��(���*�

+

�������� �������� ���)��� �� ����'��*�

���(�� ������������ �!�� ����'��"�

+

��� ���� �)�������� �������� �(����'��*�

�' )'���(����� � 1 ������������*�

������������ �!'���(����� �" � �(����'���

'���(����� �22�

+

+

+�

��� ����)*�

�������� �������� '����

Clases (Segunda parte)Trabajando con varios objetos → Vectores de objetos. Matrices 439

��������������� ��� ���

��������������� ��� ���

� � ������ ��

��� ���� ���������

��� ���� ����� ���

��� ���� ���������

��� ���� ���������

��� ���� ���������

������ ������� ����

������ ������� ����

������ � � ��������������������

��� �� � ��� � �� ��� ������ �� ���!!�"

��������������� #����������

#��������� � ��������������

��� �� � ��� � �� ��� #����������$��������������� ���!!�

���� #����������%���� ��������

���� &' &�

(

(

Si se quiere, puede mantenerse la misma interfaz pública (añadir y de-volver filas enteras) pero cambiar la implementación interna de la clase,usando una matriz clásica de dos dimensiones

�)� ������*��#�+��,-�.��-/�01+��,-�.�./��2�01

Page 227: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Vectores de objetos. Matrices 440

La elección de una implementación u otra dependerá del tipo de opera-ciones que vayamos a realizar y si resulta más cómodo o eficiente hacerlocon un tipo u otro.

El método ���� devuelve una copia de la fila de la matriz.Si modificamos la copia, no se modifica la correspondientefila de la matriz.

�������������� �����

���� � ��� ����������

���������������� �� �� � ������� �� ��� ��

Ampliación:Tal y como se indicó en la página 393, los lenguajes orientados a objetosno suelen trabajar con copias de objetos, sino que lo usual es que los mé-todos devuelvan referencias a objetos. Por lo tanto, una sentencia análogaa ��������������� sí modificaría la fila de la matriz. Esto ocurre porquesólo hay un objeto, aunque es accesible desde muchos sitios y con nom-bres distintos. Esta forma de trabajar se consigue en C++ usando punteros(pointers) (se verá en el segundo cuatrimestre)

Clases (Segunda parte)Trabajando con varios objetos → Vectores de objetos. Matrices 441

Ejemplo. Supongamos que queremos encontrar un carácter. Para devol-ver la fila y columna en la que se encuentra, podemos definir un ������:

������ �������� ���

�� ���

�� ��� ���

��

���� �����������������

�������������

�������� �� �� ����������������� ���������

��� ���������� � �����

�������� �� ������ ������������� � �� !� ��

�� ! "�

�#��������������� ���

��� ��$� %����������� && '���������� � ((��

��� �"�$�

"% �����)�*���+,�-���.�������� && '�����������

"((��

�� � �����)�*���+,�

� ����/� �����"� �� ���������

������ ���������������� � �

������ ����������������� �� � "�

���������� � �����

������ ������ ��������������

��

Page 228: Fundamentos de Programacion

Clases (Segunda parte)Trabajando con varios objetos → Vectores de objetos. Matrices 442

Ejemplo. Definimos la clase matriz de caracteres usando la plantilla es-tándar ������ (vector de vectores). Cambiamos la interfaz pública:

��� ������ ���������

��������

������ ������� ������� ���������������

�������

��� ����������������

������ ���������������������

���� !����������� "���# ��� ���������

������ ������������������"�����������������

$$ � �����

$$ ������ ��������������%"���&%�������&�

������ ������ ���� ���� �������"�����

������ �������������������������"�����

���� '������������ ������ ������"�����

����������������������(�������"�����

��� �������

������ �������� �������

������ ������ �����������������)*+�

������ ������ ����������������������)*+�

�����������������)*+��������(�,�,��

�����������������)*+��������(�,�,��

�����������������)*+��������(�,�,��

�����������������)*+��������(�,�,��

Clases (Segunda parte)Trabajando con varios objetos → Vectores de objetos. Matrices 443

������������������������ ��������������

������������������������ ��������������

������������������������ ��������������

������ ����������������������������

������ ���������������������������������

������ ������ ���� �!��

���� �!� " ������ #�!��$��

���� �!� ����������%��� && '� � ���� ��� !� �!� �� !� ������%

Page 229: Fundamentos de Programacion

Clases (Segunda parte)Diseño de una solución → 444

V.3. Diseño de una solución

V.3.1. Funciones globales versus métodos

Hemos visto que las funciones pueden definirse:

� Encapsuladas dentro de una clase (métodos)

� Globales, fuera de las clases

Como norma general, no usaremos funciones globales. Sin embargo, enocasiones, puede justificarse el uso de éstas:

� cuando sean funciones auxiliares genéricas que podamos utilizaren muchas clases diferentes,

� cuando sean funciones definidas para trabajar con tipos básicospredefinidos.

Clases (Segunda parte)Diseño de una solución → Funciones globales versus métodos 445

� Usando un método privado

����� ������

�������

����� ��������

����� ��������

�� ��������������� ��� ����� ��� �

������ ����������� �� ��!�

"

������

����������� ������������ ����� ������������

����������������������

��������������������

� "

����� #��$���������

������ ��������

"

����� #��%����������

������ ��������

"

�� &������'� ������ ��' �����

������ ������������������ ��' ���(#��$��������� ))

������������������ ��' ���(#��%�����������

"

"�

Esta aproximación es correcta, pero ¿y si necesitamos comparar dosdoubles en otras clases? Habría que repetir el código del método��������� en cada una de estas clases.

Page 230: Fundamentos de Programacion

Clases (Segunda parte)Diseño de una solución → Funciones globales versus métodos 446

� Usando una función global

�������� ��� ����

����� ��������� ����

�� ��������������� ��� ����� � � �

��� � ��������� � � �����

����� !���"#�

� �$���%

����� ��������

����� �������

������%

!���"#������ �������!���� ����� ������!����

%���������������!�����

������� ������!����

����� &��'���������

��� � ��������

����� &��( ���������

��� � �������

�� )������*� �!���"# � *������

��� � ������������������ � *����+&��'��������� ,,

���������� ������� � *����+&��( ����������

��� �������

'-�. �����/� ���� ��� �� ��������� ����������

Clases (Segunda parte)Diseño de una solución → Funciones globales versus métodos 447

�������� ��� ����

����� ��������� ����

�� ��������������� ��� ����� � � �

��� � ��������� � � �����

����� ! ��������"���� ���

������#

����� ��� �����

$$$$$$$$$$$$$$$

$$$$$$$$$$$$$$

��� �������

! ��������"���� �� ���%� ��������� � �%� ���������

�� ��%��������

$$$$$$$$$$$

��%������� � �������������%� ��������$��� �����

� �%� ��������$��� ������

$$$$$$$$$$$

Otros ejemplos de funciones que podríamos poner globales:

��� &�'��(���)�*�� ���� ��%���� � ��� � %���� �

����� &�'�� ������ ��% ���� ����� � % ����

�+� ! ���� ��%�%&�,������ ��+� ��%�� ���� �

Page 231: Fundamentos de Programacion

Clases (Segunda parte)Diseño de una solución → Funciones globales versus métodos 448

� Usando un método público

¿Nos vale poner el método �������� como público y así poder usarloen otros sitios? Poder, se puede, pero no tiene sentido:

��� ��� ����

����� �

����� ������

����� ��������

���� �������������� ���� ����� � ��� �

� ��� ��������� ��� �� �!�

"

######

�������

######

"�

��� $���������%��������

����� �

����� �&��� �

�������

����� �&��� ���

� ��� �&��� �

"

##############

"�

�� &������

$���������%������� ���' ���������� � ��' ����������

��� ��� (�'��� �'�(��'��'��� ��)#*� +#,��

���� ��'������

###########

��'����� � (�'��� �'�(��'��'��� �#���������

���' ���������#�&��� ���

� ��' ���������#�&��� ����

Clases (Segunda parte)Diseño de una solución → Funciones globales versus métodos 449

Ampliación:Muchos lenguajes de programación prohíben las funciones globales. Sinembargo, proporcionan un mecanismo muy similar, que son las clases es-táticas (static class). Éstas son clases que contienen las funciones que no-sotros pretendemos utilizar de forma global, pasándoles como parámetroslos datos sobre los que deben actuar (al contrario que los métodos, que ac-túan sobre los datos del objeto y se les pasa como parámetro informaciónadicional). Las clases estáticas tienen la peculiaridad de que el compiladorte ofrece una instancia que se llama igual que la clase y el programador nopuede crear otras instancias. La diferencia con las funciones globales esque la llamada a la función debe ir precedida del nombre de la clase. Esterecurso también está disponible en C++.El uso de clases estáticas, al igual que las funciones globales, debe limitar-se a las mismas situaciones que hemos indicado en el tema.

Page 232: Fundamentos de Programacion

Clases (Segunda parte)Diseño de una solución → Tipos de relaciones entre clases 450

V.3.2. Tipos de relaciones entre clases

Hasta ahora hemos trabajado con clases aisladas.

La resolución de un programa complejo necesita la construcción de mu-chos objetos. Éstos no funcionan de forma aislada sino que cooperanentre sí.

� El programador diseñará la solución estableciendo las relaciones(relationships) entre las clases.

� Estas relaciones se determinan en función de las responsabilida-des de las clases.

– ����������������� ��� se relaciona con �����

– ��������������� se relaciona con ���������������

– ���� ���� se relaciona con ����� ���������

– ��� ��� ����� se relaciona con ���� �

– ��� ����� se relaciona con ��� ��� �����

� Las relaciones entre las distintas clases nos indican cómo se co-munican los objetos de esas clases entre sí.

� Una vez realizado el proceso de diseño, se procederá a implemen-tar la solución (en nuestro caso, en C++)

Clases (Segunda parte)Diseño de una solución → Tipos de relaciones entre clases 451

Tipos de relaciones entre clases:

� Dependencia (Dependency)

Establece una relación de uso esporádica.

� Asociación (Association)

Establece una relación estructural o conexión permanente entreobjetos (o, al menos, durante gran parte de la vida de éstos)

� Generalización/Especialización (Generalization/Specialization)

Establece una dependencia entre clases a través de una relaciónde herencia (inheritance) → segundo cuatrimestre

La determinación de las clases, sus responsabilidades yrelaciones es el primer paso en el diseño de una solución.

La implementación en cualquier lenguaje (por ejemploC++) será siempre posterior.

Page 233: Fundamentos de Programacion

Clases (Segunda parte)Diseño de una solución → Relación de dependencia 452

V.3.3. Relación de dependencia

Establece una relación de uso esporádica.

� Una clase Servidor � depende de otra clase Cliente �, cuando en al-gún momento determinado, cualquier objeto de � necesite ejecutaralgún método de un objeto de �.

� Para indicarlo en UML, se usa una flecha discontinua:

� Situaciones típicas:

– Objetos de � pasados como parámetros a métodos de �.

– Objetos de � declarados localmente dentro de métodos de �.

– Objetos de � devueltos como parámetros por métodos de �.

¿Por qué esta dependencia? Porque cualquier cambio en � implica uncambio en �. Al revés, no.

Clases (Segunda parte)Diseño de una solución → Relación de dependencia 453

El ejemplo visto en la página 395 muestra que hay una dependencia entre����� y ����� ya que, en alguna ocasión (cuando se ejecuta el método��� ��� por ejemplo) la recta necesita tener acceso a un punto.

Page 234: Fundamentos de Programacion

Clases (Segunda parte)Diseño de una solución → Relación de asociación 454

V.3.4. Relación de asociación

� Dos clases � y � mantienen una asociación cuando los objetos deambas clases mantienen una relación estructural permanente, esdecir, que se mantiene durante toda la vida de los objetos (o, almenos, durante un tiempo prolongado)

� Para indicarlo en UML, se usa una flecha continua:

� Situaciones típicas:

– Una clase � que tiene un dato miembro (público o privado) detipo �.

– Una clase � que tiene un dato miembro (público o privado) detipo �, y viceversa, � tiene un dato miembro de tipo �.

Implica conocimientos más avanzados.

� La asociación implica una relación más fuerte que la dependen-cia. Al igual que ocurría con la dependencia, cualquier cambio en �

afecta a �.

Clases (Segunda parte)Diseño de una solución → Relación de asociación 455

Ejemplo. En la página 429 vimos que un objeto de la clase������������ contiene dos objetos de la clase � �����. Para que exis-ta un segmento, deben existir siempre los dos puntos. Por tanto, la rela-ción entre ambas es de asociación:

Nota. Observad que también hay una relación de dependencia entre am-bas clases ya que, en algún momento determinado, la ejecución de al-guno de los métodos del segmento devuelve un punto. En estos casos,se omite la flecha que indica la relación más débil (la de dependencia).

El diagrama completo se muestra en la siguiente página:

Page 235: Fundamentos de Programacion

Clases (Segunda parte)Diseño de una solución → Relación de asociación 456

Clases (Segunda parte)Diseño de una solución → Relación de asociación 457

Ejemplo. En la página 431 vimos que un objeto de la clase ������������

contiene (relación estructural) un objeto �����. Mientras exista la cuenta,existirá la fecha de apertura correspondiente. Por tanto, la relación seajusta a una asociación.

Page 236: Fundamentos de Programacion

Clases (Segunda parte)Diseño de una solución → Acoplamiento 458

V.3.5. Acoplamiento

Si una clase tiene una relación de dependencia o de asociación con mu-chas otras, cualquier modificación de éstas puede afectar a la primera.Esto se detecta fácilmente en el diagrama viendo las cajas de las quesalen flechas.

Cuando una clase usa (depende de) otras clases, se produce una depen-dencia entre ellas, también llamada acoplamiento (coupling).

Tipos de acoplamiento:

� Acoplamiento fuerte (Tight coupling)

Se produce cuando muchas clases dependen de muchas otras.Cualquier cambio en una obliga a un cambio en las otras.

� Acoplamiento débil (Loose coupling)

Se produce cuando no se da la anterior circunstancia:

– Hay bastantes clases que no dependen de ninguna otra.

– Cada una de las restantes clases no dependen de un gran nú-mero de clases.

Clases (Segunda parte)Diseño de una solución → Arquitectura por capas 459

V.3.6. Arquitectura por capas

Al separar entradas de datos, salida de datos y cómputos, conseguimosque el desarrollo de las clases que realizan los cómputos propios de laaplicación no dependa del desarrollo de las clases dedicadas a las E/Sde datos.

En general, el diseño de una solución pasa por una organización en ca-pas, obteniendo lo que se denomina una arquitectura en varias capas(multi-layer architecture)

En el gráfico siguiente se presenta la arquitectura típica en 3 capas demuchas aplicaciones de gestión.

Ampliación:En el diseño de una solución completa, también ha de tenerse en cuenta laorganización física de ésta (ordenadores servidores y clientes en los que sedistribuirá la aplicación) En este contexto se usa el término arquitectura envarios niveles (multi-tier architecture)

Page 237: Fundamentos de Programacion

Clases (Segunda parte)Diseño de una solución → Arquitectura por capas 460

Clases (Segunda parte)Diseño de una solución → Casos prácticos de diseño 461

V.3.7. Casos prácticos de diseño

En este tema se han introducido conceptos básicos de programación conC++, viendo cómo se produce la copia entre objetos, cómo pasar objetoscomo parámetros, etc. Una vez fijados estos conceptos, hemos aumen-tado el nivel de abstracción introduciendo los conceptos de cohesión,relaciones entre clases, etc.

En el desarrollo de un proyecto software, el primer paso será siempreel diseño abstracto de la solución. La implementación en un lenguajeconcreto será posterior.

En este apartado veremos algunos casos prácticos con los pasos a se-guir a la hora de plantear la solución a un problema.

Page 238: Fundamentos de Programacion

Clases (Segunda parte)Diseño de una solución → Casos prácticos de diseño 462

V.3.7.1. Matriz de caracteres

Queremos construir un sencillo programa que necesitará manejar vecto-res y matrices de caracteres e imprimirlos en pantalla.

� Determinación de responsabilidades:

– ��������������� se ocupa de representar un vector de ca-racteres, con funcionalidades como permitir añadir caracteres,obtener el tamaño actual, etc.

– �������������� se ocupa de representar una matriz de ca-racteres, como un vector de ���������������. Tendrá fun-cionalidades como permitir añadir un vector de caracteres, ob-tener el tamaño actual, obtener una fila determinada, etc.

Observad que permitimos que cada fila tenga un número dis-tinto de columnas.

– �������������������� se ocupa de imprimir un vector decaracteres en el periférico de salida de datos por defecto.

– ������������������� para leer datos desde un periférico yllenar vectores de caracteres.

– ������������������� se ocupa de imprimir una matriz decaracteres en el periférico de salida de datos por defecto.

� Relaciones entre las clases:

– ¿Cómo están ligadas las clases ��������������� e ��������������������?

Un objeto de ��������������������� necesitará, en al-gún momento, acceder a los datos de un objeto de���������������.

En otro momento, el mismo objeto ��������������������

querrá acceder a los datos de otro objeto de���������������, para imprimir otro vector distinto.

Clases (Segunda parte)Diseño de una solución → Casos prácticos de diseño 463

Por tanto, la relación es temporal y se ajusta a una de-pendencia en la que pasamos como parámetro al métodode �������������������� encargado de imprimir el objeto ������������� sobre el que va a trabajar.

– De igual forma, un objeto de la clase �������� ������������

necesitará crear localmente un objeto de la clase�������������������� cuando ejecute el método deimprimir. Posteriormente, ya no lo necesitará.

– ���������������� también depende de ������������� ya que, en algún momento, un objetode la primera clase devolverá un objeto de la segunda (cuandose ejecute el método ���������)

– La relación entre � ������������ y �������������

es más fuerte ya que la primera contiene un vector de �������������. Es una relación de asociación.

También hay una relación de dependencia ya que la cla-se � ������������ contendrá un método para devol-ver una fila determinada, es decir, un objeto de la clase �������������. En cualquier caso, como es una relaciónmás débil que la asociación, únicamente se mostrará esta últi-ma (realmente una asociación es un tipo fuerte de dependen-cia)

El diseño completo de la solución quedaría:

Page 239: Fundamentos de Programacion

Clases (Segunda parte)Diseño de una solución → Casos prácticos de diseño 464

Clases (Segunda parte)Diseño de una solución → Casos prácticos de diseño 465

Una vez hecho el diseño de la solución, veamos una posible implementa-ción en C++:

����� ���������������

�������

���� ��� �� ������� � ���

���� ���������������������

�� ��� ���!����

� "����

���������������#$

���� ���!���#�$

%

�� ���&���!���#$

�� �� ��� ���!����

%

��� '������#$

��� ���!��� � ��

%

��� ������#���� � ��$

�( #��� ���!��� ) �������$

��������������� ���!���� � � ���

��� ���!���**�

%

%

���� +��,��#�� ������$

�� �� ��������������������

%

%�

Page 240: Fundamentos de Programacion

Clases (Segunda parte)Diseño de una solución → Casos prácticos de diseño 466

����� �����������������

�������

������ ����� ��� ������������� � ���

����������������� ����� ����!�"�������������#� $$�� ����� �� �%&����'

��� (�����)�����!���

)%����

����������������*+

�(�����)�����!��*�+

� ,

��� �����-�����!��*+�

���)�� (�����)�����!���

,

�.�� /�� ���� *��� (���0 ��� ���) ��+�

���)�� ����� ����!�"(���#1/�� ����*���) ��+�

,

���! ����!�*����������������� �)����(���+�

�( *(�����)�����!�� 2 �������������+�

����� ����!�"(�����)�����!��# � �)����(����

(�����)�����!��33�

,

,

����������������� ����*��� ��!����(���+�

���)�� ����� ����!�"��!����(���#�

,

,� $$ 4�%�5� 6)� �7�!�� 8��!�� �� � ��!�(���0 /�� ���0 ��� 111

����� � ���������������������

)%����

���! � �� �*�����9 ����&�0 ����������������� )��������+�

��)� 22 ����&� 22 :;:�

(�� *��� ���� �2)��������1�����-�����!��*+� �33+

��)� 22 )��������1/�� ����*�+�

��)� 22 :;:�

Clases (Segunda parte)Diseño de una solución → Casos prácticos de diseño 467

��

����� �������� ��������� �� ���� �� ��� ����� ����� ������

������� �� ������ ��� �� ��� �� �� ������

��� ���� ��������� �� ����������

��� ����� �������������

������� ����� �� ������� ������� !������"

�������

�������� ��������#����� ������������$ ���� ������������%

���������#������������%$

������������#������������%

��� &���'�����#%�

����(���#������������%�

��� �����'�����#%�

����(����#%�

)����� �������� �������#%�

)����� �������� ����������

���� ��������

������� * ����(��#%� �� ���� "" �������� � ��� ����������

�� �� �� ������� �� �����(

�� ����(��#% �+ �� ���

,���� #������� -* ��������%�

���������(&�����#�������%�

������� * ����(��#%�

����� ����������

Page 241: Fundamentos de Programacion

Clases (Segunda parte)Diseño de una solución → Casos prácticos de diseño 468

���� ���������

� ������ ���

� ���� �� ���������� �� �� ����� ����

��

��� ���� �������������� � �

������

!��" ������ ����# � ��$ %# � ���& ����# � ��$ %���%����&

�������������� � ���%��������

���� ��' ���������� � ������%�����

���� (( � ��$ %# � ����

��� ��� �)*� �(���%�������+���,������"��� �--��

������%����������� � ��$ %���%����& ���%�������+�������

��

��� ������

���� ��' ���������� � ������%! ����%������ � �

�������������� � �������

���� �������������� � ������%�������

. ����' ���������� � �����%! ���� %������ � /����0����"���1�/��

�����%! ���� %������ � �2�� +��3 ����

43�� �����%! ���� %������ � �����������

��' ���������� � ! ���������%! ���� %������ � �. ' �������

�������2���" ! ������

�����%! ���� %������ � ��� ���+��3 ����

������%������������� /5����� " �� ������ /&/5�+��� /& ��������

���������

Clases (Segunda parte)Diseño de una solución → Casos prácticos de diseño 469

V.3.7.2. Gestión de nóminas

Descripción de requerimientos

Una empresa quiere gestionar las nóminas de sus empleados (empeza-mos a ver este ejemplo en la página 290 y en la relación de problemas III).El cómputo de la nómina se realiza basándose en los siguientes criterios:

1. Hay cuatro tipos de categorías laborales: Operario, Base, Adminis-trativo y Directivo.

2. Se parte de un salario base que depende de la antigüedad del tra-bajador y de su categoría laboral. Dicho salario base se incrementacon un tanto por ciento igual al número de años trabajados.

3. Los trabajadores tienen complementos en su nómina por el nú-mero de horas extraordinarias trabajadas. La hora se paga distintasegún la categoría. Además, al complemento que sale al computarel número de horas extraordinarias, se le aplica una subida con untanto por ciento igual al número de años trabajados.

4. Se almacenan en disco los datos de los trabajadores, tanto los per-sonales, como los del puesto de trabajo (así como las horas detrabajo extraordinarias realizadas por cada uno).

5. También se almacenan en disco las tablas salariales (el saldo basede cada una de las categorías laborales y la cuantía percibida porhora)

Diseño de la solución

� Determinación de responsabilidades:

– ����� se encargará de representar una fecha y proporcionarámétodos para obtener, por ejemplo, el número de días pasados

Page 242: Fundamentos de Programacion

Clases (Segunda parte)Diseño de una solución → Casos prácticos de diseño 470

hasta hoy.

– Para representar un trabajador, distinguiremos entre sus datospersonales y los del puesto de trabajo. Para ello, definiremoslas siguiente clases:

◦ ������������� para almacenar los datos personales co-mo la fecha de nacimiento, su dirección, etc.

◦ ���������� ���� para almacenar los datos del puesto detrabajo (categoría laboral, fecha de incorporación, etc)

◦ ���������� será una clase que aglutine la información dadapor las dos anteriores.

– Las clases �������������� y �����������������������������

se encargarán de almacenar las tablas salariales: la cuantíabase de cada categoría laboral y la cuantía a pagar por horaextraordinaria trabajada (según sea la categoría laboral).

– La clase ������ se encargará de computar los salarios en fun-ción de la política descrita anteriormente.

– Los datos históricos se almacenarán en:

◦ Un fichero de clientes, que incluirá los datos personales,del puesto de trabajo y el número de horas extraordinariastrabajadas.

La clase ������������������ tendrá la responsabilidad deleer dichos datos.

◦ Sendos ficheros con las tablas salariales básicas: en unfichero se guardan los cuatro sueldos de cada categoríalaboral y en otro fichero las cuatro cantidades que repre-sentan el complemento por hora extraordinaria de cada ca-tegoría.

La clase ������������������� tendrá la responsabilidadde leer dichas tablas de los ficheros.

Clases (Segunda parte)Diseño de una solución → Casos prácticos de diseño 471

� Relaciones entre las clases:

– Las clases �������������y ���������� ���� tendrán una re-lación de asociación con ����� ya que ambas contienen un da-to de este tipo.

– Todos los métodos de la clase ������ necesitarán acceder ala información suministrada por las tablas salariales por lo quehabrá una relación de asociación entre ������ y las clases�������������� y �����������������������������.

Cuando queramos saber el salario de un trabajador, la clase������ necesitará (en ese momento y no antes) conocer susdatos laborales (categoría laboral y antigüedad) por lo que ha-brá una dependencia entre ������ y ���������� ����. No ne-cesitará conocer sus datos personales, por lo que ������ nodependerá de �������������.

– ������������������ dependerá de ���������� ya que la primera,en algún momento, construye objetos de la segunda, leyendolos datos desde un fichero.

De la misma forma, ������������������� dependerá de�������������� y �����������������������������.

En la siguiente página se muestra el diseño completo de la solución. Sepuede obtener este gráfico en el enlace:

�������������� ��������� ��������������

En las clases de prácticas se verá una posible implementación en C++.

Page 243: Fundamentos de Programacion

Clases (Segunda parte)Diseño de una solución → Casos prácticos de diseño 472

Capa:AccesoaDatosCapa:LógicaAplicaciónCapa:Presentación

Clases (Segunda parte)Tratamiento de errores con excepciones → 473

V.4. Tratamiento de errores con excepcio-nes

Supongamos que se violan las precondiciones de un método ¿Cómo lonotificamos al cliente del correspondiente objeto?

����� ���������������

�������

���� ��� �� ������� � ���

���� ���������������������

�� ��� ���!����

� "����

#########

��� ������$���� � ��%

�& $��� ���!��� ' �������%

��������������� ���!���� � � ���

��� ���!���((�

)

����

� '' *� ��+ �,������ � &�������*�

)

)�

�� ,���$%

��������������� �����

����#������$-�-%�

##########

����#������$-�-%� .. /� +� � ��"� �0 *� ��+ �,������ � &�������*

Ya sabemos que esta solución rompe la norma básica de no mezclarC-E/S

Page 244: Fundamentos de Programacion

Clases (Segunda parte)Tratamiento de errores con excepciones → 474

El método ������ ha sido el encargado de tratar el error producido por la

violación de la precondición. Esto es poco flexible

Si se detecta un error en un método (como la violación deuna precondición) la respuesta (acciones a realizar paratratar el error) debe realizarse fuera de dicho método

La solución clásica es devolver un código de error (bool, char, entero,enumerado, etc)

��� ����� �����������

��������

����� � �� ��� ������ � ���

���� ���� �������� ���������

��� � ���� ����!�� �

� "����

#########

��� ������$���� � �� %�

��� ��� � � ��

�& $� ���� ����!�� ' ������%�

���� �������� �� ���� ����!�� � � � �� �

� ���� ����!�� ((�

)

���

��� � � *�

��� �� ��� ��

)

)�

��� +���$%�

����� ���������� ���� ��

Clases (Segunda parte)Tratamiento de errores con excepciones → 475

��������

�� ��������� ������� �� ��

��� �� �� � � ��������� �������������

�����

���� � � �����!� ��� �� � "

#�

Problema: El excesivo anidamiento oscurece el código:

��� � �����

$�%���& ����� �����

�� ��������� ������� �� ��

��� �� �� � � ��������� �������������

�����

�� ��������� ������ �� ��

��� �� �� � � ��������� �������������

����

�� ��������� ������� �� ��

��� �� �� � � ��������� �������������

����

���� � � �����!� ��� �� � "

#�

#

Page 245: Fundamentos de Programacion

Clases (Segunda parte)Tratamiento de errores con excepciones → 476

Solución: Utilizar el mecanismo de gestión de excepciones.

En PDO una excepción (exception) es un objeto que contiene informaciónque es traspasada desde el sitio en el que ocurre un problema a otro sitioen el que se tratará dicho problema.

La idea es la siguiente:

� Un método genera una excepción con información sobre un error.

La generación de la excepción se realiza a través del operador�����

� El flujo de control sale del método y va directamente a un lugar enel que se gestiona el error.

Dicho lugar queda determinado por un bloque ��� � ����.

En C++, una excepción puede ser de cualquier tipo de dato: entero, real,nuestras propias clases, etc. Por ahora, utilizaremos clases de excepciónestándar, incluidos en la biblioteca ��� ����, como por ejemplo:

� Clase �����������:Se usa para notificar que ha habido un error lógico como por ejem-plo la violación de una precondición de un método.

� Clase �������������:Se usa para notificar que ha habido un error de ejecución comopor ejemplo una división entera entre cero o un acceso a un ficheroinexistente.

Hay una sobrecarga de los constructores de dichas clases que aceptauna cadena de caracteres. En dicha cadena indicaremos el error que seha producido.

Una vez creado el objeto de excepción se consulta dicha cadena con elmétodo �����.

Clases (Segunda parte)Tratamiento de errores con excepciones → 477

�������� ������ ��

��� ������������������

�������

����� ���� ��� ������� � ��

�!�� ������" ������#�������$

��� �����"�����%���

�&����

'''''''''

���� ������(�!�� �����)�

�* (�����"�����%��� �������)�

������" ������#�����"�����%���$ � �����

�����"�����%���++

,

���

�!��- ��.��"�����(/�� !�0 ��1 ������ �*�������/)

22 3� ���� �� �&4��� �� �� ���� ��.��"�����

22 5� *'������� ��� ��� 16����

,

,

��� 1���()�

����������������� ������

��0�

������'������(7!7)

''''''''''

������'������(7�7) 22 3� 0� �� ��&� �� 5� *'������� ���� �� ����!

''''''''''

,

����!(��.��"����� ���� ����)�

���� /5���� �8.���� / ���� ����'-!��()

,

Page 246: Fundamentos de Programacion

Clases (Segunda parte)Tratamiento de errores con excepciones → 478

Por ahora, el tratamiento del error dentro del ����� únicamente consisteen informar con un ����.

Si no construimos el bloque ��� ����� y salta una excepción, el programaabortará.

� ��� �

����������������� �������

��������������� �

����������

��������������� � �� � �� � ���� �� � !��"���� ������

Clases (Segunda parte)Tratamiento de errores con excepciones → 479

El resto de métodos también pueden generar excepciones:

����� ���������������

���������

��� ��������� ������������ ���� ����������

�� ������������� � ���� �� ������������� !�

�� ������������ � �������������

�� ��� � ����������� " ������������� " �##�

�����������$�% �����������$�#&%"

�����������$�����������% ���������"

�����������''"

(

����

��) �*��������+,����-� �� �������-� ���.����+�"

(

("

�� /�����

��������������� ����"

�0

�����1������2�2�"

����������

������������3!� 2�2�"

����������

(

������*������� �4�������

�� �� +5��� �-*��6 + �� �4�������)����"

(

Según sea la excepción que se lance el método )���� devolverá ,����-�

�� �������-� ���.���� o bien 7 ��0 �/������ ����������.

Page 247: Fundamentos de Programacion

Clases (Segunda parte)Tratamiento de errores con excepciones → 480

En el mismo bloque ��������� podemos capturar excepciones generadaspor métodos de distintas clases:

��� �� ���������� � �

���������

��

��� ������������ � �

���������

���� ����� ��� ���������� � �� ���������

�� ��������������� � � �! "�#��

$������%������&��������������' ( �� ��������

��������������))�

����* ��+��� �����,-� ��� $. ���� ��%���/� ,��

��

��� $������

�� ���������� � � �����

������������ � $������

����

� ���������� �0�0��

����������

$����������� �� ������

����������

��������+��� ���� 1� %������

���� �� ,2���� �3+���4 , �� 1� %�����*������

Clases (Segunda parte)Tratamiento de errores con excepciones → 481

¿Y si se generan excepciones de tipos distintos? Hay que añadir el �����correspondiente.

����� ����������������

�������

���� ��� ��������

���� ����� �����������

������� ����� �� ��� ��� �� �� �����

�������

���������������������� ������������������

��� �������������

�����������������������

�����������������������������

��� !��"������

����#����������������

�� �����#�������

����� �����$��� % &' �� �� ������ ��� ����� & (

�����������

��) ��������������$�����

��� ����"������ ####

*������������� ��������� ####

�� +�,-����� ####

��� ������

*������������� �����

*�*���.�������� ����.�

���� ��� ������� % /0/�

���������������� �����������&-���'�����#�1�&� ���������

Page 248: Fundamentos de Programacion

Clases (Segunda parte)Tratamiento de errores con excepciones → 482

����

�������� ������������ ���

����������

��� ��������������

����������

����������������� ���

����������

������� ������ � ������� ���

� �� �� !�� � �"��� # �� ������� ��$������

���������������� � ������� ���

� �� �� !�� � �� �%�����"�# �� ������� ��$������

A tener en cuenta:

� Si se produce una excepción de un tipo, el flujo de control entra enel ����� que captura el correspondiente tipo. No entra en los otrosbloques �����.

� Si se omite el ����� correspondiente a un tipo y se produce unaexcepción de dicho tipo, el programa abortará.

El tratamiento de errores de programación usando el me-canismo de las excepciones se basa en asociar el errorcon un TIPO de excepción

Clases (Segunda parte)Tratamiento de errores con excepciones → 483

Hay que destacar que cuando se produce una excepción en un método, elflujo de control va saliendo de todas las llamadas de los métodos, hastallegar a algún sitio (por ahora será usualmente en la función ����) en elque haya una sentencia ������. Este proceso se conoce como stackunwinding (limpieza de la pila sería una posible traducción)

Page 249: Fundamentos de Programacion

Clases (Segunda parte)Tratamiento de errores con excepciones → 484

Consideraciones finales:

� El uso de excepciones modifica el flujo de control del programa.Un mal programador podría forzar su uso en sustitución de estruc-turas de control básicas como las condicionales.

Siempre reservaremos el uso de excepciones para programar ca-sos excepcionales, como por ejemplo, cuando la violación de lasprecondiciones de un método pueda tener efectos potencialmentepeligrosos (recordar lo visto en la página 342)

� En C++, una excepción puede ser de cualquier tipo de dato: entero,real, nuestras propias clases, etc.

Al crear nuestras propias clases de excepción, podremos construirobjetos con más información que un simple ������ sobre el errorproducido.

� Cuando se vea el concepto de Herencia se verá cómo puede captu-rarse diferentes tipos de excepciones en un único ����. Para ello,tendremos varias clases que heredan de otra clase base. Las ex-cepciones se generarán como se ha visto en este tema, pero secapturarán en un ���� de la clase base.

Tema VI

Recursividad

Objetivos:

� Entender el concepto de recursividad.

� Conocer los fundamentos del diseño de algoritmos recursivos.

� Comprender la ejecución de algoritmos recursivos.

� Aprender a realizar trazas de algoritmos recursivos.

� Comprender las ventajas e inconvenientes de la recursividad.

Este tema ha sido elaborado por Francisco Cortijo y Juan Carlos Cubero

Page 250: Fundamentos de Programacion

RecursividadEl concepto matemático de Recursividad → 486

VI.1. El concepto matemático de Recursi-vidad

VI.1.1. Soluciones recursivas

"La iteración es humana; la recursividad, divina.".

"Para entender la recursividad es necesario antes entender la recursi-vidad.".

Recursividad (recursion) es la forma en la cual se especifica un procesobasado en su propia definición.

Podemos usar recursividad si la solución de un problema está expresadaen términos de la resolución del mismo tipo de problema, aunque de me-nor tamaño y conocemos la solución no-recursiva para un determinadocaso base (base case) (o varios).

En Matemáticas se usa este concepto en varios ámbitos:

� Demostración por inducción (induction):

– Demostrar para un caso base.

– Demostrar para un tamaño �, considerando que está demos-trado para un tamaño menor que �.

� Definición recursiva

n! =

⎧⎨⎩

1 si n = 0

n · (n − 1)! si n > 0

RecursividadEl concepto matemático de Recursividad → Soluciones recursivas 487

� Ventajas: No es necesario definir la secuencia de pasos exacta pararesolver el problema. Podemos considerar que “tenemos resuelto”el problema (de menor tamaño).

� Desventajas: Tenemos que encontrar una solución recursiva, y,además, podría ser menos eficiente.

Ejemplo. Cálculo del factorial con n=3.

Page 251: Fundamentos de Programacion

RecursividadEl concepto matemático de Recursividad → Soluciones recursivas 488

En resumen:

RecursividadEl concepto matemático de Recursividad → Diseño de algoritmos recursivos 489

VI.1.2. Diseño de algoritmos recursivos

Debemos diseñar:

� Casos base:

Son los casos del problema que se resuelve con un segmento decódigo sin recursividad.

Para que una definición recursiva esté completamente identificadaes necesario tener un caso base que no se calcule utilizando casosanteriores y que la división del problema converja a ese caso base.��

��Siempre debe existir al menos un caso base

El número y forma de los casos base son hasta cierto punto arbitra-rios. La solución será mejor cuanto más simple y eficiente resulteel conjunto de casos seleccionados.

�� � �

� Casos generales:

Debemos encontrar la solución a un problema (o varios) del mismotipo, pero de menor tamaño.

������

� Composición:

Una vez encontradas las soluciones a los problemas menores, ha-brá que ejecutar un conjunto de pasos adicionales. Estos pasos,junto con las soluciones a los subproblemas, componen la solu-ción al problema general que queremos resolver.

�� � � ������

Page 252: Fundamentos de Programacion

RecursividadEl concepto matemático de Recursividad → Diseño de algoritmos recursivos 490

Ejercicio. Plantear la solución recursiva al problema de calcular la poten-cia de un real elevado a un entero positivo xn

� Caso base: x0 = 1

� Caso general: xn−1

� Composición: xn = x ∗ xn−1

Ejercicio. Plantear la solución recursiva al problema de sumar los enterospositivos menores que un entero

∑i=ni=1 i

� Caso base:∑i=1

i=1 i = 1

� Caso general:∑i=n−1

i=1 i

� Composición:∑i=n

i=1 i = n +∑i=n−1

i=1 i

Ejercicio. Plantear la solución recursiva al problema de multiplicar dosenteros a ∗ b

� Casos base: 0 ∗ b = 0, a ∗ 0 = 0

� Caso general: a ∗ (b − 1)

� Composición: a ∗ b = a + a ∗ (b − 1)

RecursividadFunciones recursivas → 491

VI.2. Funciones recursivas

VI.2.1. Definición de funciones recursivas

¿Cómo se expresa en un lenguaje de programación la solución a un pro-blema? Una solución será el valor devuelto por la llamada a una función.

n! → ����������

xn → ��� ������

¿Cómo se traduce a un lenguaje de programación el planteamiento re-cursivo de una solución? A través de una función que, dentro del códigoque la define, realiza una o más llamadas a la propia función.

Una función que se llama a sí misma se denomina función recursiva (re-cursive function).

�� ��������� �� � �

�� � ��������

�� ����

� ������� � �� ������ ���

��

� ������� � �������������� ������ � ���

� ��� � ��������

�� ��������� �� � �

�� ����

� ��� �� ������ ���

��

� ��� �������������� ������ � ���

Page 253: Fundamentos de Programacion

RecursividadFunciones recursivas → Ejecución de funciones recursivas 492

VI.2.2. Ejecución de funciones recursivas

En general, en la pila se almacena el marco asociado a las distintas fun-ciones que se van activando. En particular, cada llamada recursiva ge-nera una nueva zona de memoria en la pila independiente del resto dellamadas.

Ejemplo. Ejecución del factorial con n=3.

1. Dentro de factorial, cada llamada������ �������� �������

genera una nueva zona de memoria en la pila, siendo ��� el corres-pondiente parámetro actual para esta zona de memoria y quedapendiente la evaluación de la expresión y la ejecución del ������.

2. El proceso anterior se repite hasta que la condición del caso basese hace cierta.

� Se ejecuta la sentencia ������ ��

� Empieza la vuelta atrás de la recursión, se evalúan las expre-siones y se ejecutan los ������ que estaban pendientes.

RecursividadFunciones recursivas → Ejecución de funciones recursivas 493

Page 254: Fundamentos de Programacion

RecursividadFunciones recursivas → Ejecución de funciones recursivas 494

RecursividadFunciones recursivas → Ejecución de funciones recursivas 495

Page 255: Fundamentos de Programacion

RecursividadFunciones recursivas → Traza de algoritmos recursivos 496

VI.2.3. Traza de algoritmos recursivos

Se representan en cascada cada una de las llamadas al módulo recursivo,así como sus respectivas zonas de memoria y los valores que devuelven.

Llamada: ����������

RecursividadFunciones recursivas → Traza de algoritmos recursivos 497

Ejercicio. Calcular la potencia de un real elevado a un entero positivo xn

� Caso base: x0 = 1

� Caso general: xn−1

� Composición: xn = x ∗ xn−1

��� ����������� ���� ��� � ���������

�� � ������� �� ��

������ ��

����

������ ��� � ������������ � �����������

Ejercicio. Sumar los enteros positivos menores que un entero∑i=n

i=1 i

� Caso base:∑i=1

i=1 i = 1

� Caso general:∑i=n−1

i=1 i

� Composición:∑i=n

i=1 i = n +∑i=n−1

i=1 i

��� ������������ ������

�� ���� �� ��

������ ��

����

������ ���� ������������� � ���

Page 256: Fundamentos de Programacion

RecursividadFunciones recursivas → Traza de algoritmos recursivos 498

Ejercicio. Multiplicar dos enteros a ∗ b

� Casos base: 0 ∗ b = 0, a ∗ 0 = 0

� Caso general: a ∗ (b − 1)

� Composición: a ∗ b = a + a ∗ (b − 1)

��� ���������� �� ��� ��

�� �� � �� � �� ��

������ ��

����

������ � � ��������� ����

RecursividadClases con métodos recursivos → 499

VI.3. Clases con métodos recursivos

VI.3.1. Métodos recursivos

El planteamiento y definición de un método recursivo es análogo a lasfunciones. La diferencia es que todas las llamadas recursivas del métodopueden acceder a los datos miembro del objeto. Si una llamada recursivamodifica algún dato miembro, el resto de llamadas se verán afectadas, yaque todas ellas acceden a los mismos datos miembro.

Ejercicio. Plantear una solución recursiva al problema de sumar los ele-mentos de un vector y definir un método recursivo que la implemente.

����� ������� ����

�������

���� � � � ��� � ���

� �����������������

� ������������

�������

������� ����

�������������� � !

� "��#�������� �

���� ������������

!

��� $ ������ ��� �

�% ������������ & ��� �

������������������������ � ����

�����������''�

!

(( ����

(( �� ��� �)�����*

!

�+�� ���,� �� � ���� �

���� ������������� ������

!

!�

Page 257: Fundamentos de Programacion

RecursividadClases con métodos recursivos → Métodos recursivos 500

����� ������� ����

�������

���� � � � ��� � ���

� �����������������

� ������������

�������

������� ����

��������������

� !

� "��#�������� �

���� ������������

!

��� $ ������ ��� �

�% ������������ & ��� �

������������������������ � ����

�����������''�

!

(( ����

(( �� ��� �)�����*

!

�+�� ���,� �� � ���� �

���� ������������� ������

!

� -�,�.����� ����� �

�% ������ �� �

���� ���������������

����

���� ����������������� � ' -�,�.��������� /0 �

!

� -�,�"��� �

���� -�,�.��������������� / 0 �

!

!�

RecursividadClases con métodos recursivos → Métodos recursivos 501

Page 258: Fundamentos de Programacion

RecursividadClases con métodos recursivos → Métodos recursivos 502

Ejemplo. Plantear la solución recursiva al problema de buscar la primeraocurrencia de una componente de un vector y definir un método que laimplemente.

Observad que, en este ejemplo, se necesitan dos casos base.

����� ������� ����

�������

���� � � � ��� � ���

� �����������������

� ������������

�������

�������

� ��!���"����� ���� ��#� ����$ � ��%�$ � ������&�

�' #���� ( ��%�&

���� )*�

���� �' #����������������� �� ������&

���� �����

����

���� ��!���"����� ���� ��#���� + *$ ��%�$ ������&�

,

,�

RecursividadClases con métodos recursivos → Métodos recursivos 503

Page 259: Fundamentos de Programacion

RecursividadClases con métodos recursivos → Métodos recursivos 504

RecursividadClases con métodos recursivos → Métodos recursivos 505

Ejercicio. Plantear la solución recursiva al problema de encontrar el ma-yor elemento de un vector (entre dos posiciones dadas) y definir un mé-todo que la implemente.

����� ������� ����

�������

���� � � � ��� � ���

� �����������������

� ������������

�������

�������

� ���!�"� ����# � ��$�%�

� ���&�!��� �����

�' "���� �� ��$�%

���� �����

���� �' "���� ( ��$�%�

���&�!��� ���� � ���!�"���� ) *# ��$�%�

�' "���������������&�!��� ����� + �����������������%

���� ���&�!��� �����

����

���� �����

,

����

���� -*�

,

,�

Page 260: Fundamentos de Programacion

RecursividadClases con métodos recursivos → Métodos recursivos 506

Ejercicio. Plantear la solución recursiva al problema de buscar con el mé-todo de búsqueda binaria la primera ocurrencia de una componente deun vector ordenado y definir un método que la implemente.

Recordemos el método de búsqueda binaria:

����� ���������������

�������

���� ��� �� ������� � ���

���� ���������������������

�� ��� ���!����

� "����

#####################################

�� $ �% ���$������ &���� " ����'

�� �!��( ����( �����

�!�� � ��

���� � ��� ���!���)*�

���� � &�!��+����',-�

.���� &�!�� /� ���� 00 ����������������� 1� " ����'

�2 &" ���� / �����������������'

���� � ����)*�

����

�!�� � ����+*�

���� � &�!��+����',-�

3

�2 &�!�� 4 ����'

�� �� )*�

����

�� �� �����

3

3�

RecursividadClases con métodos recursivos → Métodos recursivos 507

����� ������� ����

�������

���� � � � ��� � ���

� �����������������

� ������������

�������

�������

� ��!���� � ����"� ����# � ��$�# � ������%�

� �� ��

�& "���� ' ��$�%

���� ()�

�����

�� � � "���� * ��$�% + ,�

�& "�������������� �� �� ������%

���� �� ��

����

�& "�������������� �� ' ������%

���� ��!���� � ����"����# �� �()# ������%�

����

���� ��!���� � ����"�� � * )# ��$�# ������%�

-

-

-�

Page 261: Fundamentos de Programacion

RecursividadClases con métodos recursivos → Métodos recursivos 508

RecursividadClases con métodos recursivos → Métodos recursivos 509

Page 262: Fundamentos de Programacion

RecursividadClases con métodos recursivos → Ordenación rápida: Quicksort 510

VI.3.2. Ordenación rápida: Quicksort

Ideado por Charles Antony Richard Hoare en 1960.

Este es un método de ordenación que utiliza la recursividad para ir fijandolos rangos del vector sobre los que otro método (������) realizará losintercambios necesarios para ir ordenándolo.

Idea:

� Para ordenar alfabéticamente un montón de exámenes, se hacendos pilas: en una se van echando los que tienen apellidos menoresque un pivote ��� y en la otra los mayores que ���.

� Se vuelve a repetir el proceso con cada montón, pero cambiandoel elemento pivote. En la segunda iteración recursiva, en el primermontón podría escogerse como pivote ��� y en el segundo ��.

� Si no conocemos a priori el rango de valores, el pivote lo elegimosde forma arbitraria (por ejemplo, el primero que cojamos de la pila)

���� �� ������������

��������

��� ���������� �������� ��� �������

�������

������

�������

���� ������������ ������ ��� ������

��� ���!������"

� ������ # ����� �

���!������ $ ������ ������� �����"

�������� ������� ���!������ % &�" '' (����� ������� �����

�������� ����!������ ) &� �����" '' (����� ��*���� �����

+

RecursividadClases con métodos recursivos → Ordenación rápida: Quicksort 511

��

Líneas básicas del algoritmo de la función ������:

1. Tomar un elemento arbitrario del vector: ����

2. Recorrer el vector de izquierda a derecha hasta encontrar un ele-mento situado en una posición ���� tal que � ����� � ����

3. Recorrer el vector de derecha a izquierda hasta encontrar otro ele-mento situado en una posición ���� tal que � ����� � ����

4. Intercambiar los elementos de las casillas ���� y ����

Una vez hecho el intercambio tendremos que:

� ����� � ���� � � �����

5. Repetir hasta que los dos procesos de recorrido se encuentren(���� � ����).

6. Colocar el pivote en el sitio que le corresponde.

7. Una vez hecho lo anterior, el vector está particionado en dos zonasdelimitadas por el pivote. El pivote está ya colocado correctamenteen su sitio.

Page 263: Fundamentos de Programacion

RecursividadClases con métodos recursivos → Ordenación rápida: Quicksort 512

RecursividadClases con métodos recursivos → Ordenación rápida: Quicksort 513

��� ������ ���� ������ ��� � �����

��� �����������

��� ����� �����

��� �� ������ � �������������������

���� � ����� � �� �� ������ �� � � �����

���� � � ���� �� ������ �� � � �����

�� ����� !� ������

�� �����!����� "" �����������������!��� �������

�������

�� �����!����� "" �����������������#��� �������

����$$�

�% ����� ! ����� �

���������� � ������������������

����������������� � ������������������

����������������� � �����������

����$$�

�������

&

&

���������� � �������������������

������������������ � ������������������

����������������� � �����������

����� �����

&

Page 264: Fundamentos de Programacion

RecursividadClases con métodos recursivos → Ordenación rápida: Quicksort 514

RecursividadClases con métodos recursivos → Ordenación rápida: Quicksort 515

Ampliación:� Quicksort es uno de los mejores algoritmos de ordenación. Se anali-

zará su eficiencia en el segundo cuatrimestre.

� Quicksort puede paralelizarse fácilmente. Cada CPU se encargaríade la resolución de una llamada recursiva. Al final basta juntar lossubvectores ordenados. Esto es posible porque el pivote calculadoen cada momento, es colocado en el lugar que le corresponde.

� La elección del pivote es muy importante. Las mejoras de Quicksortpasan por desarrollar mecanismos rápidos de elección de buenospivotes (elementos que dejen más o menos el mismo número de ele-mentos a la izquierda y derecha)

� Algunos applets de demostración.

Para tener una idea global:

������������� ��������� ���������������

Ejecución paso a paso:

����������������������������������� �������

���������������������������������� ���

Page 265: Fundamentos de Programacion

RecursividadRecursividad versus iteración → 516

VI.4. Recursividad versus iteración

Desventajas de la recursividad:

� La carga computacional (tiempo-espacio) asociada a una llamadaa una función y el retorno a la función que hace la llamada.

� Algunas soluciones recursivas pueden hacer que la solución paraun determinado tamaño del problema se calcule varias veces.

Ventajas de la recursividad:

� La solución recursiva suele ser concisa, legible y elegante.

Tal es el caso, por ejemplo, del recorrido de estructuras complejascomo árboles, listas, grafos, etc. Se verá en el segundo cuatrimes-tre.

Habrá que analizar en cada caso la conveniencia o no de usar recursivi-dad.

RecursividadRecursividad versus iteración → 517

Recursividad de cola

Se dice que una función tiene recursividad de cola (tail recursion) si sólose produce una llamada recursiva y no se ejecuta posteriormente ningúncódigo. Estas funciones pueden traducirse fácilmente a un algoritmo norecursivo, más eficiente. De hecho, muchos compiladores realizan auto-máticamente esta conversión.

Todos los algoritmos vistos en esta sección, salvo Quicksort, tienen re-cursividad de cola, y por tanto pueden traducirse fácilmente a un algorit-mo iterativo. Por ejemplo:

��� ����������� ���� ��� � ���������

�� � ������� �� ��

������ ��

����

������ ��� � ������������ � �����������

��� ����������� ���� ��� � ���������

��� �������� � ��

��� ��� � � �� � �� � �������� ����

�������� � �������� � ����

������ ���������

Page 266: Fundamentos de Programacion

RecursividadRecursividad versus iteración → 518

Ejemplo. Invertir un vector (el subvector entre las posiciones ���� y ����)

�� ���� �� ����

����� � � ������ � ����� � ��� � ��� ��� � ��

��

������ � ����� � ������ �� � ������ � �����

� ��� �� ����� �� ���� � � � ����

����� � ������ � ��� � �� ���� � �� � �� � ����� � �����

���� �� ��������������!

��������

������ � �� � � "#� � $%&

���� �����'������("#�)&

� � ���'��������&

������

*********

�� �������������� # ������+�������,� � ����- � � ����.!

�� �������������� � ����&

�� ,���� �� ����.

� ����*� ����,�����'������(����).&

���

�� ,���� / ����.!

� ���� � # ������+�������,������- ����.&

� ����*� ����,�����'������(����).&

0

����� � ����&

0

0&

Este método no tiene recursividad de cola ya que después de hacer lallamada recursiva, el método todavía debe hacer otras operaciones. Encualquier caso, esto no quiere decir que no se podría haber traducidocomo un algoritmo iterativo.

RecursividadRecursividad versus iteración → 519

Repetición de cómputos

Los algoritmos interesantes serán los que realicen más de una llamadarecursiva (como Quicksort), pero debemos evitar la repetición de cómpu-tos.

Ejemplo. Sucesión de Fibonacci.

Fib(0) = Fib(1) = 1

Fib(n) = Fib(n − 1) + Fib(n − 2)

Ampliación:La sucesión de Fibonacci tiene muchas aplicaciones. Por ejemplo Fibo-nacci(n+2) da como resultado el número de subconjuntos de {1, · · · , n}que no contienen enteros consecutivos. En la naturaleza, están presen-tes en la fórmula que determina cómo se disponen las hojas en los ta-llos. Hay una revista matemática dedicada exclusivamente a resultados so-bre esta sucesión. Para más información, consultad wikipedia (en inglés)

y la web de la Enci-clopedia de sucesiones enteras .

Page 267: Fundamentos de Programacion

RecursividadRecursividad versus iteración → 520

��� ��������� ��� ��

�� � � �� � �

������ ��

����

������ ������������ � �������������

Cálculo de ����������:

RecursividadRecursividad versus iteración → 521

La solución recursiva de Fibonacci repite muchos cómputos, por lo quees muy ineficiente.

La solución iterativa es sencilla de implementar y mucho más rápida:

��� ��������� ��� ��

��� ���� �� � �� � ������ �� � ��

��� �������

�� � �� � �� � �� �

������ � ��

����

�� ��� � � �� � �� �� ��� �

������ � ���� �� � � ������ �� �

� ������ �� � ���� �� �

���� �� � �������

��� � �������

Ampliación:Una forma alternativa de evitar el problema de los cómputos repetidos enrecursividad, lo proporcionan las técnicas de la programación dinámica (dy-namic programming) que, a grosso modo, van guardando adecuadamentelos resultados obtenidos previamente.

Page 268: Fundamentos de Programacion

RecursividadRecursividad versus iteración → 522

Caso base demasiado pequeño

Muchos problemas recursivos tienen como caso base un problema de untamaño reducido. En ocasiones es excesivamente pequeño.

Para resolverlo, se suele aplicar un algoritmo iterativo cuando se ha lle-gado a un caso base suficientemente pequeño.

Ejemplo. Búsqueda binaria.

Aplicamos el algoritmo recursivo en general y el iterativo cuando el ta-maño del subvector en el que estoy buscando es pequeño.

�������� ��� ��������� ��� �� ����� ���� �� � � ���

�� �� ����� � �������� ����� �� � � ��� �� ������

������ �� ����� ��� �� �������� �� ���������

�� ���� ����

��������� �� �� ������ � ������� �� �� �� ����� ����� �

�� �� �� ��

������ � �� �� � � � �� ������ � ������

��������� � �� ���� � ����������

����� ��� �� ������� ����� � ���� � ���� ��� ���������

����� �!�����"������#

$$$$$$$

��� %�����&���������"���� ���� ��'�� �( ��� ��' ���( ���� ����� ��#

��� � ) ��'�� �*

���� �������� � ) +����*

,���� �� -) ��' ��� .. /�������� ��

�+ �������'���� ���� )) ����� ��

�������� � ) ����*

����

�00*

RecursividadRecursividad versus iteración → 523

�� ����������

�� � ��

����

�� � ���

��� � �� ���������� ���� ��� ���� ��� � ������

����� ��� ��� � ��

��� ������

�� ���� � ��� � � � ����

�� � ���!� ����"�������� ���� � ������

�����

����� � ���� � ���� # $�

�� �%����&'�%��(�����) �� � �����

�� � ������

����

�� �%����&'�%��(�����) * � �����

�� � � �� ����������� �������� � ������

����

�� � � �� ������������ � �� ���� � ������

��

Nota. El caso base ���� * ���� de la función ya no es necesario.

Nota. ��� � ��� � � � ��� representa número de elementos me-nor que un umbral. Si se quiere, por eficiencia, podría cambiarse a��� � ��� � ���

Page 269: Fundamentos de Programacion

RecursividadRecursividad versus iteración → 524

Ejemplo. Mejoramos QuickSort de forma análoga:

����� ������� ����

�������

� ������� ������� � �����

�������

�������

�������

��� ���� ������������ �� ���� ������� � ������

� ����� �

�� �� ���� ������ � ����!���� � ����""��

����� #���� �� ��� �� ������ ������

$ ��������%�� � ���� �#���� �� ������ ����� ��

&

&

��� '���(���� � ���� � �� ����

� � � ������ )�

� ��������

�� ��� �� * � ��� " + ! �������

���� ���� ������������ �� ���� ���� �� ����

�����

�� �� ��� ! �� ��� �

������� ����� �� ���� �� ����

'���(�� �� ���� ������� * +�� ,, ���� � ������� ����

'���(�� �������� " +� �� ���� ,, ���� � ��-� �� ����

&

&

&

&�

RecursividadRecursividad versus iteración → 525

�������� �� � ���� y ��������

Page 270: Fundamentos de Programacion

RecursividadRecursividad versus iteración → 526

RecursividadRecursividad versus iteración → 527

Problemas complejos con una solución recursiva sencilla

Algunos problemas se resuelven directamente con recursividad. Normal-mente, también es posible resolverlos iterativamente, pero puede resultarmás complejo.

Ejemplo. Definición de fractal (fractal) de la Wikipedia:

Un fractal es un objeto semigeométrico cuya estructura básica, fragmen-tada o irregular, se repite a diferentes escalas. A un objeto geométricofractal se le atribuyen las siguientes características:

� Es demasiado irregular para ser descrito en términos geométricostradicionales.

� Es autosimilar.- Su forma es hecha de copias más pequeñas de lamisma figura. Las copias son similares al todo: misma forma perodiferente tamaño.

� · · ·� Se define mediante un simple algoritmo recursivo.

Page 271: Fundamentos de Programacion

RecursividadRecursividad versus iteración → 528

Ejemplo. Triángulos de Sierpinski

����� ���������

�����

���� ����� ���� ���� �� � ���� �� � ���� �� �� �������

�������� ��� ����

�! ������ "" #�

����$��� %������ �� ��� �� ��

�����

���&����������� ���&�������� ��

���&����������� ���&�������� ��

���&����������� ���&�������� ��

� ���� '������ ����&�����$'�������

� ���� '������ ����&�����$'�������

� ���� '������ ����&�����$'�������

����� �� ��� '������� '������� ����� ( )�

����� �� �'������� �� '������� ����� ( )�

����� �� �'������� '������� �� ����� ( )�

*

*

*

RecursividadRecursividad versus iteración → 529

Ejemplo. Torres de Hanoi. Edouard Lucas, 1883.

Se trata de mover un conjunto de discos apilados en un poste a otroposte, con las condiciones siguientes:

� Se tienen 3 postes (hay versiones para trabajar con más postes)

� Sólo se puede mover un disco en cada paso. Además, debe ser eldisco que está en la parte superior de la pila.

� Los discos en cualquier poste siempre deben formar una pirámide,es decir, colocados de mayor a menor.

Etiquetando los 3 postes como �������, ��������, �����, el algoritmorecursivo que lo resuelve sería:

���� ��� ����� ��� ������� ����� ������� ����� ����� ��� ��������

���� �� ���� ��� ���� �� ������� ����� �����

���� ��� ����� ��� �������� ����� ����� ����� ������� ��� ��������

Page 272: Fundamentos de Programacion

RecursividadRecursividad versus iteración → 530

�������� ��� ����

����� ��������� ����

��� ���� ���� ���������� ��� �������� ��� ���� ����� ��� �������

�� ���������� � ���

���� ������������� �������� ������ ���� ������

��� � �!�� ���� � ������� � �� � ������

���� ������������� ���� ����� �������� �������

"

"

��� �������

��� �� ## $%�� �� ����� � ���

��� �$%�� �� �����& ��

��� �� ��

���� ��� �� '� (�� ## ��� ��� ����� ��� � �� (�

## ����� �� ' �� ���� ��)

"

RecursividadRecursividad versus iteración → 531

Page 273: Fundamentos de Programacion

RecursividadRecursividad versus iteración → 532

Algunas curiosidades:

� Applet: ��������������� ���������������������

� Número de movimientos: 2k, siendo k = número de discos. Para 64discos, moviendo 1 disco por segundo, se tardaría algo menos de600 mil millones de años (el Universo tiene unos 20 mil millones)

� También existe una versión iterativa. No son tres líneas, pero noes demasiado complicada. En cualquier caso, el número de movi-mientos es el mismo.

Page 274: Fundamentos de Programacion

PRÁCTICAS

Curso: 2011/2012 Clase: Primero - Grupo: B

Page 275: Fundamentos de Programacion

Fundamentos de Programación.

Guión de Prácticas.Curso 2011/2012

Page 276: Fundamentos de Programacion

Autor: Juan Carlos CuberoPara cualquier sugerencia o comentario sobre este guión de prácticas, por favor, enviad une-mail a [email protected]

"Lo que tenemos que aprender a hacer, lo aprendemos haciéndolo".Aristóteles

"In theory, there is no difference between theory and practice. But, in practice, there is".Jan L. A. van de Snepscheut

"The gap between theory and practice is not as wide in theory as it is in practice".

"Theory is when you know something, but it doesn’t work. Practice is when somethingworks, but you don’t know why. Programmers combine theory and practice: Nothingworks and they don’t know why".

Guión de Prácticas. Fundamentos de Programación 1

Page 277: Fundamentos de Programacion

Acceso identificado

Acceso identificado

Los alumnos deben registrarse electrónicamente en dos sitios distintos:

• En la Universidad de Granada.

Los alumnos deben registrarse electrónicamente en la UGR para poder entrar en lasaulas de prácticas de la asignatura. Las instrucciones están en:

http://www.ugr.es/informatica/alumnos/correo.htm

Se necesita el DNI y el PIN obtenido con la matrícula. El registro electrónico tarda undía (incluso dos) en activarse. Por tanto, realizad el registro al menos tres días antesde la primera sesión de prácticas (que tendrá lugar la segunda semana de clases)

Una vez que se tenga cuenta de correo en la UGR, el alumno podrá iniciar sesiónen cualquiera de los ordenadores de la Escuela de Informática. Para ello, tendrá queintroducir como usuario y contraseña, los mismos que se han elegido para la UGR.Automáticamente, tendrá acceso a un sitio de almacenamiento en los servidores de laEscuela. Esto se explica en la primera sesión de prácticas (página 22)

• En la Web del departamento de Ciencias de la Computación e Inteligencia Artificial

https://decsai.ugr.es

La mayor parte de los alumnos ya están dados de alta en la web con los datos que he-mos obtenido de la matrícula. En cualquier caso, el alumno debe comprobarlo durantela primera semana de clases, dando los siguientes pasos:

– Al entrar en el acceso identificado de la web del departamento, introducir comonombre de usuario y como contraseña el DNI sin la letra del final (o el número depasaporte).

– Si puede entrar con éxito, acceda a sus datos personales para cambiar el pass-word y subir una foto reciente.Introducid en los datos de contacto una dirección de e-mail que consulte habi-tualmente, ya que se enviará asiduamente información sobre la asignatura. Nodebe elegirse ninguna dirección de Hotmail ya que la UGR clasifica como SPAMmuchos correos de dicho servidor.

– Puede encontrar instrucciones más detalladas en el ficheroRegistroWebDECSAI.pdf incluido enhttp://decsai.ugr.es/jccubero/fp.zip

– Si no puede entrar, envíe un e-mail a [email protected] con su nú-mero de DNI, Nombre y Apellidos.

Guión de Prácticas. Fundamentos de Programación 2

Page 278: Fundamentos de Programacion

Acceso identificado

Una vez tenga acceso a la web del departamento, podrá entrar en la asignatura deFundamentos de Programación y elegir un grupo de prácticas. También podrá accederal material de la asignatura. El material del primer tema también se encuentra en:

http://decsai.ugr.es/jccubero/fp.zip

MUY IMPORTANTE: El alumno nunca deberá dar a conocer a un tercero su nombrede usuario y contraseña, ya que es el responsable del mal uso que se pudiese realizarcon su cuenta.

Guión de Prácticas. Fundamentos de Programación 3

Page 279: Fundamentos de Programacion

Sobre el guión de prácticas

Sobre el guión de prácticas

Este guión de prácticas contiene las actividades a realizar por el alumno, tanto de formapresencial (en las aulas de la Escuela de Informática) como no presencial (individual y engrupo). Todas las actividades son obligatorias (incluidas las presenciales en las aulas deprácticas), excepto las marcadas como Actividades de Ampliación.El guión está dividido en sesiones, que corresponden a cada semana lectiva. Las activi-dades no presenciales de una sesión deben realizarse antes de la correspondiente sesiónde prácticas presencial. La primera sesión presencial de prácticas (página 21) tendrá lugardurante la segunda semana de clases, por lo que el alumno deberá realizar con anterioridadlas actividades encargadas.Una actividad no presencial recurrente es la resolución de problemas propuestos en lasRelaciones de Problemas. Éstas constan de dos tipos de problemas:

• Básicos: problemas que se resolverán a lo largo de la asignatura.

Del conjunto de problemas básicos, en el guión de prácticas se distinguirá entre:

1. Obligatorios: Deben resolverse en la casa y el alumno deberá defenderlos indivi-dualmente (a veces explicándolo a sus compañeros) en las sesiones de prácticaspresenciales, durante la primera hora. La defensa será individual y forma parte dela nota final de la asignatura (10 % tal y como se explica en el apartado de evalua-ción de la asignatura). En la segunda hora, el profesor explicará estos ejerciciosa toda la clase. También sacará a la pizarra a algún alumno para que expliquealguno de los ejercicios.Los proyectos soluciones a los problemas deberán ser subidos a la cuenta par-ticular de cada alumno en el servidor de la ETS Informática y Telecomunica-ciones antes del inicio de la sesión de prácticas presencial en las aulas de laEscuela. Para ello, el alumno debe conectarse a turing.ugr.es usando cual-quier programa cliente de ftp que incorpore el protocolo ssh, como por ejemplowinscp (http://winscp.net/). Previamente, el alumno debe tener activadasu cuenta en la Universidad de Granada, tal y como se explica en la página 2.Hay que subir la carpeta completa del proyecto solución incluyendo los fiche-ros sln, vcxproj y cpp. Borrad el resto de ficheros: para ello, puede usarsela macro _limpiar.bat que se encuentra en el material de la asignatura (fi-chero zip indicado en la página 2 o a través del acceso identificado en la webdel departamento) Debe copiarse el fichero _limpiar.bat junto con el ficherolimpiar.exe en el directorio del que cuelgan las carpetas de los proyectossoluciones, y ejecutad la macro _limpiar.bat, haciendo doble click sobre ella.Una vez ejecutada la macro, ya pueden subirse a turing las carpetas de losproyectos. En caso de tener algún problema con la conexión a turing, tambiénpueden llevarse los proyectos en un pen-drive el mismo día de las prácticas.

Guión de Prácticas. Fundamentos de Programación 4

Page 280: Fundamentos de Programacion

Sobre el guión de prácticas

Nota: mientras el profesor corrige los ejercicios a un alumno en la primera hora,los alumnos desarrollarán las actividades presenciales de la correspondiente se-sión. Cuando las hayan terminado, se pueden poner a trabajar en los problemasde la próxima sesión.

2. Opcionales: Se recomienda que se resuelvan en casa, pero el profesor no lospreguntará en las sesiones de prácticas. En la segunda hora, el profesor explicaráestos ejercicios a toda la clase.

• Ampliación: problemas cuya solución no se verá, pero que sirven para afianzar co-nocimientos. El alumno debería intentar resolver por su cuenta un alto porcentaje deéstos.

No hay que entregar al profesor la solución de los ejercicios de las distintas sesiones, yaque, durante la segunda hora de prácticas, se proporcionará la solución a los problemasbásicos y opcionales propuestos. Es muy importante que el alumno revise estas solucionesy las compare con las que él había diseñado.Las actividades marcadas como Seminario han de hacerse obligatoriamente y siempre se-rán expuestas por algún alumno elegido aleatoriamente.Para la realización de estas prácticas, se utilizará el entorno de programación MicrosoftVisual Studio. En la página 7 se encuentran las instrucciones para su instalación en nuestracasa. En cualquier caso, el alumno puede instalar en su casa cualquier otro compilador,como por ejemplo Code::Blocks→ http://www.codeblocks.org/

Muy importante:

• La resolución de los problemas y actividades puede hacerse en grupo, pero la defensadurante las sesiones presenciales es individual.

• Es muy importante que la asignatura se lleve al día para poder realizar los ejerciciospropuestos en estos guiones.

Guión de Prácticas. Fundamentos de Programación 5

Page 281: Fundamentos de Programacion

Evaluación de la asignatura

Evaluación de la asignatura

La nota final en la asignatura se computa de la siguiente forma:

• En Febrero se realizará un examen escrito consistente en la resolución de varios pro-blemas de programación relacionados con la materia impartida. La ponderación deeste bloque es del 60 %.

• La parte práctica se evalúa de la siguiente forma:

– Evaluación continua: Durante las sesiones de prácticas, los alumnos deberándefender ante la clase o ante el profesor, los problemas encargados para dichasesión de prácticas. La ponderación de esta parte es del 10 %.

– Exámenes de prácticas: A mediados de Noviembre y a principios de Enero serealizará un examen de prácticas. Cada uno de estos exámenes consistirá enla resolución de un ejercicio de programación que se extraerá de una lista deejercicios que, previamente, se habrá entregado a los estudiantes. Dichas listasde ejercicios se denominarán Listas de Problemas para el Examen Práctico, paradiferenciarlas de las Relaciones de Problemas.Cada uno de los dos exámenes durará una hora y se realizará en las aulas deprácticas de la Escuela de Informática.La ponderación del primer examen es del 10 % y la del segundo del 20 %

La realización de las prácticas puede realizarse en grupo, pero la defensa es siempreindividual.

En Septiembre se guarda la nota de la evaluación continua y sigue valiendo el 10 % de lanota final. No hay ningún examen de recuperación de esta parte. Por otra parte, en Sep-tiembre se realizarán dos exámenes consistentes en la resolución de varios problemas deprogramación relacionados con la materia impartida. Llamémosle T y P a dichos exámenes.La ponderación de ambos exámenes es 60 % para T y 30 % para P.Sólo para aquellos alumnos que se presentaron a alguna de las partes (escrita/prácticas)en Febrero:

• El alumno puede elegir no presentarse a alguna de las parte T o P. En dicho caso,conservaría la nota que hubiese obtenido en Febrero. Si no se presenta al examen T,la nota de T sería la que hubiese sacado en el examen escriTo de Febrero y si no sepresenta a P, la nota sería la obtenida en las Prácticas de Febrero.

• Si un alumno se presenta a una de las partes (T o P), la nota obtenida en Febrero endicha parte NO se conserva (es una nueva calificación) por lo que la nota de dichaparte podría bajar.

Guión de Prácticas. Fundamentos de Programación 6

Page 282: Fundamentos de Programacion

Instalación de Visual Studio en nuestra casa

Instalación de Visual Studio en nuestra casa

Conseguir Visual Studio e instalarlo

Conseguir Visual Studio

Puede encontrarse información sobre la última versión de Visual Studio en:http://msdn.microsoft.com/es-es/vstudio/default(en-us).aspx

http://www.microsoft.com/spain/visualstudio/products/2010-editions/ultimate

El DVD con la instalación de Visual Studio 2010 Ultimate puede adquirirse en la fotocopiado-ra de la Escuela por unos 3 euros aproximadamente. La licencia es legal para todo alumnodel departamento de Ciencias de la Computación e Inteligencia Artificial, fruto del programaMSDN Academic Alliance entre Microsoft y el departamento. Para más información sobreeste programa:http://www.microsoft.com/spanish/msdn/academico.mspx

La principal restricción es que no se pueden desarrollar programas comerciales con estalicencia. Para más información sobre las restricciones de la licencia:http://msdn.microsoft.com/en-us/academic/bb250608.aspx

La versión Ultimate disponible para los alumnos contiene muchas más herramientas delas que se necesitarán en la asignatura. Si se quiere, puede descargarse directamentedesde Internet la versión Express de Visual Studio. Esta versión también contiene todas lasherramientas y opciones necesarias en esta asignatura, y es la que se usará en las aulasde prácticas:http://www.microsoft.com/express/Downloads/

Para descargas de versiones anteriores, consultad:http://msdn.microsoft.com/es-es/express/aa975050.aspx

Los requisitos del sistema, para la instalación de Visual Studio Express se encuentran enhttp://www.microsoft.com/express/Support/

y para Visual Studio 2010 en:http://www.microsoft.com/spain/visualstudio/products/2010-editions/ultimate

Instalar Visual Studio

Si se usa el DVD de la fotocopiadora con Visual Studio 2010 Ultimate, se puede instalarla versión completa que incluye todos los lenguajes de Visual Studio como Visual Basic,C#, etc. Al introducir el DVD se lanzará automáticamente el programa de instalación. Selec-

Guión de Prácticas. Fundamentos de Programación 7

Page 283: Fundamentos de Programacion

Instalación de Visual Studio en nuestra casa

cionamos Instalación Personalizada. Por ahora, instalamos únicamente la parte correspon-diente al lenguaje C++ (posteriormente, podemos instalar el resto de lenguajes)En el caso de que instalemos la versión Visual Studio C++ Express, no se instalarán el restode lenguajes (que, obviamente, no son necesarios para esta asignatura)

Configuración

Preparar y acceder a la consola del sistema

La consola de Windows (la ventana con fondo negro que aparece al ejecutar el comandocmd.exe, o bien la que sale al ejecutar un proyecto de consola de Visual Studio) no estápreparada por defecto para mostrar adecuadamente caracteres latinos como los acentos.Por ejemplo, al ejecutar la sentencia de C++

cout << "Atención"

saldrá en la consola un mensaje en la forma

Atenci5/4n

Para que podamos ver correctamente dichos caracteres, debemos seguir los siguientespasos:

1. Cambiar la fuente de la consola a una que acepte caracteres Unicode. En la versiónde XP de las aulas ya se ha realizado dicho cambio. En nuestra casa, tendremos quehacer lo siguiente:

Inicio -> Ejecutar -> cmd

Una vez que se muestre la consola, hacemos click con la derecha y seleccionamosPredeterminados. Seleccionamos la fuente Lucida Console y aceptamos.

2. Debemos cargar la página de códigos correspondiente al alfabeto latino. Para ello,tenemos dos alternativas:

a) Si queremos que la consola siempre cargue la tabla de caracteres latinos, debe-mos modificar el registro de Windows. Lo abrimos desde

Inicio->Ejecutar->regeditNos situamos en la clave

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\\Control\Nls\CodePage

y cambiamos el valor que hubiese dentro de OEMCP y ACP por el de 1252. Esta es

Guión de Prácticas. Fundamentos de Programación 8

Page 284: Fundamentos de Programacion

Instalación de Visual Studio en nuestra casa

la forma recomendada y la que se ha usado en las aulas de prácticas. Requierereiniciar el ordenador.Muy Importante: Si se usa otra tabla (distinta a 1252), el sistema operativo podríaincluso no arrancar.

b) Si queremos hacerlo para una única consola, basta ejecutar el comandochcp 1252

sobre la consola. El problema es que cada vez que se abre una nueva consola(por ejemplo, como resultado de ejecutar un programa desde Visual C++) hayque realizar este cambio. En nuestro caso, pondríamos (por ejemplo, al inicio delprograma, justo después de las declaraciones de las variables) lo siguiente:

system("chcp 1252");

En cualquier caso, remarcamos que esta solución no es necesaria si se adoptala primera, es decir, el cambio del registro de Windows.

Configuración del entorno

Se recomienda que se usen las mismas opciones de configuración del entorno que lasestablecidas en las aulas de prácticas. Para ello, deben darse los siguientes pasos. Dentrodel ficherohttp://decsai.ugr.es/jccubero/fp.zip

se encuentra la carpeta Visual Studio\Settings, y dentro el ficheroSettingsAulasPracticas_VS2010.vssettings.vssettings

Copiadlo localmente, preferiblemente dentro de la carpetaMis Documentos\Visual Studio 2010\Settings

Abrid Visual Studio. Seleccionad

Herramientas -> Importar y exportar configuraciones ->Importar la configuración de entorno seleccionada ->Siguiente

Si se quiere guardar las configuraciones actuales, elegid la primera opción. Si no se hatrabajado anteriormente con Visual Studio, podemos elegir directamente la segunda opción:

No, sólo importar la nueva configuración,reemplazando la configuración actual-> Siguiente-> Examinar

Seleccionamos las opciones guardadas anteriormente enMis Documentos\Visual Studio 2010\Settings\\SettingsAulasPracticas.vssettings

Guión de Prácticas. Fundamentos de Programación 9

Page 285: Fundamentos de Programacion

Instalación de Visual Studio en nuestra casa

y hacemos click en Siguiente. Aparecen algunas opciones marcadas con un símbolo de ad-miración, indicando que no se van a importar (pues pueden contener información privada).Aceptamos y terminamos.Cosas a tener en cuenta:

• A partir de ahora, si realizamos algún cambio en el entorno o en las opciones deconfiguración (Herramientas->Opciones), éstas se guardan automáticamente enel archivo

Mis Documentos\Visual Studio 2010\\Settings\CurrentSettings.vssettings

Es decir, el archivo SettingsAulasPracticas.vssettings no se modifica conlos cambios que efectuemos en las opciones del entorno.

• Si queremos exportar nuestra configuración para utilizarla en otro sitio, basta con se-leccionar

Herramientas -> Importar y exportar configuraciones ->Exportar la configuración de entorno seleccionada

y seleccionad el nombre del fichero .vssettings en el que queremos guardar laconfiguración.

La plantilla _fp_2010

En el entorno Visual Studio de las aulas de prácticas, se ha incluido una plantilla con lasopciones de configuración de compilación más usuales así como un esqueleto del programaprincipal que incluye la cabecera que usaremos siempre en nuestros programas.Para instalar esta plantilla en nuestros ordenadores personales, descargad de Internet elficherohttp://decsai.ugr.es/jccubero/fp.zip

Dentro se encuentra la carpeta Visual Studio\PlantillaFP. Seguid las instruccionesque se encuentran en el fichero Instrucciones.txt (simplemente habrá que cambiaruna línea de texto de un fichero y copiar unos ficheros).Para crear un proyecto nuevo en Visual Studio basado en esta plantilla, basta abrir VisualStudio y seleccionar:

Archivo -> Nuevo Proyecto -> Asistentes -> _fp_2010

Seleccionamos una ubicación y tecleamos un nombre para el proyecto.

Guión de Prácticas. Fundamentos de Programación 10

Page 286: Fundamentos de Programacion

Instalación de Visual Studio en nuestra casa

Otros recursos

Dentro del ficherohttp://decsai.ugr.es/jccubero/fp.zip

se encuentra la carpeta Visual Studio\OtrosRecursos, con los siguientes ficheros:

• StepOver_VS_2010.reg. Es un fichero que añade claves al registro de Windowspara que el depurador de Visual Studio no entre a depurar recursos usuales comocout. Para ejecutarlo, basta hacer doble click sobre él (como Administrador del Sis-tema)

• _limpiar.bat y _limpiar.exe. El primero es una macro que llama al segun-do programa. Ambos ficheros deben estar en el directorio del cual cuelgan nuestrascarpetas locales de proyectos de Visual Studio. La macro borra todos los ficheros au-xiliares como los ejecutables, los que contienen información de depuración, etc. Ennuestra casa ejecutaremos la macro cuando nos estemos quedando sin espacio enel disco duro y antes de subir a turing los proyectos soluciones de las distintassesiones prácticas.

Guión de Prácticas. Fundamentos de Programación 11

Page 287: Fundamentos de Programacion

Tabla resumen de accesos directos usados en Visual Studio

Tabla resumen de accesos directos usados en Visual Studio

Ctr-F7 CompilarAlt-Ctr-F7 Generar ejecutable

F5 Ejecutar programa (con depuración)F10 Ejecución paso a paso (sin entrar en las funciones)F11 Ejecución paso a paso (entrando en las funciones)

Shift-F11 Sale de la ejecución paso a paso de la funciónShift-F5 Detiene ejecución paso a paso

Ctr-F5 Ejecutar programa (sin depuración)Ctr-Barra espaciadora Autocompleta el código

F1 AyudaF9 Quita o pone un punto de interrupción

Ctr-F10 Ejecuta instrucciones hasta el cursor y empieza depuraciónCtr-K,Ctr-F Aplica formato al texto seleccionadoCtr-K,Ctr-D Aplica formato al documento

Ctr - Navega por el texto hacia atrás

Guión de Prácticas. Fundamentos de Programación 12

Page 288: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS I. Introducción a C++

RELACIÓN DE PROBLEMAS I. Introducción a C++

Problemas Básicos

1. Crear un programa que pida un valor de intensidad y resistencia e imprima el voltajecorrespondiente, según la Ley de Ohm:

voltaje = intensidad * resistencia

Finalidad: Ejemplo básico de asignación a una variable del resultado de una expresión.Dificultad Baja.

2. Un banco presenta la siguiente oferta. Si se deposita una cantidad de euros capitaldurante un año a plazo fijo, se dará un interés dado por la variable interes. Realizadun programa que lea una cantidad capital y un interés interes desde teclado ycalcule en una variable total el dinero que se tendrá al cabo de un año, aplicando lafórmula:

total = capital+ capital ∗interes

100

Es importante destacar que el compilador primero evaluará la expresión de la partederecha de la anterior asignación (usando el valor que tuviese la variable capital) ya continuación ejecutará la asignación, escribiendo el valor resultante de la expresióndentro de la variable total).

A continuación, el programa debe imprimir en pantalla el valor de la variable total.Tanto el capital como el interés serán valores reales. Supondremos que el usuariointroduce el interés como un valor real entre 0 y 100, es decir, un interés del 5,4%se introducirá como 5.4. También supondremos que lo introduce correctamente, esdecir, que sólo introducirá valores entre 0 y 100.

Supongamos que queremos modificar la variable original capital con el nuevo valorde total. ¿Es posible hacerlo directamente en la expresión de arriba?

Nota: El operador de división en C++ es /

Finalidad: Resolver un problema real sencillo, usando varias sentencias. DificultadBaja.

3. Queremos realizar un programa para intercambiar los contenidos de dos variablesenteras. El programa leerá desde teclado dos variables edad_Pedro y edad_Juane intercambiará sus valores. A continuación, mostrará en pantalla las variables yamodificadas. El siguiente código no funciona correctamente.

edad_Pedro = edad_Juan;edad_Juan = edad_Pedro;

Guión de Prácticas. Fundamentos de Programación 13

Page 289: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS I. Introducción a C++

¿Por qué no funciona? Buscad una solución.

Finalidad: Entender cómo funciona la asignación entre variables. Dificultad Baja.

4. Cread un programa que nos pida la longitud del radio, calcule el área del círculo yla longitud de la circunferencia correspondientes, y nos muestre los resultados enpantalla. Recordad que:

long. circunf = 2πr área circ = πr2

Usad el literal 3.1416 a lo largo del código, cuando se necesite multiplicar por π.

Una vez hecho el programa, cambiad las apariciones de 3.1416 por 3.14159, re-compilad y ejecutad (La parte de compilación y ejecución se realizará cuando se veaen clase de prácticas el entorno de programación).

¿No hubiese sido mejor declarar un dato constante PI con un valor igual a 3.14159,y usar dicho dato donde fuese necesario? Hacedlo tal y como se explica en las trans-parencias de los apuntes de clase.

Cambiad ahora el valor de la constante PI por el de 3.1415927, recompilad y ejecu-tad.

Finalidad: Entender la importancia de las constantes. Dificultad Baja.

5. Realizar un programa que lea los coeficientes reales µ y σ de una función gaussiana(ver definición abajo). A continuación el programa leerá un valor de abscisa x y seimprimirá el valor que toma la función en x

gaussiana(x) =1

σ√2π

e

−12

(x− µσ

)2

El parámetro µ se conoce como esperanza o media y σ como desviación típica (meany standard deviation en inglés). Para definir la función matemática e usad la funciónexp de la biblioteca cmath. En la misma biblioteca está la función sqrt para calcularla raíz cuadrada. Para elevar un número al cuadrado se puede usar la función pow,que se utiliza en la siguiente forma:

pow(base, exponente)

En nuestro caso, el exponente es 2 y la basex− µσ

. Comprobad que los resultados

son correctos, usando el applet disponible enhttp://www.danielsoper.com/statcalc/calc54.aspxo bien algunos de los ejemplos de la figura siguiente (observad que el valor de ladesviación está elevado al cuadrado):

Guión de Prácticas. Fundamentos de Programación 14

Page 290: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS I. Introducción a C++

Finalidad: Trabajar con expresiones numéricas más complejas. Dificultad Baja.

6. Las ganancias de un determinado producto se reparten entre el diseñador y los tresfabricantes del mismo. Diseñar un programa que pida la ganancia total de la empresa(los ingresos realizados con la venta del producto) y diga cuanto cobran cada uno deellos, sabiendo que el diseñador cobra el doble que cada uno de los fabricantes. Eldato de entrada será la ganancia total a repartir. Utilizad el tipo double para todas lasvariables.Importante: No repetid cálculos ya realizados.

Finalidad: Entender la importancia de no repetir cómputos para evitar errores de pro-gramación. Dificultad Baja.

7. Redactar un algoritmo para calcular la media aritmética muestral y la desviación es-tándar (o típica) muestral de las alturas de tres personas. Éstos valores serán reales(de tipo double)

X =1

3

3∑i=1

xi , σ =

√√√√1

3

3∑i=1

(xi −X)2

X representa la media aritmética y σ la desviación estándar. Para resolver este pro-blema es necesario usar la función sqrt (raíz cuadrada) que se encuentra en la bi-blioteca cmath.

Finalidad: Trabajar con expresiones numéricas y con variables para no repetir cómpu-tos. Dificultad Baja.

8. Realizar un programa que declare las variables x, y y z, les asigne los valores 10, 20y 30 e intercambien entre sí sus valores de forma que el valor de x pasa a y, el de ypasa a z y el valor de z pasa a x (se pueden declarar variables auxiliares aunque sepide que se use el menor número posible).

Finalidad: Mostrar la importancia en el orden de las asignaciones. Dificultad Media.

9. Leed desde teclado tres variables correspondientes a un número de horas, minutosy segundos, respectivamente. Diseñar un algoritmo que calcule las horas, minutos

Guión de Prácticas. Fundamentos de Programación 15

Page 291: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS I. Introducción a C++

y segundos dentro de su rango correspondiente. Por ejemplo, dadas 10 horas, 119minutos y 280 segundos, debería dar como resultado 12 horas, 3 minutos y 40 se-gundos. En el caso de que nos salgan más de 24 horas, daremos también los díascorrespondientes (pero ya no pasamos a ver los meses, años, etc)

Como consejo, utilizad el operador / que cuando trabaja sobre datos enteros, repre-senta la división entera. Para calcular el resto de la división entera, usad el operador%.

Finalidad: Trabajar con expresiones numéricas y con variables para no repetir cómpu-tos. Dificultad Media.

10. Realizad el ejercicio del reparto de la ganancia de un producto, pero cambiando el tipode dato de la ganancia total a int (el resto de variables siguen siendo double)

Finalidad: Trabajar con expresiones numéricas que involucren distintos tipos de datos.Dificultad Baja.

11. Realizad el ejercicio del cálculo de la desviación típica, pero cambiando el tipo de datode las variables xi a int.Nota: Para no tener problemas en la llamada a la función pow (en el caso de que sehaya utilizado para implementar el cuadrado de las diferencias de los datos con lamedia), obligamos a que la base de la potencia sea un real multiplicando por 1.0, porlo que la llamada quedaría en la forma pow(base*1.0, exponente)

Finalidad: Trabajar con expresiones numéricas que involucren distintos tipos de datos.Dificultad Baja.

12. Encontrar el valor de la variable resultado después de la ejecución de este código

real1 = 4.0;real2 = 3.0;

resultado = real1/real2 - real1*real2;cout << "\nResultado = " << resultado;

Considerad los siguientes casos:

float real1, real2;double resultado;

y

float real1, real2, resultado;

Guión de Prácticas. Fundamentos de Programación 16

Page 292: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS I. Introducción a C++

Nota. Si se desea ver el contenido de una variable real con cout, es necesario queantes de hacerlo, se establezca el número de decimales que se quieren mostrar enpantalla. Hacedlo escribiendo la sentencia cout.precision(20);, en cualquier si-tio del programa antes de la ejecución de cout << real1 << "," << real2;.

Realizad lo mismo pero asignando los siguientes valores:

double real1, real2real1 = 1234567890.1;real2 = 1234567891.2;

Al multiplicar los dos double se obtiene un número real demasiado grande, que podráser representado en formato exponencial, pero sólo con 16 cifras significativas, por loque sólo se puede garantizar un resultado aproximado.

Generad otro error lógico al perder precisión en las cifras decimales.

Finalidad: Trabajar con tipos distintos en una misma expresión y entender los proble-mas de precisión. Dificultad Baja.

13. Considerad el siguiente código:

double real, otro_real;

real = 2e34;otro_real = real + 1;otro_real = otro_real - real;

cout << otro_real;

¿Qué imprime en pantalla? Justificar la respuesta.

Finalidad: Entender el problema de la precisión con los reales. Dificultad Media.

14. Diseñar un programa que lea un carácter (supondremos que el usuario introduce unamayúscula), lo pase a minúscula y lo imprima en pantalla. Hacedlo sin usar las fun-ciones toupper ni tolower de la biblioteca cctype. Para ello, debe considerarsela equivalencia en C++ entre los tipos enteros y caracteres.

Finalidad: Entender la equivalencia de C++ entre tipos enteros y de carácter. DificultadBaja.

15. Supongamos el siguiente código:

int entero;char caracter;

caracter = '7';entero = caracter;

Guión de Prácticas. Fundamentos de Programación 17

Page 293: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS I. Introducción a C++

La variable entero almacenará el valor 55 (el orden en la tabla ASCII del carácter'7'). Queremos construir una expresión que devuelva el entero 7, para asignarlo a lavariable entero. Formalmente:

Supongamos una variable car de tipo carácter que contiene un valor entre '0' y '9'.Construid un programa que obtenga el correspondiente valor entero, se lo asigne auna variable de tipo int llamada entero y lo imprima en pantalla. Por ejemplo, si lavariable car contiene '7' queremos asignarle a entero el valor numérico 7.

Nota. La comilla simple para representar un literal de carácter es la que hay en elteclado del ordenador debajo de la interrogación ?.

Finalidad: Entender la equivalencia de C++ entre tipos enteros y de carácter. DificultadBaja.

16. Razonar sobre la falsedad o no de las siguientes afirmaciones:

a) 'c' es una expresión de caracteres.

b) 4<3 es una expresión numérica.

c) (4+3)<5 es una expresión numérica.

d) cout << a; da como salida la escritura en pantalla de una a.

e) ¿Qué realiza cin >> cte, siendo cte una constante entera?

Finalidad: Distinguir entre expresiones de distinto tipo de dato. Dificultad Baja.

17. Escribid una expresión lógica que sea verdadera si una variable de tipo carácter lla-mada letra es una letra minúscula y falso en otro caso.

Escribid una expresión lógica que sea verdadera si una variable de tipo entero llamadaedad es menor de 18 o mayor de 65.

Escribid una expresión lógica que nos informe cuando un año es bisiesto. Los añosbisiestos son aquellos que o bien son divisibles por 4 pero no por 100, o bien sondivisibles por 400.

Nota: Cuando se imprime por pantalla (con cout) una expresión lógica que es true,se imprime 1. Si es false, se imprime un 0. En el tema 2 veremos la razón.

Finalidad: Empezar a trabajar con expresiones lógicas, muy usadas en el tema 2.Dificultad Baja.

18. Indique qué tipo de dato usaría para representar:

• Edad de una persona

• Producto interior bruto de un país. Consultad:http://es.wikipedia.org/wiki/Anexo:Pa%C3%ADses_por_PIB_(nominal)

• La cualidad de que un número entero sea primo o no.

Guión de Prácticas. Fundamentos de Programación 18

Page 294: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS I. Introducción a C++

• Estado civil (casado, soltero, separado, viudo)

• Sexo de una persona (hombre o mujer exclusivamente)

Finalidad: Saber elegir adecuadamente un tipo de dato, atendiendo a la informaciónque se quiere representar. Dificultad Media.

Problemas de Ampliación

19. El precio final de un automóvil para un comprador es la suma total del costo del vehícu-lo, del porcentaje de ganancia de dicho vendedor y del I.V.A. Diseñar un algoritmo paraobtener el precio final de un automóvil sabiendo que el porcentaje de ganancia de estevendedor es del 20 % y el I.V.A. aplicable es del 16 %.

Dificultad Baja.

20. Declarar las variables necesarias y traducir las siguientes fórmulas a expresiones vá-lidas del lenguaje C++.

a)1 + x2

y

x3

1+y

b)1 + 1

3sinh− 1

7cosh

2 h

c)

√1 +

(ex

x2

)2

Algunas funciones decmathsen(x) −→ sin(x)cos(x) −→ cos(x)xy −→ pow(x, y)ln(x) −→ log(x)ex −→ exp(x)

Dificultad Baja.

21. Dos locomotoras parten de puntos distintos avanzando en dirección contraria sobrela misma vía. Se pide redactar un programa para conocer las distancias que habránrecorrido ambas locomotoras antes de que choquen teniendo en cuenta que la primeralocomotora viaja a una velocidad constante V1, que la segunda viaja a una velocidadconstante V2, la fórmula que relaciona velocidad, espacio y tiempo (s = v t) y queel momento en que se producirá el choque viene dado por la fórmula

t =D

V1 + V2

Dificultad Baja.

22. El área A de un triángulo se puede calcular a partir del valor de dos de sus lados, a y

b, y del ángulo θ que éstos forman entre sí con la fórmulaA =1

2ab sin(θ). Construid

Guión de Prácticas. Fundamentos de Programación 19

Page 295: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS I. Introducción a C++

un programa que pida al usuario el valor de los dos lados (en centímetros), el ánguloque éstos forman (en grados), y muestre el valor del área.

Tened en cuenta que el argumento de la función sin va en radianes por lo que habráque transformar los grados del ángulo en radianes.

Dificultad Baja.

23. Escribir un programa que lea un valor entero. Supondremos que el usuario introducesiempre un entero de tres dígitos, como por ejemplo 351. Escribid en pantalla losdígitos separados por tres espacios en blanco. Con el valor anterior la salida sería:

3 5 1

Dificultad Media.

24. Los compiladores utilizan siempre el mismo número de bits para representar un tipode dato entero (este número puede variar de un compilador a otro). Por ejemplo, 32bits para un int. Pero, realmente, no se necesitan 32 bits para representar el 6, porejemplo, ya que bastarían 3 bits:

6 = 1 ∗ 22 + 1 ∗ 21 + 0 ∗ 20 ≡ 110

Se pide crear un programa que lea un entero n, y calcule el mínimo número de dígitosque se necesitan para su representación. Para simplificar los cómputos, suponed quesólo queremos representar valores enteros positivos (incluido el cero). Consejo: senecesitará usar el logaritmo en base 2 y obtener la parte entera de un real (se obtienetras el truncamiento que se produce al asignar un real a un entero)

Dificultad Media.

Guión de Prácticas. Fundamentos de Programación 20

Page 296: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS I. Introducción a C++

Sesión 1

I Actividades a realizar en casa

Actividad: Conseguir login y password.

Antes de empezar la primera sesión de prácticas el alumno debe estar registrado en laUniversidad, tal y como se indica en:http://www.ugr.es/informatica/alumnos/correo.htmDe esta forma, obtendremos un login y un password que habrá que introducir al arrancarlos ordenadores en las aulas de prácticas. La cuenta tarda 48 horas an activarse, por lo queel registro debe realizarse al menos dos días antes de la primera sesión de prácticas.

Actividad: Instalación de Visual Studio.

Durante la primera semana de clase, el alumno debería instalar en su casa el compiladorVisual Studio. Consultad la sección de Instalación (página 7) de este guión.

Actividad: Resolución de problemas.

Realizad una lectura rápida de las actividades a realizar durante la próxima sesión de prác-ticas en las aulas de ordenadores.Resolved los ejercicios siguientes de la relación de problemas I, página 13 (utilizando úni-camente papel y lápiz):

• Obligatorios: 1, 2, 3, 4, 5, 6

• Opcionales: 7, 8

Actividades de Ampliación

Leer el artículo de Norvig: Aprende a programar en diez añoshttp://loro.sourceforge.net/notes/21-dias.html

sobre la dificultad del aprendizaje de una disciplina como la Programación.

Guión de Prácticas. Fundamentos de Programación 21

Page 297: Fundamentos de Programacion

El Entorno de Programación. Compilación de Programas

I Actividades a realizar en las aulas de ordenadoresDurante esta sesión de prácticas, el profesor irá corrigiendo individualmente (a algunosalumnos elegidos aleatoriamente) los ejercicios indicados anteriormente. Mientras tanto, elresto de alumnos deben seguir las instrucciones indicadas en los siguientes apartados. Enla última media hora, el profesor explicará los ejercicios.

El Entorno de Programación. Compilación de Programas

Arranque del Sistema Operativo

Para poder arrancar el SO en las aulas de ordenadores, es necesario obtener el login ypassword indicados en las actividades a realizar en casa.En la casilla etiquetada como Código, introduciremos fp. Al arrancar el SO, aparecerá unainstalación básica de XP con el compilador Microsoft Visual C++. Todo lo que escribamos enla unidad C: se perderá al apagar el ordenador. Por ello, el alumno dispone de un directoriode trabajo en la unidad lógica U:, cuyos contenidos permanecerán durante todo el cursoacadémico. En cualquier caso, es recomendable no saturar el espacio usado ya que, encaso contrario, el compilador no podrá funcionar.El alumno deberá crear el directorio (U:\FP). Si durante la sesión se requiere abrir algúnfichero, éste puede encontrarse en la carpeta del Sistema Operativo

H:\CCIA\Grado_FP\

También están accesibles en la web a través de la página web de la asignatura (accesoidentificado)https://decsai.ugr.es

Muy Importante. Los ficheros que se encuentran en la unidad H: están protegidos y nopueden modificarse. Por tanto, habrá que copiarlos a la unidad local U:, dónde ya sí podránser modificados.Nota. En el escritorio de XP, se encuentra un acceso directo a la carpetaH:\CCIA\Grado_FP.

El primer programa

Copiando el código fuente

En el directorio H:\ccia\Grado_FP\ProblemasI se encuentra el directorioI_Pitagoras. Copiadlo entero a vuestra carpeta local (dentro de U:\FP).

Guión de Prácticas. Fundamentos de Programación 22

Page 298: Fundamentos de Programacion

El Entorno de Programación. Compilación de Programas

Importante: Siempre hay que copiar localmente las carpetas que aparecen en la unidad H:del departamento ya que están protegidos contra escritura y no se puede trabajar directa-mente sobre los proyectos incluidos en dichas carpetas.Desde el Explorador de Windows, entrad en la carpeta recién creada en vuestra cuenta:

U:\FP\I_Pitagoras

y observad los ficheros que contiene. Cada vez que creemos un programa desde VisualStudio se creará automáticamente una carpeta (en este caso I_Pitagoras) con distintosficheros necesarios para el compilador Visual Studio. Por ejemplo, podemos encontrar losficheros

I_Pitagoras.vcprojI_Pitagoras.slnI_Pitagoras.cpp

Por ahora, lo único que nos interesa saber es lo siguiente:

• Para abrir directamente Visual Studio, basta con hacer doble click sobre los ficheros.vcproj o .sln. Al hacerlo, automáticamente se abrirá Visual Studio y cargará elproyecto que, entre otras cosas, contiene el fichero de código fuente con extensión.cpp. Para abrirlo, haremos doble click sobre él desde el Explorador de Solucionesde Visual Studio.

Importante : No debe hacerse doble click desde el Explorador de Windows sobre elfichero con extensión .cpp, ya que, en dicho caso, Visual Studio lo abriría pero nopodríamos compilarlo al no encontrarse dentro de un proyecto.

Para poder compilar un fichero, éste debe estar incluido en un proyecto

• El fichero realmente interesante es el que tiene la extensión cpp. En nuestro caso esI_Pitagoras.cpp. Estos serán los ficheros sobre los que escribiremos el código denuestros programas. Este fichero se abrirá automáticamente en el editor de Visual Stu-dio, después de que hallamos cargado el correspondiente fichero I_Pitagoras.sln

Haced doble click sobre el fichero I_Pitagoras.sln. Debe aparecer una ventana comola de la figura 1 (el sitio exacto en el que se muestran las distintas ventanas del entornopuede cambiar):

Guión de Prácticas. Fundamentos de Programación 23

Page 299: Fundamentos de Programacion

El Entorno de Programación. Compilación de Programas

Figura 1: Programa que implementa el algoritmo de Pitágoras

Guión de Prácticas. Fundamentos de Programación 24

Page 300: Fundamentos de Programacion

El Entorno de Programación. Compilación de Programas

Algunas consideraciones con respecto a la escritura de código en C++ (ver figura 2)

• Es bueno que, desde el principio se incluyan comentarios indicando el objetivo delprograma y resaltando los aspectos más importantes de la implementación.

• Es muy importante una correcta tabulación de los programas. Por ahora, incluiremostodas las sentencias del programa principal con una tabulación. Sólo es necesarioincluir la primera; el resto las pone automáticamente el entorno, al pasar a la siguientelínea.

• Para facilitar la lectura del código fuente, se deben usar espacios en blanco para se-parar las variables en la línea en la que van declaradas, así como antes y despuésdel símbolo = en una sentencia de asignación. Dejad también un espacio en blancoantes y después de << y >> en las sentencias que contienen una llamada a cout ycin respectivamente.

Figura 2: Escritura de código

No respetar las normas de escritura de código baja puntos en todos losexámenes y prácticas de la asignatura

Guión de Prácticas. Fundamentos de Programación 25

Page 301: Fundamentos de Programacion

El Entorno de Programación. Compilación de Programas

Observad la última sentencia

system("pause");

Veamos para qué sirve. Cuando el programa se ejecuta desde el entorno del VisualStudio, automáticamente se abre una ventana de consola para ofrecer resultados yleer datos. Cuando el programa termina de funcionar, automáticamente se cierra estaventana, por lo que si había algún mensaje escrito en ella, no da tiempo a leerlo.

Para resolver este problema, ejecutamos el comando pause de la consola del SistemaOperativo. Este comando hace que se muestre el mensaje en pantalla

Pulse cualquier tecla para continuar

La ejecución del programa se detiene y cuando el usuario pulsa cualquier tecla, prosi-gue la ejecución.

La forma de ejecutar un comando cualquiera de la consola, desde dentro de un progra-ma de C++, es a través del recurso system, pasándole como parámetro una cadenade caracteres con el comando que se quiere ejecutar. En nuestro caso sería, tal ycomo aparece arriba, system("pause");.

Compilación

Una vez cargado el programa, pasamos a comprobar si las sentencias escritas son sintácti-camente correctas, es decir, pasamos a compilar el programa. Para ello pulsamos Ctr-F7,

o bien sobre el icono .Para que el proceso de compilación se realice de forma correcta y se obtenga el programaejecutable, es necesario que el código fuente no contenga errores sintácticos. Si aparecenerrores, es necesario volver a la fase de edición, guardar de nuevo el código fuente y repetirla fase de compilación.Como resultado de la fase de compilación, en la esquina inferior izquierda del entorno debeaparecer un mensaje del tipo:

Generación satisfactoria

Una vez compilado el programa, pasamos a generar el ejecutable, I_Pitagoras.exe.Para ello, o bien pulsamos Alt-Ctr-F7 o bien sobre el icono de la barra de herramientasque contiene el texto Volver a generar solución. Finalmente, para ejecutar el pro-grama pulsamos pulsamos F5 o sobre el icono . Si se quiere ejecutar directamente, bastapulsar F5, sin dar los dos primeros pasos de compilación y generación.Debe aparecer una ventana de comandos del Sistema, en la que se estará ejecutando elprograma. La ejecución del programa se detendrá en aquellos puntos del mismo donde

Guión de Prácticas. Fundamentos de Programación 26

Page 302: Fundamentos de Programacion

El Entorno de Programación. Compilación de Programas

se requiera la interacción del usuario para poder proseguir, es decir, en la operaciones deentrada de datos a través del dispositivo estándar de entrada. En este ejemplo, sería en lasdos operaciones cin. En el resto de los casos, la ejecución del programa continuará hastael final. La introducción de datos mediante la sentencia cin se hace siempre de la mismamanera; primero se introduce el valor que se desee y al terminar se pulsa la tecla RETURN.Introducid ahora los valores pedidos en el ejemplo de Pitágoras y comprobad la respuestadel programa.Como hemos indicado anteriormente, en la fase de generación del ejecutable se ha crea-do un fichero en el Sistema que se llama igual que nuestro fichero pero sustituyendo laextensión ”cpp” por ”exe”, es decir, I_Pitagoras.exe. Este fichero se encuentra en eldirectorio Debug, dentro de la carpeta I_Pitagoras que habíamos copiado localmen-te. Para mostrar que el fichero generado es independiente del entorno de programación,hacemos lo siguiente:

1. Cerramos Visual Studio

2. Abrid una ventana de Mi PC.

3. Situarse en la carpeta dónde se guardó el código fuente.

4. Haced doble click sobre el fichero I_Pitagoras.exe.

Nota. En la instalación por defecto de Visual Studio que hagamos en nuestra casa, losficheros de salida e intermedios necesarios por Visual Studio se almacenan en la mismacarpeta del proyecto.

Prueba del programa

Uno podía pensar que una vez que consigo un fichero ejecutable a partir de mi código fuen-te, el problema está terminado. Sin embargo esto no es así. Tras el proceso de compilado serequiere una fase de prueba. Dicha fase intenta probar que el algoritmo planteado resuelveel problema propuesto. Para llevar a cabo esta fase, es necesario ejecutar el programa yverificar que los resultados que obtiene son los esperados.Ahora que podemos ver el resultado obtenido por el programa implementado, verifiquemosmediante el siguiente conjunto de pruebas que el programa funciona de forma correcta.

lado1 lado2 hip3 4 51 5 5.099

2.7 4.3 5.0771.25 2.75 3.02

Una vez que el algoritmo supera la fase de prueba, podemos considerar que se ha concluidocon la fase inicial del desarrollo del software.

Guión de Prácticas. Fundamentos de Programación 27

Page 303: Fundamentos de Programacion

El Entorno de Programación. Compilación de Programas

Introducción a la corrección de errores

Los errores de compilación

Ya hemos visto los pasos necesarios para construir un fichero ejecutable a partir del códigofuente. El paso central de este proceso era la fase de compilación. En esta parte de esteguión de prácticas aprenderemos a corregir los errores más comunes que impiden unacompilación exitosa del fichero fuente.Cargad el proyecto I_Pitagoras.sln (no olvidad que desde el Sistema Operativo hayque seleccionar el fichero con extensión vcproj o sln). En la ventana del Exploradorde Soluciones, haced doble click sobre I_Pitagoras.cpp para poder editar el fichero.Quitadle una 'u' a alguna aparición de cout. Intentad compilar. Podemos observar quela compilación no se ha realizado con éxito. Cuando esto sucede, en la parte inferior dela ventana principal, en la pestaña Lista de errores, aparecen los errores que se hanencontrado. Aparece una descripción del error, así como otra información, como el númerode línea en la que se produjo. Los pasos que debemos seguir para la corrección son lossiguientes:

1. Ir a la primera fila de la lista de errores.

2. Leer el mensaje de error e intentar entenderlo.

3. Hacer doble click sobre esa fila con el ratón. Esto nos posiciona sobre la línea en elfichero fuente donde el compilador detectó el error.

4. Comprobar la sintaxis de la sentencia que aparece en esa línea. Si se detecta el error,corregirlo. Si no se detecta el error mirar en la línea anterior, comprobar la sintaxis yrepetir el proceso hasta encontrar el error.

5. Después de corregir el posible error, guardamos de nuevo el archivo y volvemos acompilar. Esto lo hacemos aunque aparezcan más errores en la ventana. La razón esque es posible que el resto de los errores sean consecuencia del primer error.

6. Si después de corregir el error aparecen nuevos errores, volver a repetir el procesodesde el paso 1.

A veces, el compilador no indica la línea exacta en la que se produce el error, sino algunaposterior. Para comprobarlo, haced lo siguiente:

• Comentad la línea de cabecera #include <iostream> desde el principio. El com-pilador no reconocerá las apariciones de cin o cout.

• Quitad un punto y coma al final de alguna sentencia. Dará el error en la línea siguiente.

Guión de Prácticas. Fundamentos de Programación 28

Page 304: Fundamentos de Programacion

El Entorno de Programación. Compilación de Programas

Para familiarizarnos con los errores más frecuentes y su corrección vamos a realizar elsiguiente proceso: a partir del código fuente del ejemplo I_Pitagoras.cpp, iremos intro-duciendo deliberadamente errores para conocer los mensajes que nos aparecen. A conti-nuación se muestran algunos errores posibles. No deben introducirse todos ellos a la vez,sino que han de probarse por separado.

1. Cambiad algún punto y coma por cualquier otro símbolo

2. Cambiad double por dpuble

3. Cambiad la línea using namespace std; por using namespace STD;

4. Poned en lugar de iostream, el nombre iotream.

5. Borrad alguno de los paréntesis de la declaración de la función main

6. Introducid algún identificador incorrecto, como por ejemplo cour

7. Usad una variable no declarada. Por ejemplo, en la definición de variables cambiad elnombre a la variable lado1 por el identificador lado11.

8. Borrad alguna de las dobles comillas en una constante de cadena de caracteres, tantolas comillas iniciales como las finales.

9. Borrad alguna de las llaves que delimitan el inicio y final del programa.

10. Borrad la línea using namespace std; (basta con comentarla con //)

11. Cambiad un comentario iniciado con //, cambiando las barras anteriores por las si-guientes \\

12. Cambiad la aparición de << en cout por las flechas cambiadas, es decir, >>. Hacedlo mismo con cin.

13. Suprimid todo el main. No hace falta borrar el código, basta con comentarlo.

14. Aunque no sea un error, comentad la última linea que contiene system("pause");para comprobar que el programa se ejecuta correctamente, pero no da tiempo a verlos resultados en la consola.

Además de los errores, el compilador puede generar avisos. Estos se muestran en la pesta-ña Advertencias en la misma ventana de la lista de errores. Estas advertencias indicanque algún código puede generar problemas durante la ejecución. Por ejemplo, al usar unavariable que todavía no tiene un valor asignado, al intentar asignar un entero grande a unentero chico, etc. Sin embargo, no son errores de compilación, por lo que es posible generarel programa ejecutable correspondiente.

Guión de Prácticas. Fundamentos de Programación 29

Page 305: Fundamentos de Programacion

El Entorno de Programación. Compilación de Programas

Los errores lógicos y en tiempo de ejecución

Aunque el programa compile, esto no significa que sea correcto. Puede producirse unaexcepción durante la ejecución, de forma que el programa terminará bruscamente (típicoerror en Windows de Exception Violation Address) o, lo que es peor, dará una salida que noes correcta (error lógico).Sobre el programa I_Pitagoras.cpp, haced lo siguiente:

• Cambiad la sentenciasqrt(lado1*lado1 + lado2*lado2) por:sqrt(lado1*lado2 + lado2*lado2)

Ejecutad introduciendo los lados 2 y 3. El resultado no es correcto, pero no se produceningún error de compilación ni en ejecución. Es un error lógico.

• Para mostrar un error de ejecución, declarad tres variables ENTERAS (tipoint) resultado, numerador y denominador. Asignadle cero a denominadory 7 a numerador. Asignadle a resultado la división de numerador entredenominador. Imprimid el resultado. Al ejecutar el programa, se produce una ex-cepción o error de ejecución al intentar dividir un entero entre cero.

Creación de un programa nuevo

En esta sección vamos a empezar a crear nuestros propios programas desde Visual Studio.El primer ejemplo que vamos a implementar corresponde al ejercicio 1 sobre la Ley de Ohm,de la relación de problemas I.Para crear un programa nuevo, abrimos Visual Studio y elegimos

Archivo->Nuevo ProyectoSi tenemos instalados varios lenguajes (Visual Basic, C#, etc), elegimos C++. Nosaparecen distintos tipos de proyectos, en función de lo que vayamos a crear (una aplicaciónen Consola, un formulario de Windows, etc). Elegimos Proyecto vacío. En la parte in-ferior de la ventana, hacemos click sobre Examinar para elegir la carpeta donde colgaráel directorio de nuestra aplicación. En nuestro caso, será U:\FP. Finalmente elegimos unnombre para nuestra aplicación. Teclead I_Voltaje y pulsad sobre Aceptar (ver figura 3)Se nos abrirá una ventana con el Explorador de Soluciones.Sobre la carpeta Archivos de código fuente pulsamos click con la derecha y se-leccionamos Agregar->Nuevo elemento. Seleccionamos Archivo C++ (.cpp) y ledamos un nombre. Podemos darle el mismo nombre que el del proyecto, I_Voltaje (verfigura 4)Llegado a este paso, debemos tener el entorno de Visual Studio, con varias ventanas comolas de la figura 5 (la situación exacta de las ventanas puede variar)

Guión de Prácticas. Fundamentos de Programación 30

Page 306: Fundamentos de Programacion

El Entorno de Programación. Compilación de Programas

Figura 3: Creación de un proyecto nuevo

Figura 4: Añadiendo un fichero de código vacío

Guión de Prácticas. Fundamentos de Programación 31

Page 307: Fundamentos de Programacion

El Entorno de Programación. Compilación de Programas

Figura 5: Entorno de Visual Studio

Ya estamos en condiciones de resolver el problema pedido. Escribimos el código en laventana correspondiente a la pestaña I_Voltaje.cpp. Habrá que leer desde teclado losvalores de intensidad y resistencia y el programa imprimirá en pantalla el voltaje correspon-diente. Recordad que compilamos con Ctr-F7 y ejecutamos con F5.

Nota. Cuando tenemos varias variables en el código, podemos empezar a escribir el nombrede alguna de ellas y antes de terminar, pulsar Ctr-Barra espaciadora. La ayuda nosmostrará los identificadores disponibles que empiecen por las letras tecleadas.A partir de ahora, cada uno de los ejercicios irá en un proyecto nuevo. Implementad losejercicios que se habían mandado para esta sesión en este orden: 2, 3, 4, 5, 6. Usad enesta sesión el tipo de proyecto "Proyecto Vacío".

Guión de Prácticas. Fundamentos de Programación 32

Page 308: Fundamentos de Programacion

Tipos básicos y operadores

Sesión 2

Tipos básicos y operadores

I Actividades a realizar en casa

Actividad: Seminario.

Realizar un resumen de los modificadores de tipo de dato ofrecidos por C++ como porejemplo long, unsigned, etc. En las transparencias de teoría del primer tema puedenencontrarse enlaces en la Web con la información necesaria.Analizad las ventajas e inconvenientes de poder disponer de este amplio conjunto de tiposde datos.Alguno de los alumnos deberá exponer este trabajo durante las horas de teoría (en el aulagrande) en la semana que indique el profesor.

Actividad: Resolución de problemas.

Resolved los siguientes problemas de la relación I. Por cada uno de ellos, habrá que crearel correspondiente proyecto. Usad el tipo de proyecto "Proyecto Vacío". Recordad que antesdel inicio de esta sesión en el aula de ordenadores hay que subir las soluciones a la cuentapersonal en turing.ugr.es tal y como se indica en la página 4.

• Obligatorios:

10 (Fabricantes con enteros)11 (Media y desviación con enteros)12 (Precisión con reales)13 (Precisión con reales)14 (Pasar de mayúscula a minúscula)15 (Pasar de carácter a entero)

• Opcionales:

9 (Horas, minutos y segundos)18 (Tipos de datos para representar información diversa)

Guión de Prácticas. Fundamentos de Programación 33

Page 309: Fundamentos de Programacion

Tipos básicos y operadores

Actividades de Ampliación

Recordad los conceptos de combinación y permutación, que irán apareciendo recurrente-mente a lo largo de la carrera. Consultad, por ejemplohttp://www.disfrutalasmatematicas.com/combinatoria/combinaciones-permutaciones.html

para una introducción básica a los conceptos, yhttp://club.telepolis.com/ildearanda/index.html

como una referencia a las fórmulas que nos proporcionan los cómputos correspondientes.Ejecutad el applethttp://www.disfrutalasmatematicas.com/combinatoria/combinaciones-permutaciones-calculadora.html

con los valores pertinentes para calcular cuántos número distintos se pueden representarutilizando únicamente dos símbolos (0 y 1) en 64 posiciones de memoria. Ejecutad el mismoapplet para que muestre en la parte inferior las distintas permutaciones que se puedenconseguir con 2 símbolos (0,1) y 4 posiciones.

Guión de Prácticas. Fundamentos de Programación 34

Page 310: Fundamentos de Programacion

Configuración del proyecto y gestión de errores

I Actividades a realizar en las aulas de ordenadoresTodas las sesiones de prácticas en el aula, a partir de ésta, se desarrollarán de la mismaforma: El profesor irá corrigiendo individualmente (a algunos alumnos elegidos aleatoria-mente) los ejercicios indicados anteriormente. Mientras tanto, el resto de alumnos debenseguir las instrucciones indicadas en la sesión de prácticas. Cuando terminen, pueden em-pezar a resolver los problemas planteados para la siguiente sesión. En la segunda hora, elprofesor sacará a la pizarra a algunos alumnos para que expliquen algunos problemas deesta sesión, y explicará el resto de ejercicios.

Configuración del proyecto y gestión de errores

Los proyectos en Microsoft Visual C++ pueden ser generados con muchas opciones. Porejemplo, se puede añadir al fichero ejecutable información de depuración, para poder rea-lizar un seguimiento de las instrucciones ejecutadas, o que detecte los problemas paraexportar el programa a una plataforma de 64 bits, etc. Estas opciones están disponiblesdesde el Explorador de Soluciones, pinchando con la izquierda el proyecto y seleccionan-do Propiedades, o bien directamente desde el menú Proyecto->Propiedades. Novamos a ver ninguna de estas opciones, aunque sí debemos saber cómo influyen en eldesarrollo de un programa. Normalmente, los programas se desarrollan en dos fases:

1. En una primera fase, se usa un entorno optimizado de depuración. Esto supone unarecarga computacional importante, pero es muy adecuada para detectar errores deprogramación, como por ejemplo, el usar una variable no asignada previamente. Cuan-do se trabaja en esta fase, hay que seleccionar

Proyecto -> Propiedades

y pinchad sobre Administrador de configuración en la esquina superiorderecha. Dentro de Configuración de soluciones activas, seleccionadDebug. Esta es la configuración adecuada en esta primera fase. Para probarlo, copiadla carpeta I_Voltaje del directorio de la asignatura a la unidad local U:\FP. Abridel proyecto y comentad la sentencia en la que se realiza la lectura de la intensidad

// cin >> intensidad;

Cuando se llegue a ejecutar la sentencia

voltaje = intensidad * resistencia;

el valor de intensidad será basura. Si compilamos el programa con Ctr-F7 pode-mos apreciar que se genera una advertencia en la lista de errores, indicando que se

Guión de Prácticas. Fundamentos de Programación 35

Page 311: Fundamentos de Programacion

Configuración del proyecto y gestión de errores

está usando la variable intensidad sin haberle asignado previamente un valor. Aúnasí, podemos generar el fichero .exe y ejecutarlo. Hacedlo, para comprobar el errorque se obtiene en tiempo de ejecución.

2. En una segunda fase, cuando ya hemos comprobado que el programa funciona co-rrectamente, se procede a generar el fichero ejecutable (.exe) eliminando la infor-mación de depuración (entre otras cosas). Esto hará que el ejecutable obtenido seabastante más pequeño. Para ello, hay que cambiar la configuración antes de generarel ejecutable. Volvemos a entrar enConfiguración de soluciones activasy seleccionamos Release. Podemos hacerlo directamente desde el botón disponibleen la esquina superior derecha de la barra de herramientas. Si generamos el progra-ma bajo esta última configuración, veremos que al ejecutarlo no se produce un errordurante la ejecución. Esto es debido, como ya hemos comentado, a que el compila-dor ya no pierde el tiempo comprobando estos posibles errores de programación. Porcontra, obtendremos un error lógico ya que la variable intensidad contiene basuray al multiplicarla por la variable resistencia el resultado será basura.

A lo largo de la asignatura, usaremos siempre la configuración Debug, por lo que al-gunos errores de programación, como el uso de variables no asignadas previamente,serán detectados por el compilador. Pero debemos tener claro que en en la configu-ración Release, o bien en la compilación realizada con otros compiladores distintosa Visual Studio, no se producirá ningún error durante la ejecución sino un lamentableerror lógico.

En el entorno Visual Studio de las aulas de prácticas, se ha incluido una plantilla con lasopciones de configuración de compilación más usuales (tanto para la configuración Debugcomo Release) así como un esqueleto del programa principal que incluye la cabecera queusaremos siempre en nuestros programas. Para crear un programa nuevo basándonos enesta plantilla, basta hacer lo siguiente:

Archivo -> Nuevo Proyecto -> _fp_2010

Seleccionamos una ubicación (usualmente U:\FP) y tecleamos un nombre para el proyec-to. A partir de esta sesión usaremos siempre la plantilla _fp_2010 para crear nuestrosproyectos.Para instalar esta plantilla en nuestros ordenadores personales, seguid las instruccionesque se encuentran en la página 7

Guión de Prácticas. Fundamentos de Programación 36

Page 312: Fundamentos de Programacion

Configuración del proyecto y gestión de errores

Ejercicio.Cread un proyecto nuevo llamado Prueba_Tipos. Declarad variables de tipo int,double, float, double, char y bool. Provocad errores de compilación y lógicosal mezclar distintos tipos de datos en una misma expresión. Por ejemplo:

– Asignad a un dato un literal fuera de rango,

– Forzad un error en ejecución al dividir un entero por cero,

– Provocar errores lógicos de desbordamiento con un único tipo de dato,

– Provocar errores lógicos de desbordamiento mezclando distintos tipos de dato enuna misma expresión, · · ·

Ejercicio.Copiad a la unidad local la carpeta I_Pitagoras. Cargad el proyecto y cambiad lasuma dentro de sqrt por una resta. Ejecutad introduciendo los lados 2 y 3.

Como el resultado es la raíz cuadrada de un número negativo, el ordenador no puedehacer los cálculos y muestra -1.#IND. Tal y como se vio en clase de teoría, este es elvalor de Indeterminación, representable en los datos de coma flotante (double1 es untipo de dato en coma flotante). En este caso se ha producido un error lógico, pero enotro lenguaje de programación que no utilizase una representación de reales en comaflotante, podría haberse producido un error fatal durante la ejecución, terminándosede forma brusca el programa.

Si sobra tiempo, realizad cualquiera de los ejercicios de ampliación de la Relación de Pro-blemas I de la página 19

1El valor de indeterminación no puede representarse en un tipo entero

Guión de Prácticas. Fundamentos de Programación 37

Page 313: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS II. Estructuras de Control

RELACIÓN DE PROBLEMAS II. Estructuras de Control

Problemas Básicos

1. Ampliad el ejercicio 7 de la relación de problemas I, para que, una vez calculada lamedia y la desviación, el programa imprima por cada uno de los valores introducidospreviamente, si está por encima o por debajo de la media. Por ejemplo:

33 es menor que su media48 es mayor o igual que su media.....

Nota. Los valores introducidos son enteros, pero la media y la desviación son reales.

Finalidad: Plantear un ejemplo básico con varias estructuras condicionales indepen-dientes. Dificultad Baja.

2. Cread un programa que incluya una variable edad en la que guardamos la edad deuna persona (como una variable entera) y otra variable ingresos, en la que alma-cenamos sus ingresos (como un real). Subid sus ingresos en un 5% si es un jubiladocon unos ingresos inferiores a 300 euros e imprimid el resultado por pantalla. En casocontrario imprimid el mensaje "No es aplicable la subida". En ambos casosimprimid los ingresos resultantes.

Finalidad: Plantear una estructura condicional doble con una expresión lógica com-puesta. Dificultad Baja.

3. Realizar un programa en C++ que lea dos valores enteros desde teclado y diga sicualquiera de ellos divide o no (de forma entera) al otro. En este problema no hacefalta decir quién divide a quién. Supondremos que los valores leídos desde tecladoson ambos distintos de cero y se pueden mezclar cómputos con entradas y salidas.

Finalidad: Plantear una estructura condicional doble con una expresión lógica com-puesta. Dificultad Baja.

4. Vamos a modificar el ejercicio 3 de la siguiente forma. Queremos leer dos valoresenteros desde teclado y, en el caso de que uno cualquiera de ellos divida al otro, elprograma nos debe decir quién divide a quién.

a) En primer lugar, resolved el ejercicio mezclando entradas, cómputos y salidas deresultados

b) En segundo lugar, se pide resolver el ejercicio sin mezclar C/E,S. Para ello, seofrecen varias alternativas. ¿Cual sería la mejor? Escoged una e implementar lasolución.

Guión de Prácticas. Fundamentos de Programación 38

Page 314: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS II. Estructuras de Control

I) Utilizar un variable de tipo string de la forma siguiente:string quien_divide;.............if (a%b==0)

quien_divide = "b divide a a" ;.............if (quien_divide == "b divide a a")

cout << b << " divide a " << a;

Nota. Para poder usar el operador de comparación == entre dos string,hay que incluir la biblioteca string.Si se opta por esta alternativa, el suspenso está garantizado. ¿Por qué?

II) Utilizar dos variables lógicas de la forma siguiente:bool a_divide_b, b_divide_a;.............if (a%b==0)

a_divide_b = true;.............if (a_divide_b)

cout << a << "divide a " << b;

III) Detectamos si se dividen o no y usamos otras dos variables que me indiquenquien es el dividendo y quien el divisor:

bool se_dividen;int Divdo, Divsor;.............if (a%b==0){

Divdo = a;.............if (se_dividen)

cout << Dvsor << " divide a " << Dvdo;

Completar la solución elegida para contemplar también el caso en el que alguno delos valores introducidos sea cero, en cuyo caso, ninguno divide al otro.

Finalidad: Mostrar cómo se comunican los distintos bloques de un programa a travésde variables que indican lo que ha sucedido en el bloque anterior. Dificultad Media.

5. Se quiere leer un carácter letra_original desde teclado, y comprobar con unaestructura condicional si es una letra mayúscula. En dicho caso, hay que calcu-lar la minúscula correspondiente en una variable llamada letra_convertida.En cualquier otro caso, le asignaremos a letra_convertida el valor quetenga letra_original. Finalmente, imprimiremos en pantalla el valor deletra_convertida. No pueden usarse las funciones tolower ni toupper de labiblioteca cctype.

Guión de Prácticas. Fundamentos de Programación 39

Page 315: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS II. Estructuras de Control

Se propone una primera solución como sigue:

char letra_convertida, letra_original;const int DISTANCIA_MAY_MIN = 'a'-'A';

cout << "\nIntroduzca una letra --> ";cin >> letra_original;

if ((letra_original >= 'A') && (letra_original <= 'Z')){letra_convertida = letra_original + DISTANCIA_MAY_MIN;cout << letra_convertida;

}else{

cout << letra_original << " no es una mayúscula";}

El problema es que dentro de la misma sentencia condicional se realizan cómputos(letra_convertida = letra_original + DISTANCIA_MAY_MIN ) y salidasde resultados en pantalla (cout << letra_convertida;). Para evitarlo, se pro-pone el uso de una variable lógica llamada es_mayuscula, de la siguiente forma:

if ((letra_original >= 'A') && (letra_original <= 'Z'))es_mayuscula = true;

if (es_mayuscula)letra_convertida = letra_original + DISTANCIA_MAY_MIN;

elseletra_convertida = letra_original;

cout << "\nEl carácter " << letra_original<< " una vez convertido es: " << letra_convertida;

Sin embargo, hay un error lógico ya que la variable es_mayuscula se podría quedarsin un valor asignado (en el caso de que la expresión lógica fuese false) El compiladorlo detecta y da el aviso al inicio de la sentencia if (es_mayuscula). Comprobadlopara familiarizarnos con este tipo de avisos y proponer una solución.

Moraleja: Hay que garantizar la asignación de las variables lógicas, en todos loscasos posibles

Finalidad: Plantear una condición compuesta y destacar la importancia de incluir unbloque else, para garantizar que siempre se ejecuta el código adecuado, en todaslas situaciones posibles. Dificultad Baja.

6. Queremos modificar el ejercicio 5 para leer un carácter letra_original desde te-clado y hacer lo siguiente:

Guión de Prácticas. Fundamentos de Programación 40

Page 316: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS II. Estructuras de Control

• Si es una letra mayúscula, almacenaremos en la variable letra_convertidala correspondiente letra minúscula.• Si es una letra minúscula, almacenaremos en la variable letra_convertida

la correspondiente letra mayúscula.• Si es un carácter no alfabético, almacenaremos el mismo carácter en la variableletra_convertida

Para ello, añadimos una variable nueva es_minuscula para detectar el caso en elque la letra sea una minúscula. Si escribimos el siguiente código

if (letra_original >= 'A') && (letra_original <= 'Z')es_mayuscula = true;

elsees_minuscula = true;

estaremos cometiendo el tipo de error indicado en el ejercicio 5, ya que si le asignamosun valor a una de las variables lógicas, no se lo asignamos a la otra y se queda conbasura. Para resolverlo, planteamos la siguiente solución:

if ((letra_original >= 'A') && (letra_original <= 'Z')){es_mayuscula = true;es_minuscula = false;

}else{

es_mayuscula = false;es_minuscula = true;

}

o si se prefiere, de una forma más concisa:

es_mayuscula = (letra_original >= 'A') &&(letra_original <= 'Z');

es_minuscula = !es_mayuscula;

En este planteamiento hay un error lógico que se comete de forma bastante habitual,cuando se quiere detectar más de dos situaciones posibles. En la asignación

es_minuscula = !es_mayuscula;estamos diciendo que una minúscula es todo aquello que no sea una mayúscula.Esto no es correcto, ya que un símbolo como # no es ni mayúscula ni minúscula.Deberíamos haber usado lo siguiente:

es_mayuscula = (letra_original >= 'A') &&(letra_original <= 'Z');

es_minuscula = (letra_original >= 'a') &&(letra_original <= 'z');

Guión de Prácticas. Fundamentos de Programación 41

Page 317: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS II. Estructuras de Control

Completad el ejercicio, asignándole el valor correcto a la variableletra_convertida e imprimid en pantalla el valor de letra_convertida.

Finalidad: Plantear una estructura condicional anidada. Dificultad Baja.

7. Para salir de una crisis económica, el gobierno decide:

• Bajar un 1 % la retención fiscal a los autónomos

• Para las rentas de trabajo:

– Se mantiene la misma retención fiscal a todos los pensionistas– Subir un 6 % la retención fiscal a las rentas de trabajo inferiores a 20.000

euros– Subir un 8 % la retención fiscal a los casados con rentas de trabajo superiores

a 20.000 euros– Subir un 10 % la retención fiscal a los solteros con rentas de trabajo superio-

res a 20.000 euros

Cread un programa que calcule la nueva retención a aplicar, la aplique a los ingre-sos e imprima el resultado . En este ejercicio no haremos ninguna lectura con cin,sino que declararemos las variables necesarias (por ejemplo retencion_fiscal,es_autonomo, etc) y les asignaremos los valores que se deseen directamente dentrodel código.

Nota: Cuando se pide subir un x % la retención fiscal, significa que la nueva retenciónserá la antigua más el resultado de realizar el x % sobre la antigua retención.

Finalidad: Plantear una estructura condicional anidada. Dificultad Baja.

8. Una compañía aérea establece el precio del billete como sigue: en primer lugar se fijauna tarifa base de 150 euros, la misma para todos los destinos. Si el destino está amenos de 200 kilómetros, el precio final es la tarifa inicial. Para destinos a más de 200Km, se suman 10 céntimos por cada kilómetro de distancia al destino (a partir del Km200).

En una campaña de promoción, se barajan las siguientes alternativas de políticas dedescuento:

a) Una rebaja del 3 % en el precio final, para destinos a más de 600Km

b) Una rebaja del 4 % en el precio final, para destinos a más de 1100Km

c) Una rebaja del 5 % si el comprador es cliente previo de la empresa.

Cread un programa para que lea el número de kilómetros al destino y si el billetecorresponde a un cliente previo de la empresa. Calcular el precio final del billete conlas siguientes políticas de descuento:

• Aplicando c) de forma adicional a los descuentos a) y b)

Guión de Prácticas. Fundamentos de Programación 42

Page 318: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS II. Estructuras de Control

• Aplicando c) de forma exclusiva con los anteriores, es decir, que si se aplica c),no se aplicaría ni a) ni b)

Finalidad: Plantear una estructura condicional anidada. Dificultad Media.

9. En el ejercicio 6 se han usado dos variables lógicas (es_mayuscula,es_minuscula), que nos proporciona la distinción entre 4 casos distintos(VV, VF, FV, FF). Sin embargo, sólo queremos distinguir tres posibilidades, a sa-ber, es mayúscula, es minúscula y no es un carácter alfabético. Para ello, volved aresolver el ejercicio 6 sustituyendo las dos variables lógicas por un tipo enumeradoadecuado.

Finalidad: Usar el tipo enumerado para detectar cuándo se produce una situacióndeterminada. Dificultad Media.

10. Realizar un programa que lea desde teclado un entero tope e imprima en pantallatodos sus divisores. Para obtener los divisores, basta recorrer todos los enteros me-nores que el valor introducido y comprobar si lo dividen. A continuación, mejorar elejercicio obligando al usuario a introducir un entero positivo, usando un filtro con unbucle post test (do while).

Finalidad: Plantear un ejemplo sencillo de bucle y de filtro de entrada de datos. Difi-cultad Baja.

11. Realizar un programa que lea reales desde teclado y calcule cuántos se han introduci-do y cual es el mínimo de dichos valores (pueden ser positivos o negativos). Se dejaráde leer datos cuando el usuario introduzca el valor 0. Realizad la lectura de los realesdentro de un bucle sobre una única variable llamada dato. Es importante controlar loscasos extremos, como por ejemplo, que el primer valor leído fuese ya el terminador deentrada (en este caso, el cero).

Finalidad: Destacar la importancia de las inicializaciones antes de entrar al bucle.Ejemplo de lectura anticipada. Dificultad Baja.

12. Modifiquemos el ejercicio 2 del capital y los intereses de la primera relación. Supon-gamos ahora que se quiere reinvertir todo el dinero obtenido (el original C más losintereses producidos) en otro plazo fijo a un año. Y así, sucesivamente. Construid unprograma para que lea el capital, el interés y un número de años N , y calcule e im-prima todo el dinero obtenido durante cada uno de los N años, suponiendo que todolo ganado (incluido el capital original C) se reinvierte a plazo fijo durante el siguienteaño. El programa debe mostrar una salida del tipo:

Total en el año número 1 = 240Total en el año número 2 = 288Total en el año número 3 = 345.6......................

Guión de Prácticas. Fundamentos de Programación 43

Page 319: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS II. Estructuras de Control

Finalidad: Usar una variable acumuladora dentro del cuerpo de un bucle (aparecerá ala izquierda y a la derecha de una asignación). Dificultad Baja.

13. Sobre el mismo ejercicio del capital y los intereses, construid un programa para cal-cular cuantos años han de pasar hasta llegar a doblar, como mínimo, el capital inicial.Los datos que han de leerse desde teclado son el capital inicial y el interés anual.

Finalidad: Usar la variable acumuladora en la misma condición del bucle. DificultadBaja.

14. Se pide leer un carácter desde teclado, obligando al usuario a que sea una letra ma-yúscula. Para ello, habrá que usar una estructura repetitiva do while, de forma quesi el usuario introduce un carácter que no sea una letra mayúscula, se le volverá apedir otro carácter. Calculad la minúscula correspondiente e imprimidla en pantalla.No pueden usarse las funciones tolower ni toupperde la biblioteca cctype. Si sequiere, se puede usar como base el proyecto que resolvió el ejercicio 14 de la relaciónde problemas I.

Finalidad: Trabajar con bucles con condiciones compuestas. Dificultad Baja.

15. Un número entero de n dígitos se dice que es narcisista si se puede obtener como lasuma de las potencias n-ésimas de cada uno de sus dígitos. Por ejemplo 153 y 8208son números narcisistas porque 153 = 13 + 53 + 33 y 8208 = 84 + 24 + 04 + 84.Construir un programa que, dado un número entero positivo, nos indique si el númeroes o no narcisista. Si se va a usar la función pow, no pueden ser ambos argumentosenteros, por lo que forzaremos a que la base (por ejemplo) sea double, multiplicandopor 1.0.

Finalidad: Ejercitar los bucles. Dificultad Media.

16. Calcular mediante un programa en C++ la función potencia xn, y la función factorialn! con n un valor entero y x un valor real. No pueden usarse las funciones de labiblioteca cmath.

El factorial de un entero n se define de la forma siguiente:

0! = 1

n! = 1× 2× 3× · · ·n, ∀n ≥ 1

Finalidad: Trabajar con bucles controlados por contador. Dificultad Baja.

17. Calcular mediante un programa en C++ el combinatorio(nm

)con n, m valores

enteros. No pueden usarse las funciones de la biblioteca cmath.

El combinatorio de n sobre m (con n ≥ m) es un número entero que se define comosigue: (

nm

)=

n!

m! (n−m)!

Guión de Prácticas. Fundamentos de Programación 44

Page 320: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS II. Estructuras de Control

Finalidad: Trabajar con bucles controlados por contador. Dificultad Media.

18. Todo lo que se puede hacer con un bucle while se puede hacer con un do while.Lo mismo ocurre al revés. Sin embargo, cada bucle se usa de forma natural en ciertassituaciones. El no hacerlo, nos obligará a escribir más código y éste será más difícilde entender. Para comprobarlo, haced lo siguiente:

a) Modificad la solución del ejercicio 10 de forma que el filtro de entrada usado paraleer la variable tope, se haga con un bucle pre-test while.

b) Modificad la solución del ejercicio 12 sustituyendo el bucle while por undo while. Observad que debemos considerar el caso en el que el número deaños leído fuese cero.

Finalidad: Enfatizar la necesidad de saber elegir entre un bucle pre-test o un buclepost-test. Dificultad Media.

19. Una empresa que tiene tres sucursales decide llevar la contabilidad de las ventasde sus productos a lo largo de una semana. Para ello registra cada venta con tresnúmeros, el identificador de la sucursal (1,2 ó 3), el código del producto (1, 2 ó 3) yel número de unidades vendidas. Diseñar un programa que lea desde el teclado unaserie de registros compuestos por sucursal, producto, unidades y diga cuáles la sucursal que más productos ha vendido. La serie de datos termina cuando lasucursal introducida vale -1. Por ejemplo, con la serie de datos

1 2 101 2 41 1 11 1 11 3 22 2 152 2 62 1 203 3 40-1

Se puede ver que la sucursal que más productos ha vendido es la número 2 con41 unidades totales. La salida del programa deberá seguir exactamente el siguienteformato:

SUCURSAL: 2VENTAS: 41

Para comprobar que el programa funciona correctamente, cread un fichero de texto yre-dirigid la entrada a dicho fichero.

Guión de Prácticas. Fundamentos de Programación 45

Page 321: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS II. Estructuras de Control

Finalidad: Ver un bucle en el que se leen varios datos en cada iteración, pero sólo unode ellos se usa como terminador de la entrada. Dificultad Media.

20. Supongamos una serie numérica cuyo término general es:

ai = a1ri−1

Cread un programa que lea desde teclado r, el primer elemento a1 y el tope k ycalcule la suma de los primeros k valores de la serie, es decir:

i=k∑i=1

ai

Realizad la suma de la serie usando la función pow para el cómputo de cada términoai. Los argumentos de pow no pueden ser ambos enteros, por lo que forzaremos aque la base (por ejemplo) sea double, multiplicando por 1.0.

Finalidad: Trabajar con bucles que van acumulando resultados en cada iteración. Difi-cultad Baja.

21. La serie del ejercicio 20 es una progresión geométrica ya que cada término de la seriequeda definido por la siguiente expresión:

ai+1 = ai ∗ r

Es decir, una progresión geométrica es una secuencia de elementos en la que cadauno de ellos se obtiene multiplicando el anterior por una constante denominada razóno factor de la progresión.

Cread un programa que lea desde teclado la razón r, el primer elemento a1 y el topek y calcule la suma de los primeros k valores de la progresión geométrica.

En la solución de este ejercicio NO puede utilizarse la función pow.

¿Qué solución es preferible en términos de eficiencia? ¿ésta o la del ejercicio 20?

Finalidad: Trabajar con bucles que aprovechan cómputos realizados en la iteraciónanterior. Dificultad Baja.

22. Reescribid la solución a los ejercicios 10, 12 usando un bucle for

Finalidad: Familiarizarnos con la sintaxis de los bucles for. Dificultad Baja.

23. Diseñar un programa para calcular la suma de los 100 primeros términos de la suce-sión siguiente:

ai =(−1)i(i2 − 1)

2i

No puede usarse la función pow. Hacedlo calculando explícitamente, en cada itera-ción, el valor (−1)i (usad un bucle for). Posteriormente, resolvedlo calculando dichovalor a partir del calculado en la iteración anterior, es decir, (−1)i−1.

Guión de Prácticas. Fundamentos de Programación 46

Page 322: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS II. Estructuras de Control

Finalidad: Enfatizar la conveniencia de aprovechar cómputos realizados en la iteraciónanterior. Dificultad Media.

24. El método RLE (Run Length Encoding) codifica una secuencia de datos formada porseries de valores idénticos consecutivos como una secuencia de parejas de núme-ros (valor de la secuencia y número de veces que se repite). Esta codificación es unmecanismo de compresión de datos (zip) sin pérdidas. Se aplica, por ejemplo, paracomprimir los ficheros de imágenes en las que hay zonas con los mismos datos (fondoblanco, por ejemplo). Realizar un programa que lea una secuencia de números natu-rales terminada con un número negativo y la codifique mediante el método RLE. Leedlos datos desde un fichero externo, tal y como se explica en la página 60.

Entrada: 1 1 1 2 2 2 2 2 3 3 3 3 3 3 5 -1(tres veces 1, cinco veces 2, seis veces 3, una vez 5)

Salida: 3 1 5 2 6 3 1 5

Finalidad: Controlar en una iteración lo que ha pasado en la anterior. Dificultad Media.

25. Sobre la solución del ejercicio 12 de esta relación de problemas, se pide lo siguiente.Supondremos que sólo pueden introducirse intereses enteros (1, 2, 3, etc). Se pidecalcular el capital obtenido al término de cada año, pero realizando los cálculos paratodos los tipos de interés enteros menores o iguales que el introducido (en pasos de1). Por ejemplo, si el usuario introduce un interés de 5, y un número de años igual a 3,hay que mostrar el capital ganado al término de cada uno de los tres años a un interésdel 1 %; a continuación, lo mismo para un interés del 2 %, y así sucesivamente hastallegar al 5 %. El programa debe mostrar una salida del tipo:

Cálculos realizados al 1%:

Dinero obtenido en el año número 1 = 2020Dinero obtenido en el año número 2 = 2040.2Dinero obtenido en el año número 3 = 2060.6

Cálculos realizados al 2%:

Dinero obtenido en el año número 1 = 2040Dinero obtenido en el año número 2 = 2080.8Dinero obtenido en el año número 3 = 2122.42

.......

Finalidad: Empezar a trabajar con bucles anidados. Dificultad Baja.

26. Cread un programa que ofrezca en pantalla la siguiente salida:

Guión de Prácticas. Fundamentos de Programación 47

Page 323: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS II. Estructuras de Control

1 2 3 4 5 62 3 4 5 63 4 5 64 5 65 66

Finalidad: Ejercitar los bucles anidados. Dificultad Baja.

27. Cread un programa que ofrezca en pantalla la siguiente salida:

1 2 3 4 5 62 3 4 5 6 73 4 5 6 7 84 5 6 7 8 95 6 7 8 9 106 7 8 9 10 11

Finalidad: Ejercitar los bucles anidados. Dificultad Media.

28. Modificad los dos ejercicios anteriores para que los valores inicial (1) y final (6) puedanser cualesquiera introducidos desde el teclado.

Finalidad: Ejercitar los bucles anidados. Dificultad Media.

29. Se dice que un número natural es feliz si cumple que si sumamos los cuadrados desus dígitos y seguimos el proceso con los resultados obtenidos, finalmente obtenemosuno (1) como resultado. Por ejemplo, el número 203 es un número feliz ya que 22 +02 + 32 = 13→ 12 + 32 = 10→ 12 + 02 = 1.Se dice que un número es feliz de grado k si se ha podido demostrar que es feliz enun máximo de k iteraciones. Se entiende que una iteración se produce cada vez quese elevan al cuadrado los dígitos del valor actual y se suman. En el ejemplo anterior,203 es un número feliz de grado 3 (además, es feliz de cualquier grado mayor o igualque 3)Escribir un programa que diga si un número natural n es feliz para un grado k dadode antemano. Tanto n como k son valores introducidos por el usuario.

Finalidad: Ejercitar los bucles anidados. Dificultad Media.

30. Escribir un programa que encuentre dos enteros n y m mayores que 1 que verifiquenlo siguiente:

m∑i=1

i2 = n2

Finalidad: Ejercitar los bucles anidados. Dificultad Media.

Guión de Prácticas. Fundamentos de Programación 48

Page 324: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS II. Estructuras de Control

Problemas de Ampliación

31. Cread un programa que acepte el número de un año e indique si es bisiesto o no.Un año es bisiesto si es múltiplo de cuatro, pero no de cien. Excepción a la reglaanterior son los múltiplos de cuatrocientos que siempre son bisiestos. Son bisiestos:1600,1996, 2000, 2004. No son bisiestos: 1700, 1800, 1900, 1998, 2002.

Dificultad Baja.

32. Realizar un programa para calcular los valores de la función:

f(x) =

√3x+ x2

1− x2

para valores de x enteros en el rango [-3..3].

Dificultad Baja.

33. Realizar un programa para calcular los valores de la función:

f(x, y) =

√x

y2 − 1

para los valores de (x, y) con x = −50,−48, . . . , 48, 50 y =−40,−39, . . . , 39, 40, es decir queremos mostrar en pantalla los valores de la funciónen los puntos

(−50, 40), (−50,−39), · · · (−50, 40), (−48, 40), (−48,−39), · · · (50, 40)

Dificultad Baja.

34. Diseñar un programa que presente una tabla de grados C a grados Fahrenheit (F=9/5C+32) desde los 0 grados a los 300, con incremento de 20 en 20 grados.

Dificultad Baja.

35. Diseñar un programa que lea caracteres desde la entrada y los muestre en pantalla,hasta que se pulsa el '.' y diga cuantos separadores se han leído (espacios enblanco ' ', tabuladores '\t' y caracteres de nueva línea '\n').

Dificultad Baja.

36. Realizar un programa para calcular la suma de los términos de la serie

1− 1/2 + 1/4− 1/6 + 1/8− 1/10 + ...− 1/(2n− 1) + 1/(2n)

para un valor n dado.

Dificultad Baja.

Guión de Prácticas. Fundamentos de Programación 49

Page 325: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS II. Estructuras de Control

37. Se decide informatizar el acta de un partido de baloncesto para saber qué equipoes el ganador del partido. El acta contiene una serie de anotaciones formadas poruna pareja de números cada una, con el dorsal del jugador y el número de puntosconseguidos teniendo en cuenta que la última anotación es un valor -1. Por ejemplo

1 2 4 1 4 1 2 3 6 2 3 2 5 2 5 1 1 3 -1

El programa deberá indicar si ha ganado el equipo 1 (con los dorsales 1, 2 y 3) o elequipo 2 (dorsales 4, 5 y 6) o han empatado.

Por ejemplo, con la entrada anterior, gana el equipo 1.

Dificultad Baja.

38. La Unión Europea ha decidido premiar al país que más toneladas de hortalizas exportea lo largo del año. Se dispone de un registro de transacciones comerciales en el queaparecen tres valores en cada apunte. El primer valor es el indicativo del país (E:España, F: Francia y A: Alemania), el segundo valor es un indicativo de la hortaliza quese ha vendido en una transacción (T: Tomate, P: Patata, E: Espinaca) y el tercer valorindica las toneladas que se han vendido en esa transacción. Diseñar un programa quelea desde el teclado este registro, el cual termina siempre al leer un país con indicativo’@’, y que diga qué país es el que más hortalizas exporta y las toneladas que exporta.

Por ejemplo, con la entrada

E T 10 E T 4 E P 1 E P 1 E E 2 F T 15 F T 6 F P 20 A E 40 @

el país que más vende es Francia con un total de 41 toneladas.

Dificultad Baja.

39. Diseñar un programa para jugar a adivinar un número. El juego tiene que dar pistasde si el número introducido por el jugador está por encima o por debajo del númerointroducido. Como reglas de parada considerad a) que haya acertado o b) se hayahartado y decida terminar (escoged cómo se quiere que se especifique esta opción)

Realizar el mismo ejercicio pero permitiendo jugar tantas veces como lo desee eljugador.

Dificultad Media.

40. Se dice que un número es triangular si se puede poner como la suma de los primerosm valores enteros, para algún valor de m. Por ejemplo, 6 es triangular ya que 6 =1 + 2 + 3. Una forma de obtener los números triangulares es a través de la fórmulan(n+ 1)

2∀n ∈ N. Se pide construir un programa que obtenga todos los números

triangulares que hay menores que un entero k introducido desde teclado, sin aplicarla fórmula anterior.

Dificultad Baja.

Guión de Prácticas. Fundamentos de Programación 50

Page 326: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS II. Estructuras de Control

41. Escribir un programa que lea una secuencia de números enteros en el rango de 0a 100 terminada en un número mayor que 100 o menor que 0 y encuentre la sub-secuencia de números ordenada, de menor a mayor, de mayor longitud. El programanos debe decir la posición donde comienza la subsecuencia y su longitud. Por ejemplo,ante la entrada siguiente:

23 25 7 40 45 45 73 73 71 4 9 101

el programa nos debe indicar que la mayor subsecuencia empieza en la posición 3 (enel 7) y tiene longitud 6 (termina en la segunda aparición del 73)

Dificultad Media.

42. El algoritmo de la multiplicación rusa es una forma distinta de calcular la multiplicaciónde dos números enteros n ∗ m. Para ello este algoritmo va multiplicando por 2 elmultiplicador m y dividiendo (sin decimales) por dos el multiplicando n hasta quen tome el valor 1 y suma todos aquellos multiplicadores cuyos multiplicandos seanimpares. Por ejemplo, para multiplicar 37 y 12 se harían las siguientes iteraciones

Iteración Multiplicando Multiplicador1 37 122 18 243 9 484 4 965 2 1926 1 384

Con lo que el resultado de multiplicar 37 y 12 sería la suma de los multi-plicadores correspondientes a los multiplicandos impares (en negrita), es decir37*12=12+48+384=444

Cread un programa para leer dos enteros n y m y calcule su producto utilizando estealgoritmo.

Dificultad Media.

43. Construid un programa para comprobar si las letras de una palabra se encuentrandentro de otro conjunto de palabras. Los datos se leen desde un fichero de la formasiguiente: el fichero contiene, en primer lugar un total de 3 letras que forman la palabraa buscar, por ejemplo f e o. Siempre habrá, exactamente, tres letras. A continuación,el fichero contiene el conjunto de palabras en el que vamos a buscar. El final de cadapalabra viene determinado por la aparición del carácter '@', y el final del fichero porel carácter '#'. La búsqueda tendrá las siguientes restricciones:

• Deben encontrarse las tres letras• Debe respetarse el orden de aparición. Es decir, si por ejemplo encontramos la'f' en la segunda palabra, la siguiente letra a buscar 'e' debe estar en unapalabra posterior a la segunda.

Guión de Prácticas. Fundamentos de Programación 51

Page 327: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS II. Estructuras de Control

• Una vez encontremos una letra en una palabra, ya no buscaremos más letras endicha palabra.

• No nos planteamos una búsqueda barajando todas las posibilidades, en el senti-do de que una vez encontrada una letra, no volveremos a buscarla de nuevo.

Entrada:

f e oh o l a @m o f e t a @ <- fc o f i a @c e r r o @ <- ep e r a @c o s a @ <- oh o y @#

En este caso, sí se encuentra.

Dificultad Media.

44. Un número perfecto es aquel que es igual a la suma de todos sus divisores positivosexcepto él mismo. El primer número perfecto es el 6 ya que sus divisores son 1, 2 y3 y 6=1+2+3. Escribir un programa que muestre el mayor número perfecto que seamenor a un número dado por el usuario.

Dificultad Media.

45. El número aúreo se conoce desde la Antigüedad griega y aparece en muchos te-mas de la geometría clásica. La forma más sencilla de definirlo es como el úniconúmero positivo φ que cumple que φ2 − φ = 1 y por consiguiente su valor es

φ =1 +√5

2. Se pueden construir aproximaciones al número aúreo mediante la fór-

mula an =fib(n+ 1)

fib(n)siendo fib(n) el término n-ésimo de la suceción de fibonacci

que se define como:

fib(0) = 0, fib(1) = 1 y fib(n) = fib(n− 2) + fib(n− 1) para n ≥ 2

Escribir un programa que calcule el menor valor de n que hace que la aproximacióndada por an difiera en menos de δ del número φ, sabiendo que n ≥ 1. La entradadel programa será el valor de δ y la salida el valor de n. Por ejemplo, para un valor deδ = 0,1 el valor de salida es n = 3

Dificultad Media.

Guión de Prácticas. Fundamentos de Programación 52

Page 328: Fundamentos de Programacion

Estructura condicional

Sesión 3

I Actividades a realizar en casa

Estructura condicional

Actividad: Resolución de problemas.

Resolved los siguientes problemas de la relación II (página 38). Por cada uno de ellos, habráque crear el correspondiente proyecto. Usad el tipo de proyecto _fp_2010

• Obligatorios:

2 (Subir ingresos a jubilados)3 (Ver si dos números se dividen)4 (Quién divide a quién)5 (Pasar de mayúscula a minúscula)6 (Pasar de mayúscula a minúscula y viceversa)7 (Medidas contra la crisis)

• Opcionales:

8 (Tarifa aérea)

Actividades de Ampliación

Hojear la páginahttp://catless.ncl.ac.uk/Risks

que publica periódicamente casos reales en los que un mal desarrollo del software ha tenidoimplicaciones importantes en la sociedad.

Guión de Prácticas. Fundamentos de Programación 53

Page 329: Fundamentos de Programacion

Estructura condicional

I Actividades a realizar en las aulas de ordenadoresEn esta sesión empezaremos a usar las estructuras condicionales. En primer lugar, copia-mos localmente el proyecto II_Media disponible en la carpeta ProblemasII de la unidadH: de la asignatura, que contiene la solución al ejercicio 1 de la relación de problemas II.Sobre este proyecto, probaremos las nuevas herramientas que vamos a ver a continuación.Es muy importante poner atención a la tabulación correcta de las sentencias, tal y como seindica en las transparencias. Recordad que una tabulación incorrecta supondrá bajar puntosen la primera prueba práctica que se realizará dentro de algunas semanas. Visual Studioofrece algunas herramientas para agilizar la correcta tabulación:

• VS tabula automáticamente el código si así se especifica en:

Herramientas -> Opciones -> Editor de texto-> C/C++ -> Tabulaciones -> Automático

El fichero de configuración .settings usado en las aulas de prácticas viene condicha opción seleccionada.

• De forma semi-automática, podemos seleccionar un bloque de texto con el ratón ypulsar Ctr-K,Ctr-F.

• De forma manual, podemos seleccionar un bloque de texto con el ratón y pulsar so-bre alguno de los iconos para disminuir o aumentar la sangría. Las teclas deacceso directo para estas operaciones son Shift-Tabulador y Tabulador res-pectivamente.

Visual Studio ofrece también un recurso bastante útil para la escritura de código. Cuandonuestros programas contienen muchas líneas de código, nos gustaría ocultar las partes quese han comprobado que funcionan correctamente. Para ello, basta seleccionar con el ratónun bloque de texto y seleccionar con la derecha

Esquematización -> Ocultar selección

De esta forma conseguimos que en el margen izquierdo del editor de texto aparezca unsímbolo +. Si pinchamos sobre él, se despliega mostrando el código y si pulsamos otravez, se oculta dicha selección. Hay que destacar que el código que estamos ocultandosigue siendo código del programa, por lo que se compilará y ejecutará como cualquier otrocódigo. Dicho de otra forma, por el hecho de ocultar de esta forma un trozo de código, no loestamos incluyendo como un comentario.

Guión de Prácticas. Fundamentos de Programación 54

Page 330: Fundamentos de Programacion

Depuración

Forzad los siguientes errores en tiempo de compilación, para habituarnos a los mensajesde error ofrecidos por el compilador:

• Suprimid los paréntesis de alguna de las expresiones lógicas de la sentencia if

• Quitad la llave abierta de la sentencia condicional (como únicamente hay una senten-cia dentro del if no es necesario poner las llaves, pero añadimos las llaves a cualquiercondicional para comprobar el error que se produce al eliminar una de ellas)

• Quitad la llave cerrada de la sentencia condicional

Depuración

" If debugging is the process of removing bugs, then programming must be the processof putting them in. Edsger Dijkstra (1930/2002) ".

Un depurador de programas (debugger en inglés) permite ir ejecutando un programa sen-tencia a sentencia (ejecución paso a paso). Además, nos permite ver en cualquier momentoel valor de las variables usadas por el programa. El uso de un depurador facilita la locali-zación de errores lógicos en nuestros programas, que de otra forma resultarían bastantedifíciles de localizar directamente en el código.

"Debuggers don’t remove bugs. They only show them in slow motion".

Cargad el proyecto II_Media. Una vez abierto lo compilamos para que se genere la in-formación de depuración. Dicha información se puede almacenar en distintos sitios. En laplantilla de _fp_2010 se ha seleccionado que sea sobre un fichero con extensión .pdb.Nota. Para más información, id al Explorador de Soluciones, pinchad sobre el proyecto conel click derecho y seleccionad ayuda con F1 sobre:

Proyecto -> Propiedades -> Propiedades de configuración-> C/C++ -> General -> Formato de la información de depuración

Si en la anterior opción se eligiese Deshabilitado, no se generaría ninguna informaciónde depuración.La idea básica en la depuración es ir ejecutando el código línea a línea para ver posiblesfallos del programa. Para eso, debemos dar los siguientes pasos:

1. Establecer una línea del programa en la que queremos que se pare la ejecución. Loharemos introduciendo un punto de ruptura o (breakpoint) en dicha línea. Si sospe-chamos dónde puede estar el error, situaremos el punto de ruptura en dicha línea. Encaso contrario, lo situaremos al principio del programa.

Guión de Prácticas. Fundamentos de Programación 55

Page 331: Fundamentos de Programacion

Depuración

Para establecer un punto de ruptura podemos mover el ratón en la parte más a laizquierda de una línea de código, y pulsar el botón izquierdo en esa posición. La ins-trucción correspondiente queda marcada en rojo. Si en esa línea ya había un punto deruptura, entonces será eliminado. También podemos colocar el cursor sobre la instruc-ción y pulsar F9 . Para eliminar un punto de ruptura, se realiza la misma operaciónque para incluirlo, sobre la instrucción que actualmente lo tiene.

Colocad ahora un punto de ruptura sobre la linea que contiene la primera sentenciacondicional if.

2. A continuación le pediremos al depurador que empiece a ejecutar nuestro programapulsando como siempre F5 . Esto provocará que se ejecuten todas las sentenciasque hay justo antes del punto de ruptura. Llegado a este punto, la ejecución se pausay se muestra en amarillo aquella línea que se va a ejecutar a continuación (en estecaso, la que contiene el punto de interrupción)

3. Una vez que tenemos la línea amarilla sobre una instrucción, para proceder a su eje-cución, pulsamos F10 . Sólo se ejecuta una sentencia (línea) y se marca en amarillola siguiente línea, en espera a que volvamos a pulsar F10. Desde la barra de herra-

mientas, podemos pinchar sobre el icono

Ejecutad varias líneas de programa pulsando F10. Cuando se ejecute una sentenciacin, habrá que irse a la ventana de la consola e introducir el valor pedido, y una vezhecho, volver a Visual Studio para proseguir la ejecución con F10.

4. Para proseguir la ejecución del programa sin ir paso a paso, basta con pulsar de nuevoF5. Para detener la ejecución (y por tanto también la depuración), seleccionaríamos

Shift-F5 , o bien el cuadrado de la barra de herramientas .

Importante. No debe abortarse la ejecución del programa, cerrando la ventana de laconsola (a través de Ctr-C o haciendo click sobre la aspa de la ventana). Esta formade parar la ejecución es brusca y el compilador podría no liberar adecuadamentealgunos recursos utilizados del sistema operativo.

5. Cuando lleguemos a la última línea del programa, la que contiene la llave cerradadel main, al pulsar F10, se abrirá una pestaña nueva sobre un fichero denominadocrt0.c. Este fichero es utilizado internamente por Visual Studio como punto de en-trada de la aplicación. Para evitar que aparezca este fichero, cuando lleguemos a laúltima línea del programa, pulsaremos F5 en vez de F10.

Guión de Prácticas. Fundamentos de Programación 56

Page 332: Fundamentos de Programacion

Depuración

Otros recursos:

Este comando, accesible también con Ctr-F10 , ejecuta todas las instrucciones hastadonde se encuentre actualmente el cursor de la ventana de edición. Al llegar a él, semarca en amarillo dicha línea y se queda en espera a que iniciemos una ejecuciónpaso a paso, o a que prosigamos la ejecución ininterrumpida con F5.

Se utiliza para saltar determinadas sentencias que no queremos revisar.

• Si pulsamos Ctr-F5 en vez de F5, el programa se ejecutará sin procesar la informa-ción de depuración, por lo que, por ejemplo, no se parará en ningún punto de interrup-ción. Además, al ejecutar el programa de este forma, también saldrá un mensaje alfinal con la leyenda Pulse cualquier tecla para continuar. Este mensaje se añadirá alque nosotros ya habíamos puesto con system("pause").

• Podemos iniciar la ejecución paso a paso desde el principio, sin poner ningún pun-to de interrupción, pulsando directamente F10. Esto hará que la primera instruccióndestacada en amarillo sea la correspondiente a main.

Los depuradores de programas permiten consultar los valores que tienen en cada momentoalgunas de las variables que se utilizan en el programa, para así intentar descubrir dóndepuede estar el posible error lógico del programa. EN PRIMER LUGAR, debemos iniciar ladepuración introduciendo un punto de interrupción y pulsando F5 (o empezando desde elprincipio con F10). Automáticamente aparecen las ventanas siguientes:

• Automático: Contiene una lista de las variables involucradas en la sentencia que seva a ejecutar, así como las involucradas en la sentencia anterior

• Locales: Contiene una lista de las variables definidas en el bloque actual. Por ahora,las que aparecen son las que están definidas dentro de main.

• Inspección: Contiene variables que explícitamente ha incluido el programador. Yaveremos en temas posteriores en qué situaciones puede resultar útil.

Los valores mostrados para cada variable en las anteriores ventanas, son el valor actualpara cada una de ellas. Por valor actual entendemos el valor que tiene dicha variable, antesde que se ejecute la línea marcada en amarillo. El valor de cada variable se irá actualizandode forma automática conforme el programa siga su ejecución.Además, si durante la ejecución interrumpida situamos el cursor sobre alguna variable delcódigo escrito .cpp, aparecerá automáticamente una leyenda informativa con el valor ac-tual de dicha variable. También podemos seleccionar una expresión con el ratón (comocualquier selección de texto) y se mostrará la evaluación de dicha expresión.

Guión de Prácticas. Fundamentos de Programación 57

Page 333: Fundamentos de Programacion

Depuración

Observación final: El depurador ayuda a encontrar errores al permitir ejecutar las sentenciaspaso a paso y así comprobar por donde va el flujo de control y ver cómo van cambiando lasvariables. En cualquier caso, nunca nos cansaremos de repetir que el mejor programador esel que piensa la solución en papel, antes de escribir una sola línea de código en el entornode programación.

"When your code does not behave as expected, do not use the debugger, think".

Guión de Prácticas. Fundamentos de Programación 58

Page 334: Fundamentos de Programacion

Estructura Repetitiva. Bucles while

Sesión 4

Estructura Repetitiva. Bucles while

I Actividades a realizar en casa

Actividad: Resolución de problemas.

Resolved los siguientes problemas de la relación II. Por cada uno de ellos, habrá que crearel correspondiente proyecto. Usad el tipo de proyecto _fp_2010Importante: En estos ejercicio se permiten mezclar E/S con cómputos dentro del mismobucle (ya que todavía no se conocen herramientas para no hacerlo)

• Obligatorios:10 (Divisores de un número)11 (El mínimo de varios reales leídos desde teclado)12 (Reinvertir capital e interés un número de años)13 (Reinvertir capital e interés hasta doblar cantidad inicial)20 y 21 (Progresión geométrica)

• Opcionales:14 (Filtro entrada mayúscula)16 (Factorial y potencia)17 (Combinatorio)18 (While versus do while)

Guión de Prácticas. Fundamentos de Programación 59

Page 335: Fundamentos de Programacion

Redireccionando las entradas de cin

I Actividades a realizar en las aulas de ordenadores

Redireccionando las entradas de cin

Cada vez que se ejecuta cin, se lee un dato desde el periférico por defecto. Nosotros lohemos hecho desde el teclado, introduciendo un dato y a continuación un ENTER. Otra for-ma alternativa es introducir un dato y luego un separador (uno o varios espacios en blancoo un tabulador). Para comprobarlo, copiad localmente la carpeta ProblemasII\II_cinque se encuentra en el directorio de la asignatura. Observad el código del programa y eje-cutadlo desde Visual Studio. Para introducir los datos pedidos (un entero y dos caracteres)separadlos por espacios en blanco. Pulsad ENTER al final (una sola vez).Los datos anteriores se pueden poner dentro de un fichero de texto. Dentro del fichero, cadadato hay que separarlo por uno o varios espacios en blanco o tabuladores. Para poder leerlos datos del fichero, basta con ejecutar el programa .exe desde una consola del sistema yespecificar que la entrada de datos será desde un fichero a través del símbolo de redireccio-namiento < (no ha de confundirse con el token << que aparecía en una instrucción cout deC++) Hay que destacar que este redireccionamiento de la entrada lo estamos haciendo enla llamada al ejecutable desde la consola del sistema operativo2. Para probarlo, seleccionadel fichero II_cin_datos_entrada.txt que se encuentra dentro de la carpeta II_ciny copiadlo dentro de Mis Documentos. Copiad también dentro de Mis Documentos, elfichero ejecutable II_cin.exe que se encuentra en la carpeta II_cin\DebugAbrimos MisDocumentos desde el sistema operativo y seleccionamos con el click derechadel ratón "Abrir Símbolo del Sistema". Introducimos la instrucción siguiente (verFigura 6):

II_cin.exe < II_cin_datos_entrada.txt

Ahora, cada vez que se ejecute una instrucción cin en el programa, se leerá un valor delos presentes en el fichero de texto.Visual Studio también permite redireccionar la entrada de datos desde el propio entorno.Esto resulta muy útil cuando se desea leer datos de un fichero y a la misma vez depurar elprograma (introducir puntos de interrupción, ejecución paso a paso, evaluación de variables,etc). Para hacerlo, seleccionad

Proyecto -> Propiedades de ....Propiedades de Configuración -> Depuración

Argumentos del comando -> Editar ->

2También pueden leerse datos de un fichero desde dentro del propio código fuente del programa, pero estose verá en el segundo cuatrimestre

Guión de Prácticas. Fundamentos de Programación 60

Page 336: Fundamentos de Programacion

Redireccionando las entradas de cin

Figura 6: Redirección de la entrada desde la consola

En el cuadro de texto que aparece al seleccionar Editar, introduciremos el símbolo <seguido del nombre del fichero de texto que contiene los datos(ver Figura 7). Con el anteriorejemplo sería:

< II_cin_datos_entrada.txt

Por defecto, el entorno busca el fichero de entrada de datos en la misma carpeta que elproyecto. Si se quiere, puede indicarse otra carpeta distinta, a través de la opción siguiente:

Proyecto/PropiedadesPropiedades de Configuración/Depuración

Directorio de trabajo/

Cuando ejecutemos el programa, cada ejecución de cin leerá un dato desde el fichero indi-cado, saltándose previamente todos los espacios en blanco y tabuladores que hubiese pre-viamente. Cuando llegue al final del fichero, la lectura de un valor cargaría el carácter fin defichero. Cuando llega al final del programa y se ejecuta la instrucción system("pause")el programa se detiene y lee una tecla del dispositivo por defecto, que en este caso es elfichero. Lee la marca de fin de fichero como tecla válida y por tanto no hace la pausa queestábamos esperando. Para solucionarlo, basta con que introduzcamos un punto de rupturaal final del código fuente de nuestro programa.Nota. En nuestra casa, o bien instalamos un programa que permita abrir una consolaen el directorio actual, como por ejemplo Open Command Prompt Shell Extension dispo-nible en http://code.kliu.org/cmdopen/ o bien abrimos un símbolo del sistema(Inicio->Ejecutar->cmd) y vamos cambiando de directorio con la orden cdNota. CodeBlocks también permite, en teoría, la ejecución paso a paso cuando los datos seleen desde un fichero (desde la opción Project-Set program’s arguments). Sin embargo, enla última versión (10.5) esta opción no funciona correctamente bajo Windows.

Guión de Prácticas. Fundamentos de Programación 61

Page 337: Fundamentos de Programacion

Redireccionando las entradas de cin

Figura 7: Redirección de la entrada desde el entorno

Guión de Prácticas. Fundamentos de Programación 62

Page 338: Fundamentos de Programacion

Redireccionando las entradas de cin

Ejercicio. Construid un programa para que vaya leyendo números desde la entrada por de-fecto y los vaya sumando, hasta que se lea el valor -1. Imprimid el resultado. Realizad laentrada desde un fichero externo que contendrá la serie de valores. Utilizad las herramien-tas de depuración vistas en la sesión anterior para inspeccionar el valor de las variablesusadas en cada iteración del bucle.

Guión de Prácticas. Fundamentos de Programación 63

Page 339: Fundamentos de Programacion

Estructura Repetitiva: bucles for y bucles anidados

Sesión 5

Estructura Repetitiva: bucles for y bucles anidados

I Actividades a realizar en casa

Actividad: Resolución de problemas.

Resolved los siguientes problemas de la relación II. Por cada uno de ellos, habrá que crearel correspondiente proyecto. Usad el tipo de proyecto _fp_2010.Importante: En estos ejercicio se permiten mezclar E/S con cómputos dentro del mismobucle (ya que todavía no se conocen herramientas para no hacerlo)Durante la primera media hora de la clase, el alumno debe realizar las actividadesindicadas en "Actividades a realizar en las aulas de ordenadores". Durante la hora ymedia posterior, los alumnos saldrán a explicar las soluciones de los ejercicios.

• Obligatorios:

22 (Divisores e interés usando un for)24 (Método RLE)15 (Número narcisista)25 (Interés con anidamiento)26, 27, 28 (Pintar pirámide y cuadrado)

• Opcionales:

21 (Progresión geométrica usando un for)23 (Serie)30 (Encontrar enteros)

Guión de Prácticas. Fundamentos de Programación 64

Page 340: Fundamentos de Programacion

Estructura Repetitiva: bucles for y bucles anidados

I Actividades a realizar en las aulas de ordenadoresEntrad en la web del departamento y pinchad sobre el último icono que aparece de accesoa la plataforma GAP. Esta es la plataforma que se usará para subir el fichero cpp el día delexamen. Una vez accedamos a ella, estaremos automáticamente dados de alta. Si se quie-re, se puede cambiar la contraseña de acceso para que sea distinta a la del departamento,aunque no se recomienda que se haga.

Ejercicio. Objetivo: Enfatizar la importancia del correcto diseño de una estructura condicionalanidada en un bucleCopiad la carpeta ProblemasII\II_Divisores que se encuentra en el directorio de laasignatura. Cambiad el bloque de código

while (divisor <= tope){if (tope % divisor == 0)

cout << divisor << " es un divisor de " << tope << endl;divisor++;

}

por el siguiente:

while (divisor <= tope){if (tope % divisor == 0)

cout << divisor << " es un divisor de " << tope << endl;else

divisor++;}

¿Qué error se produce?Moraleja: Mucho cuidado con las sentencias condicionales dentro de los bucles: debemosasegurarnos de cambiar apropiadamente las variables involucradas en la condición del bu-cle, para que, en algún momento, dicha condición sea false

Como programadores noveles en C++, podemos confundir el operador = con el operador==. El resultado puede ser un error lógico en nuestro programa, aunque afortunadamente,puede ser detectado en tiempo de compilación. Vamos a familiarizarnos con el aviso delcompilador cuando usamos una sentencia de asignación en una condición. Sobre el ejemplode los divisores, cambiad la línea en la que aparece la sentencia condicional

if (tope % divisor == 0){....

por las siguientes

Guión de Prácticas. Fundamentos de Programación 65

Page 341: Fundamentos de Programacion

Estructura Repetitiva: bucles for y bucles anidados

modulo = tope % divisor

if (modulo = 0){ // <- Usamos = en vez de ==....

dónde modulo es una variable entera que habrá que declarar previamente. Compilad yobservad el aviso que nos da Visual Studio. ¿Qué error lógico se produce y por qué? Paracontestar esta pregunta hay que repasar las transparencias de teoría en las que se dice queuna asignación es una expresión y se habla sobre la dualidad entre el tipo bool y el tipoint

Guión de Prácticas. Fundamentos de Programación 66

Page 342: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS III. Funciones y Clases

RELACIÓN DE PROBLEMAS III. Funciones y Clases

Problemas Básicos

Problemas sobre funciones

1. Cread una función que calcule el máximo entre tres double. La cabecera de la fun-ción será la siguiente:

double Max(double un_valor, double otro_valor, double el_tercero)

Construid un programa principal que llame a dicha función con los parámetros actualesque se quiera.

Finalidad: Familiarizarnos con la definición de funciones, el paso de parámetros y elámbito de las variables. Dificultad Baja.

2. Cread una función para calcular la suma de una progresión geométrica, tal y comose vio en el ejercicio 21 de la relación de problemas II. Analizad cuáles deben ser losparámetros de dicha función.

Finalidad: Diseño de una función sencilla. Dificultad Baja.

3. En el ejercicio 8 de la relación de problemas II (sobre los descuentos a aplicar a unatarifa aérea), se repetía en varias ocasiones un código muy parecido, a saber:

rebaja = rebaja + tarifa_con_km_adicionales *DESCUENTO_CLIENTE_PREVIO/100.0;

rebaja = rebaja + tarifa_con_km_adicionales *DESCUENTO_TRAYECTO_MEDIO/100.0;

...........

Construid la función apropiada para que no se repita código y re-escribid la soluciónllamando a dicha función en todos los sitios donde sea necesario.

Finalidad: Diseño de una función sencilla. Dificultad Baja.

4. Se pide definir las siguientes funciones y cread un programa principal de ejemplo quelas llame:

a) EsMinuscula comprueba si un carácter pasado como parámetro es una minús-cula. A dicho parámetro, llamadlo una_letra.

Guión de Prácticas. Fundamentos de Programación 67

Page 343: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS III. Funciones y Clases

b) Convierte_a_Mayuscula comprueba si un carácter pasado como parámetroes minúscula (para ello, debe llamar a la función anterior), en cuyo caso lo trans-forma a mayúscula. Si el carácter no es minúscula debe dejar la letra igual. Adicho parámetro, llamadlo caracter.Esta función hace lo mismo que la función tolower de la biblioteca cctype

Observad que el parámetro una_letra de la función EsMinuscula podría llamarseigual que el parámetro caracter de la otra función. Esto es porque están en ámbitosdistintos y para el compilador son dos variables distintas. Haced el cambio y compro-barlo.

Finalidad: Entender el ámbito de los parámetros de las funciones, así como las llama-das entre funciones. Dificultad Baja.

5. En el ejercicio 5 de la relación de problemas I (página 14) se vio cómo obtener elvalor de ordenada asignado por la función gaussiana, sabiendo el valor de abscisa x.Recordemos que esta función matemática dependía de dos parámetros µ (esperanza)y σ (desviación), y venía definida por:

gaussiana(x) =1

σ√2π

e

−12

(x− µσ

)2

Cread una función para calcular el valor de la función gaussiana en un punto arbitrarioleído desde teclado. Cread un programa principal que llame a la función.

Finalidad: Entender la separación de E/S con Cómputos en el contexto de las funcio-nes. Dificultad Baja.

6. Vamos a añadir una función al ejercicio 4 de esta relación de problemas. Se pideimplementar la función Transforma, a la que se le pase como parámetro un char yhaga lo siguiente:

• si el argumento es una letra en mayúscula, devuelve su correspondiente letra enminúscula,• si el argumento es una letra en minúscula, devuelve su correspondiente letra en

mayúscula,• si el argumento no es ni una letra mayúscula, ni una letra mayúscula, devuelve el

carácter pasado como argumento.

Observad que la constante de amplitud

const int AMPLITUD = 'a'-'A';

es necesaria declararla como constante local en ambas funciones. Para no repetireste código, ¿qué podemos hacer?

Finalidad: Entender cómo se llaman las funciones entre sí. Dificultad Baja.

Guión de Prácticas. Fundamentos de Programación 68

Page 344: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS III. Funciones y Clases

Problemas sobre clases

7. Se pide crear una clase Conjunto_3_Valores que represente un conjunto de 3valores de tipo double, sobre los que se quiere realizar las operaciones de calcularel máximo y la media aritmética. Para ello, haced lo siguiente:

a) Definid en primer lugar la clase con tres datos miembro públicos llamados uno,dos y tres. A esta primera versión de la clase, dadle el nombreConjunto_3_Valores_vs1

Añadid un método público Max. Este método tendrá la siguiente cabecera:

double Max()

Observad que el método Max actúa sobre los datos de la clase (uno, dos ytres) por lo que no tiene parámetros. Observad la diferencia con la cabecera delejercicio 1 en el que Max era una función que no estaba dentro de ninguna clase.

b) Añadid ahora un método para calcular la media aritmética de los tres valores.

c) Cread un main que llame a los métodos anteriores.Comprobad que podemos modificar directamente los datos miembro públicosdesde el main, lo cual no es muy recomendable como ya se ha visto en clase deteoría. Para resolver este problema, hacemos lo siguiente:

d) Copiad el código de la clase anterior y copiadlo dentro de una nueva clase llama-daConjunto_3_Valores_vs2

En esta nueva versión, declarad los datos miembro como private, en vez depublic. Comprobad que ya no podemos acceder a ellos desde el main, por loque necesitamos asignarles un valor de otra forma. Para ello, haced lo siguiente:

I) Añadid un constructor a la clase Conjunto_3_Valores_vs2. En dichoconstructor, pasaremos los tres valores que habrá que asignárselos a losdatos miembro (usad la lista de inicialización, que va precedida de dos pun-tos).Cread el objeto correspondiente desde el main (el compilador nos obligará apasar los tres valores en el constructor)

II) Añadid tres métodos (GetPrimero(), GetSegundo(), GetTercero())que devuelvan los correspondientes datos miembro, para que así pueda con-sultarse su valor desde el main.

e) Supongamos que creamos un objeto con los valores 2, 5, 7. Si ahora quisié-ramos cambiar de conjunto de datos y trabajar con 3, 9, 1, por ejemplo, ten-dríamos que crear otro objeto distinto. Esto es completamente lícito. En cualquier

Guión de Prácticas. Fundamentos de Programación 69

Page 345: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS III. Funciones y Clases

caso, dependiendo del problema que estemos abordando, podríamos estar in-teresados en permitir cambiar los datos del objeto (su estado) y así no tener quecrear otro objeto distinto. Para ello, debemos proporcionar dicha funcionalidad ala clase. Lo hacemos de tres formas alternativas:

• Creamos la claseConjunto_3_Valores_vs3

que contendrá el mismo código que Conjunto_3_Valores_vs2 y le aña-dimos un método SetValores que cambie los tres valores a la vez (co-mo ha cambiado el nombre de la clase, habrá que cambiar el nombre delconstructor). Cread un objeto de esta clase desde el main y llamad a susmétodos.En esta solución, asignamos (dentro del constructor) un primer valor a cadauno de los tres datos miembro y posteriormente permitimos su modificacióna través del método SetValores. Sólo permitimos la modificación conjuntade los tres datos miembro a la misma vez.• Alternativamente, Creamos la clase

Conjunto_3_Valores_vs4

que contendrá el mismo código que Conjunto_3_Valores_vs3, salvo quesuprimimos el constructor de la clase. Modificad convenientemente el main.En esta solución, los tres datos miembro sólo los podemos asignar con elmétodo nuevo SetValores. Sólo permitimos la modificación conjunta delos tres datos miembro a la misma vez.• Alternativamente, creamos la clase

Conjunto_3_Valores_vs5

que contendrá el mismo código que Conjunto_3_Valores_vs4, perosuprimimos el método SetValores, y le añadimos tres métodos nuevosSetPrimero, SetSegundo, SetTercero, para que cambien cada uno delos valores de forma independiente. Cread un objeto de esta clase desde elmain y llamad a sus métodos.En esta solución, los tres datos miembro sólo los podemos asignar a travésde un método específico para cada uno de ellos.

Observad la flexibilidad que me ofrece el concepto de clase. El programador de-cide cómo quiere que se acceda a los datos miembro: prohibiendo cambiar losdatos miembro una vez que se ha construido el objeto (versión 2) o permitiéndolo,bien todos a la vez (versiones 3 y 4) o uno a uno (versión 5).

Finalidad: Trabajar con los conceptos básicos de clases. Dificultad Baja.

A partir de ahora, todos los ejercicios deben resolverse utilizandoúnicamente datos miembro privados.

Guión de Prácticas. Fundamentos de Programación 70

Page 346: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS III. Funciones y Clases

8. Cread una clase llamada ParejaEnteros que represente una pareja de enteroscualesquiera. Añadid un constructor y los métodos que se estimen oportunos paraasignarles valores a los enteros y para obtener el valor que éstos tengan. Las ope-raciones que queremos realizar sobre una pareja son calcular el mayor, el menor,comprobar si se dividen, ver quien es el dividendo y quien el divisor, intercambiarlos ycalcular el máximo común divisor. Cread un main que llame a dichos métodos, paracomprobar que están bien implementados.

¿Le añadiría a la clase ParejaEnteros un método para calcular el factorial de unnúmero? ¿Por qué?

Finalidad: Diseñar la interfaz de una clase. Dificultad Baja.

9. Sobre el ejercicio 8 de esta relación de problemas se pide crear un programa principalmás completo de la siguiente forma. En el main se leerán dos enteros y a continuaciónse ofrecerá al usuario un menú con las opciones para realizar cualquiera de las opera-ciones definidas en la clase ParejaEnteros. También se ofrecerá la posibilidad deimprimir el valor de cada uno de los dos enteros. Una vez ejecutada la operación, sevolverá a mostrar el mismo menú, hasta que el usuario decida salir (pulsando la tecla'X', por ejemplo).

Finalidad: Organizar un menú de opciones que se va repitiendo mientras el usuario nodecida salir. Dificultad Media.

10. Definid una clase para representar una progresión geométrica, tal y como se definióen el ejercicio 21 de la relación de problemas II.

a) Pensad cual debería ser el constructor de la clase y los métodos básicos que laclase debería tener.

b) Añadid un método llamado SumaHastaInfinito para que calcule la suma da-da por:

i=∞∑i=1

ai =a1

1− r

siempre que el valor absoluto de la razón sea menor o igual que 1.

c) Añadid un método llamado SumaHasta para que sume los k primeros elementosde la progresión. Para implementar el método SumaHasta, usad el mismo algo-ritmo (con un bucle for) que se vio como solución del ejercicio 21 de la relaciónde problemas II.Cread un programa principal que construya la progresión con los valores a1 =3,5 y r = 4,1 y calcule la suma hasta k = 30.

d) Cambiemos ahora la implementación del método SumaHasta. Para ello, en vezde usar un bucle for aplicamos la siguiente fórmula que nos da la sumatoria

Guión de Prácticas. Fundamentos de Programación 71

Page 347: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS III. Funciones y Clases

aplicando únicamente cinco operaciones:

i=k∑i=1

a1ri = a1

rk − 1

r − 1

Es muy importante remarcar que el programa main no cambia nada. Hemoscambiado la implementación del método SumaHasta y lo hemos podido hacersin cambiar el main, ya que éste no tenía acceso al código que hay dentro delmétodo. Esto es ocultación de información tal y como se describió en las clasesde teoría.Nota. La potenciación (en nuestro ejemplo rk) es una operación costosa, porlo que hasta podría ser más lenta la versión nueva que la antigua usando unbucle for. Probad distintos valores para ver si hay diferencias significativas. Encualquier caso, lo importante es que mientras no cambiemos la cabecera delmétodo SumaHasta, podemos cambiar su implementación sin tener que cambiarni una línea de código del main.

e) Añadid ahora otro método MultiplicaHasta para que multiplique los k prime-ros elementos de la progresión, aplicando la fórmula:

i=k∏i=1

a1ri =

√(a1ak)k

Finalidad: Enfatizar la importancia de la ocultación de información. Dificultad Baja.

11. Se quiere construir una clase DepositoSimulacion para simular préstamos, ofre-ciendo la funcionalidad descrita en los ejercicios 12 (reinvierte capital e interés un nú-mero de años) y 13 (reinvierte capital e interés hasta obtener el doble de la cantidadinicial) de la relación de problemas II (página 44). Por tanto, la clase debe proporcionar,para un capital y unos intereses dados, métodos para:

• calcular el capital que se obtendrá al cabo de un número de años,

• calcular el número de años que deben pasar hasta obtener el doble de la cantidadinicial.

A la hora de diseñar la clase, tendremos que analizar cuestiones como:

a) Si queremos modificar el capital y el interés una vez creado el objeto,

b) Si queremos poder modificarlos de forma independiente,

c) Si hay alguna restricción a la hora de asignar un valor al capital e interés,

d) Si es mejor un método para calcular el número de años hasta obtener el doble dela cantidad inicial, o por el contrario es mejor un método para calcular el númerode años hasta obtener una cantidad específica.

Guión de Prácticas. Fundamentos de Programación 72

Page 348: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS III. Funciones y Clases

Finalidad: Diseñar la interfaz de una clase. Dificultad Baja.

12. Se quiere construir una clase para realizar la funcionalidad descrita en el ejercicio 10de la relación de problemas I sobre la nómina del fabricante y diseñador (página 16).La clase debe proporcionar, al menos, los métodos SalarioNetoDisenador ySalarioNetoFabricante. El criterio del cálculo del salario es el mismo (el dise-ñador cobre el doble de cada fabricante) pero además, ahora se le va a aplicar unaretención fiscal para el cómputo de los salarios netos. Dicha retención será la mismatanto para el fabricante como para el diseñador.

Analizad las siguientes posibilidades y elegid la que crea más adecuada, justificándo-lo:

a) Creamos un dato miembro para almacenar el valor de retención fiscal y pasamossu valor en el constructor.

b) Creamos un dato miembro para almacenar su valor y además proporcionamosun método para su modificación.

Finalidad: Trabajar con datos miembro constantes. Dificultad Baja.

13. Una empresa quiere gestionar las nóminas de sus empleados. El cómputo de la nó-mina se realiza en base a los siguientes criterios:

a) Hay cuatro tipos de categorías laborales: Operario, Base, Administrativo y Direc-tivo.

b) Se parte de un salario base que depende de la antigüedad del trabajador y desu categoría laboral. Para la categoría Operario, el salario base es de 900 euros,1100 el puesto Base, 1200 los Administrativos y 2000 los Directivos. Dicho salariobase se incrementa con un tanto por ciento igual al número de años trabajados.

c) Los trabajadores tienen complementos en su nómina por el número de horasextraordinarias trabajadas. La hora se paga distinta según la categoría: 16 eurospor hora para los operarios, 23 para el puesto Base, 25 los Administrativos y 30los Directivos. Además, al complemento que sale al computar el número de horasextraordinarias, se le aplica una subida con un tanto por ciento igual al númerode años trabajados.

Se pide diseñar la interfaz de una clase (también hay que incluir los datos miembroprivados) para poder trabajar con esta información. No se pide implementar la clase,únicamente determinar la interfaz.

Finalidad: Diseñar la interfaz de una clase. Dificultad Media.

14. Transformad la solución del ejercicio 9 de esta relación de problemas para que laresponsabilidad de la lectura de la opción introducida por el usuario recaiga en unaclase a la que llamaremos Menu.

Finalidad: Ver una clase específica que gestione la entrada de datos. Dificultad Media.

Guión de Prácticas. Fundamentos de Programación 73

Page 349: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS III. Funciones y Clases

15. Cread una clase para representar fracciones. El numerador y denominador serán en-teros y debe proporcionar un método para normalizar la fracción, es decir, encontrarla fracción irreducible que sea equivalente. Para ello, tendrá que dividir el numeradory denominador por su máximo común divisor.

Finalidad: Diseñar la interfaz de una clase. Dificultad Media.

16. En C++, los tipos de datos simples como int, char, double, etc, no son clases.Por tanto, si declaramos una variable real en la forma double real, para calcular elseno de real, llamamos a una función en la forma

double real, resultado;real = 6.5;resultado = sin(real);

Estamos interesados en construir una clase llamada MiReal para trabajar con realesal estilo de las clases. Por tanto, para calcular el seno de 6.5, deberíamos hacer algocomo lo siguiente:

MiReal real(6.5);double resultado;resultado = real.Seno();

En esta caso, Seno es un método de la clase MiReal que devuelve un tipo double.Construid dicha clase, proporcionando los siguientes métodos:

a) Valor. Este método debe devolver el valor del real (6.5 en el ejemplo anterior)

b) Seno. Para definirlo, llamad a la propia función sin de la biblioteca cmath. Debedevolver un double

c) ValorAbsoluto. Devolverá un tipo double que contendrá el valor absoluto delreal. No pueden utilizarse las funciones de cmath.

Cread un programa principal que llame a dichos métodos.

Observad que sería interesante que nuestro código fuese el siguiente:

MiReal real(6.5);MiReal resultado;resultado = real.Seno();resultado = resultado + real;

Es decir, que el método Seno devolviese un tipo MiReal en vez de un tipo double.Aunque esto es posible en C++, por ahora no disponemos de las herramientas ne-cesarias para hacerlo. Por ejemplo, para hacer la asignación entre variables de tipoMiReal se necesita el concepto de sobrecarga del operador de asignación y para

Guión de Prácticas. Fundamentos de Programación 74

Page 350: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS III. Funciones y Clases

realizar la suma de dos variables de tipo MiReal se necesita sobrecargar el operador+ (se verá en el segundo cuatrimestre).

Nota. Este tipo de clases (MiEntero, MiReal, etc) son proporcionadas por Java deforma standard. En otros lenguajes como SmallTalk o plataformas como .NET (conlenguajes como Visual Basic, C#) no existe la diferencia entre tipos básicos (comoint, double, etc) y todo son clases, siguiendo una filosofía orientada a objetos pura.

Finalidad: Entender las clases que actúan como envolventes (wrappers) de los tiposbásicos. Dificultad Baja.

Guión de Prácticas. Fundamentos de Programación 75

Page 351: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS III. Funciones y Clases

Problemas de Ampliación

17. Definid funciones aisladas para implementar las soluciones a los siguientes ejerciciosde la relación de problemas II: 16 (factorial y combinatorio), 23 (serie), 15 (narcisis-ta), 29 (feliz).

Dificultad Baja.

18. Construid la clase MiEntero que será utilizada en la forma siguiente:

MiEntero entero(6);int entero;resultado = entero.Factorial();

Debe proporcionar los siguientes métodos:

a) Valor. Este método debe devolver el valor del entero (un tipo int).

b) Factorial. Usad la solución del ejercicio 16 de la relación de problemas II(página 44).

c) EsNarcisista. Usad la solución del ejercicio 15 de la relación de problemas II(página 44)

Cread un programa principal que llame a dichos métodos.

19. Construid la clase MiCaracter que será utilizada en la forma siguiente:

MiCaracter caracter('a');char resultado;resultado = entero.GetMayuscula();

Debe proporcionar los siguientes métodos:

a) Valor. Este método debe devolver el valor del carácter.

b) EsMinuscula. Devuelve un bool.

c) EsMayuscula. Devuelve un bool.

d) EsLetra. Devuelve un bool.

e) GetMayuscula. Devuelve un char correspondiente al carácter convertido a ma-yúscula. Si el carácter no es minúscula, devuelve el mismo valor del char.

f ) GetMinuscula. El recíproco del anterior.

Cread un programa principal que llame a dichos métodos.

Guión de Prácticas. Fundamentos de Programación 76

Page 352: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS III. Funciones y Clases

20. La sonda Mars Climate Orbiter fue lanzada por la NASA en 1998 y llegó a Marteel 23 de septiembre de 1999. Lamentablemente se estrelló contra el planeta ya quese acercó demasiado. El error principal fue que los equipos que desarrollaron losdistintos módulos de la sonda usaron sistemas de medida distintos (el anglosajón y elmétrico). Cuando un componente software mandaba unos datos en millas (o libras),otro componente software los interpretaba como si fuesen kilómetros (o Newtons). Elproblema se habría arreglado si todos hubiesen acordado usar el mismo sistema. Encualquier caso, cada equipo se encuentra más a gusto trabajando en su propio sistemade medida. Por tanto, la solución podría haber pasado por que todos utilizasen unamisma clase para representar distancias (idem para fuerzas, presión, etc), utilizandolos métodos que les resultasen más cómodos.

Para ello, se pide construir la clase Distancia que contendrá métodos comoSetKilometros, SetMillas, etc. Internamente se usará un único dato miembroprivado llamado kilometros al que se le asignará un valor a través de los métodosanteriores, realizando la conversión oportuna (una milla es 1,609344 kilómetros). Laclase también proporcionará métodos como GetKilometros y GetMillas para loque tendrá que realizar la conversión oportuna (un kilómetro es 0,621371192 millas).

Observad que la implementación de la clase podría haber utilizado como dato miem-bro privado, una variable millas, en vez de kilómetros. Esto se oculta a losusuarios de la clase, que sólo ven los métodos SetKilometros, SetMillas,GetKilometros y GetMillas.

Nota. Otro de los fallos del proyecto fue que no se hicieron suficientes pruebas delsoftware antes de su puesta en marcha, lo que podría haber detectado el error. Estopone de manifiesto la importancia de realizar una batería de pruebas para comprobarel correcto funcionamiento del software en todas las situaciones posibles. Esta parteen el desarrollo de un proyecto se le conoce como pruebas de unidad (unit testing)

Finalidad: Trabajar con una clase como una abstracción de un concepto. DificultadBaja.

21. Se quiere construir una clase para representar la tracción de una bicicleta, es decir,el conjunto de estrella, cadena y piñón. Supondremos que el plato delantero tienetres estrellas y el trasero tiene 7 piñones. La clase debe proporcionar métodos paracambiar la estrella y el piñón, sabiendo que la estrella avanza o retrocede de 1 en 1, ylos piñones cambian a salto de uno o de dos.

Una vez hecha la clase y probada con un programa principal, modificadla para queno permita cambiar la marcha (con la estrella o el piñón) cuando haya riesgo de quese rompa la cadena. Este riesgo se produce cuando la marcha a la que queremoscambiar es de la siguiente forma:

• Primera estrella y piñón mayor o igual que 5• Segunda estrella y piñón o bien igual a 1 o bien igual a 7• Tercera estrella y piñón menor o igual que 4

Guión de Prácticas. Fundamentos de Programación 77

Page 353: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS III. Funciones y Clases

Finalidad: Diseñar la interfaz de una clase. Trabajar con datos miembro constantes..Dificultad Media.

22. Construid una clase llamada MedidaAngulo que represente una medida de un ángu-lo. Al igual que se hizo en el ejercicio 20, la clase aceptará datos que vengan de algunade las siguientes formas: número de grados con decimales (real); número de radianes(entero); número de segundos (entero); número de grados, minutos y segundos (enun struct que represente estos tres valores)

Dificultad Baja.

23. Recuperad el ejercicio 5 de esta relación de problemas sobre la función gaussiana.Ahora estamos interesados en obtener el área que cubre la función en el intervalo[−∞, x]. Dicho valor se conoce como la distribución acumulada (cumulative dis-tribution function) en el punto x, abreviado CDF (x). Matemáticamente se calcula

realizando la integral∫ x

−∞gaussiana(x)dx, tal y como puede comprobarse ejecutan-

do el applet disponible en:http://dostat.stat.sc.edu/prototype/calculators/index.php3?dist=Normal

También pueden obtenerse un valor aproximado de CDF (x), como por ejemplo, eldado por la siguiente fórmula (ver Wikipedia: Normal distribution)

CDF (x) = Área hasta (x) ≈ 1− gaussiana(x)(b1t+ b2t2 + b3t

3 + b4t4)

dónde:

t =1

1 + b0xb0 = 0,2316419 b1 = 0,319381530 b2 = −0,356563782

b3 = 1,781477937 b4 = −1,821255978 b5 = 1,330274429

Para implementarlo, podríamos definir la función siguiente:

double AreaHasta (double esperanza, double desviacion, double x)

En vez de trabajar con funciones, planteamos la solución con una clase. La clase sellamará Gaussiana y crearemos objetos pasándole en el constructor la esperanzay la distribución (los parámetros que definen la gaussiana). Le añadiremos métodospara:

• Obtener el valor de la función en un punto x cualquiera.

• Obtener el área hasta un punto x cualquiera.

Dificultad Media.

Guión de Prácticas. Fundamentos de Programación 78

Page 354: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS III. Funciones y Clases

24. Cread un struct llamado CoordenadasPunto2D para representar un par devalores reales correspondientes a un punto en R2. Cread ahora una clase lla-mada Circunferencia. Para establecer el centro, se usará un valor del tipoCoordenadasPunto2D. Añadid métodos para obtener la longitud de la circunferen-cia y el área del círculo interior. Añadid también un método para saber si la circun-ferencia contiene a un punto. Recordemos que un punto (x1, y1) está dentro de unacircunferencia con centro (x0, y0) y radio r si se verifica que:

(x0 − x1)2 + (y0 − y1)2 <= r2

Observad que el valor de π debe ser constante, y el mismo para todos los objetos dela clase Circunferencia.

Finalidad: Trabajar con constantes estáticas de tipo double. Dificultad Baja.

25. Implementad la clase del ejercicio 13 de esta relación de problemas. Dificultad Media.

Guión de Prácticas. Fundamentos de Programación 79

Page 355: Fundamentos de Programacion

Funciones

Sesión 6

Funciones

I Actividades a realizar en casa

Actividad: Resolución de problemas.

Resolved los siguientes ejercicios de la relación de problemas III:

• Obligatorios:

1 (Máximo de 3 doubles)2 (Progresión geométrica)3 (Tarifa aérea)4 (Comprobar si una letra es minúscula y pasar a mayúscula)5 (Gaussiana)

• Opcionales:

6 (Mayúscula a minúscula y viceversa)

Actividades de Ampliación

Familiarizarse con las webs de referencias de funciones estándar.http://www.cplusplus.com/reference/clibrary/

http://www.cppreference.com

I Actividades a realizar en las aulas de ordenadoresDurante la primera media hora de clase, seguid las instrucciones indicadas en el apartadosiguiente Depuración de funciones (el otro apartado es para hacerlo en casa), mientras queel profesor corrige individualmente los ejercicios de algunos alumnos. Durante el resto de lasesión, el profesor irá llamando a los alumnos para que expliquen al resto de compañeroslos ejercicios de esta sesión.

Guión de Prácticas. Fundamentos de Programación 80

Page 356: Fundamentos de Programacion

Funciones

Depuración de funciones

• Ejecución paso a paso dentro de las funciones.

Abrid el proyecto III_Max, disponible en el directorio de Material de la Asignatura.Incluid un punto de interrupción en la primera línea del main. Ejecutad con F5. Si pul-samos F10 ejecutaremos el programa paso a paso, pero cuando llegue a la sentenciaque llama a la función Max, el depurador no entrará en el código de dicha función. Parapoder hacerlo, habrá que pulsar F11 justo antes de la llamada a la función. Se puedealternar F10 y F11 de forma arbitraria. El icono de acceso directo a esta funcionalidad

es . Probadlo.

Si pulsamos F11 justo en la llave cerrada del main, el depurador entrará en el códigode una función especial que se encarga de ejecutar el programa. Para salirnos, obien pulsamos F5, o bien interrumpimos la ejecución. Para no entrar en este código,cuando lleguemos a la llave cerrada del main, pulsaremos F10 o F5.

• Salirse de una función.

Si durante la depuración entramos en el código de una función, por ejemplo Max, yqueremos ejecutar de golpe el resto de la función Max y proseguir paso a paso a partirde la línea desde la que se llamó a Max, pulsaremos Shift-F11 .

• Variables locales.

Cuando estemos escribiendo código, la función de autocompletar el nombre de lasvariables con Ctr-Barra espaciadora también está disponible dentro de las funciones(para las variables locales).

Cuando estamos depurando, en la ventana Variables Locales podemos ver el va-lor de las variables locales de la función activa en ese momento. Obviamente, tambiénaparecen los parámetros formales ya que son variables locales a la función. Compro-badlo ejecutando paso a paso la función Max.

Otra forma de ver el valor de una variable local durante la depuración es dejar el cursordel ratón encima de la variable y aparecerá una leyenda en amarillo con el valor quedicha variable tiene en ese momento (al igual que hacíamos con las variables delmain)

• Ir a definición.

Otro recurso interesante del entorno de Visual Studio es el siguiente: situad el cursorsobre la llamada a una función, por ejemplo, sobre la llamada a Max desde el main.Haced click con el ratón derecha y seleccionad Ir a definición (o pulsad sobre

el icono ). Automáticamente, el cursor se situará en la definición de la función. Paravolver a la línea en la que estábamos, pulsaremos Ctr- (navegación hacia atrás), o

bien pincharemos sobre el icono

Guión de Prácticas. Fundamentos de Programación 81

Page 357: Fundamentos de Programacion

Funciones

• En la ventana Vista de Clases, si pinchamos sobre Funciones y variables globales,podremos ver las funciones definidas dentro del fichero .cpp. Haciendo doble clicksobre cualquier función, el cursor se sitúa en el código de la función.

Figura 8: Vista de Clases

• Una vez hayamos definido una función, desde cualquier otra función definida con pos-terioridad, podemos invocarla escribiendo su nombre y la lista de parámetros actuales.Visual Studio permite el uso de Ctr-Barra espaciadora para completar el nombre dela función llamada. Además, saldrá automáticamente una leyenda informativa con losnombres de los parámetros formales.

Guión de Prácticas. Fundamentos de Programación 82

Page 358: Fundamentos de Programacion

Funciones

Apéndice: Saltar la depuración de ciertas funciones

Lo que sigue a continuación es para hacerlo en nuestra casa y no en esta sesión de prácti-cas.Cuando se pulse F11 sobre una instrucción cin, cout o system el depurador de Vi-sual Studio también entrará en el código fuente de dichos recursos. Para que no lo ha-ga, debemos ejecutar el fichero StepOver_VS_2010.reg (se encuentra en el directorioOtros Recursos Visual Studio dentro del fichero fp.zip que se proporcionó al ini-cio de la asignatura). Para ello, basta hacer doble click sobre él desde el explorador delSistema Operativo. Una vez hecho esto, volvemos a cargar Visual Studio. Esta operaciónsólo es necesario realizarla una vez en nuestro PC (en las aulas de prácticas no es nece-sario hacerlo). Si no funcionase la ejecución del fichero, hay que cambiar manualmente elregistro de Windows, ejecutando Regedit y accediendo a la clave

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\NativeDE\StepOver]

y seleccionamos con el click derecho del ratónNuevo->Valor alfanumérico.

Añadimos sendas claves con los nombres NoDepures1 y NoDepures2 (por ejemplo) ycon los siguientes valores:

std\:\:.*=NoStepIntosystem=NoStepInto

Guión de Prácticas. Fundamentos de Programación 83

Page 359: Fundamentos de Programacion

Clases

Sesión 7

Clases

I Actividades a realizar en casa

Actividad: Resolución de problemas.

Resolved los siguientes ejercicios de la relación de problemas III:

• Obligatorios:

7 (Conjunto de 3 valores)8 (Pareja de enteros)10 (Progresión geométrica)

• Opcionales:

9 (Pareja de enteros con un menú principal)

I Actividades a realizar en las aulas de ordenadoresEl profesor irá llamando a los alumnos para que expliquen al resto de compañeros losejercicios de esta sesión. Si sobra tiempo, los alumnos pueden trabajar sobre los ejerciciosdel próximo examen.

Guión de Prácticas. Fundamentos de Programación 84

Page 360: Fundamentos de Programacion

Clases

Sesión 8

I Actividades a realizar en casa

Durante la semana del 21 al 25 de Noviembre se realizará el primer examen práctico. Dichoexamen se realizará durante las horas de las sesiones prácticas.Para la próxima semana, no hay que resolver ningún problema, pero sí hay que hacer losiguiente:

• Seguid las instrucciones indicadas en el apartado siguiente Inspección de objetos.Esta actividad hay que realizarla en la casa (no más de 10 minutos).

• Consultar las soluciones a los siguientes ejercicios (las soluciones están disponiblesen la web de la asignatura y en clase de teoría ya se han explicado la mayoría)

23 (Gaussiana)11 (Interés)12 (Fabricante)15 (Fracción)16 (MiReal)18 (MiEntero)13 (Nómina)14 (Pareja de enteros con el menú principal como una clase)

Guión de Prácticas. Fundamentos de Programación 85

Page 361: Fundamentos de Programacion

Clases

Inspección de objetos

Recuperar la solución del ejercicio 9 disponible en la web de la asignatura(III_ParejaEnteros). Incluid un punto de interrupción dentro del método MCD tal y comose indica en la figura. Ejecutar el programa introduciendo dos enteros cualesquiera y selec-cionar la opción de calcular el máximo común divisor. Cuando la ejecución pare al llegar alpunto de interrupción, abrir la ventana de inspección de variables locales:

Depurar -> Ventanas -> Variables Locales

Podremos ver el valor de las variables locales al método MCD, así como los datos miembro(desplegando el signo + que aparece junto al nombre this) De todas las variables que semuestran, la última en modificarse se mostrará en color rojo.

Guión de Prácticas. Fundamentos de Programación 86

Page 362: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS IV. Vectores

RELACIÓN DE PROBLEMAS IV. Vectores

Importante: Para todos los ejercicios, se ha de diseñar una batería de pruebas.Si se va a leer desde un fichero, para poder leer carácter a carácter incluidos los espaciosen blanco, debe realizar la lectura en la forma caracter = cin.get(). Cada vez quese ejecute cin.get() el compilador lee un carácter (incluido el espacio en blanco) desdela entrada de datos por defecto.

Problemas Básicos

1. En clase de teoría se ha visto la siguiente clase MiVectorCaracteres.

class MiVectorCaracteres{private:

static const int TAMANIO = 50;char vector_privado[TAMANIO];int total_utilizados;

public:MiVectorCaracteres()

:total_utilizados(0){}int TotalUtilizados(){

return total_utilizados;}void Aniade(char nuevo){

if (total_utilizados < TAMANIO){vector_privado[total_utilizados] = nuevo;total_utilizados++;

}}char Elemento(int indice){

return vector_privado[indice];}

};

Añadir un método que nos diga si el vector es un palíndromo, es decir, quese lee igual de izquierda a derecha que de derecha a izquierda. Por ejemplo,{'a','b','b','a'} sería un palíndromo.

Finalidad: Ejemplo de método que accede a las componentes del vector. DificultadBaja.

Guión de Prácticas. Fundamentos de Programación 87

Page 363: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS IV. Vectores

2. Sobre la clase MiVectorCaracteres, añadir un método con la cabecera

void Modifica (int indice_componente, char nuevo)

para que modifique la componente con índice indice_componente y ponga en sulugar el valor nuevo. Este método está pensado para modificar una componente yaexistente, pero no para añadir componentes nuevas. Por tanto, en el caso de que lacomponente no esté dentro del rango correcto, el método no modificará nada.

Finalidad: Ejemplo de método que modifica el estado del objeto. Gestión de precondi-ciones. Dificultad Baja.

3. Sobre la clase MiVectorCaracteres, añadir un métodoIntercambiaComponentes para intercambiar dos componentes del vector.Por ejemplo, si el vector contiene {'h','o','l','a'}, después de intercambiarlas componentes 1 y 3, se quedaría con {'h','a','l','o'}.

Añadid otro método para invertir el vector, de forma que si el vector contenía los carac-teres {'a','g','t','b','i','o'}, después de llamar al método se quedará con{'o','i','b','t','g','a'}. Para implementar este método, llamad el métodoanterior IntercambiaComponentes.

¿Qué deberían hacer los métodos si los índices de componentes no son correctos?

Imprimir las componentes del vector desde el main, antes y después de llamar adicho método. Observad que se repite el mismo tipo de código cuando se imprimenlas componentes del vector. Ya lo arreglaremos en el tema siguiente.

Finalidad: Ejemplo de método que modifica el estado del objeto. Gestión de precondi-ciones. Dificultad Baja.

4. Sobre la clase MiVectorCaracteres, añadir un método Elimina para eliminar elcarácter que se encuentre en una determinada posición, de forma que si el vectorcontenía los caracteres {'h','o','l','a'}, después de eliminar la componentecon índice 2 (la tercera) se quedará con {'h','o','a'}.

¿Qué debería hacer el método si el índice de componente no es correcto?

Finalidad: Ejemplo de método que modifica el estado del objeto. Gestión de precondi-ciones. Dificultad Baja.

5. Sobre la clase MiVectorCaracteres, se quiere añadir un métodoEliminaMayusculas para eliminar todas las mayúsculas. Por ejemplo, des-pués de aplicar dicho método al vector {'S','o','Y',' ','y','O'}, éste debequedarse con {'o',' ','y'}. Implementar el siguiente algoritmo:

Recorrer todas las componentes del vectorSi la componente es una mayúscula, borrarla

Guión de Prácticas. Fundamentos de Programación 88

Page 364: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS IV. Vectores

Para borrar la mayúscula, se desplazan una posición a la izquierda todas las compo-nentes que hay a su derecha. Para ello, llamad al método Elimina que se ha definidoen el ejercicio 4 de esta relación de problemas.

Finalidad: Recorrido sencillo de un vector con dos bucles anidados. Dificultad Baja.

6. El algoritmo del ejercicio 5 es muy ineficiente ya que requiere trasladar muchas vecesmuchas posiciones. Proponer un algoritmo para resolver eficientemente este problemae implementarlo.

Consejo: Una forma de hacerlo es utilizar dos variables, posicion_lectura yposicion_escritura que nos vayan indicando, en cada momento, la componenteque se está leyendo y el sitio dónde tiene que escribirse.

Finalidad: Modificar un vector a través de dos apuntadores. Dificultad Media.

Problemas de Ampliación

7. Sobre la clase MiVectorCaracteres, añadir un método para eliminar elexceso de caracteres en blanco, es decir, que suprima todas las secuen-cias de espacios en blanco mayor de 1. Por ejemplo, si el vector ori-ginal es (' ','a','h',' ',' ',' ','c'), el vector resultante debe ser(' ','a','h',' ','c'). Debe hacerse lo más eficiente posible.

Finalidad: Recorrido de las componentes de un vector, en el que hay que recordar loque ha pasado en la iteración anterior. Dificultad Media.

8. Sobre la clase MiVectorCaracteres, añadir un método EliminaRepetidos quequite los elementos repetidos, de forma que cada componente sólo aparezca unaúnica vez. Por ejemplo, si el vector contiene{'b','a','a','h','a','a','a','a','c','a','a','a','g'}después de quitar los repetidos, se quedaría como sigue:{'b','a','h','c','g'}

Implementad los siguientes algoritmos para resolver ester problema:

a) Usar un vector local sin_repetidos en el que almacenamos una única apari-ción de cada componente:

Recorrer todas las componentes del vector originalSi la componente NO está en el vector sin_repetidos,añadirla (al vector sin_repetidos)

Asignar las componentes de sin_repetidos al vector original

b) El problema del algoritmo anterior es que usa un vector local, lo que podría su-poner una carga importante de memoria si trabajásemos con vectores grandes.Por lo tanto, vamos a resolver el problema sin usar vectores locales.

Guión de Prácticas. Fundamentos de Programación 89

Page 365: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS IV. Vectores

Si una componente está repetida, se borrará del vector. Para borrar una compo-nente, podríamos desplazar una posición a la izquierda, todas las componentesque estén a su derecha. El algoritmo quedaría:

Recorrer todas las componentes del vector originalSi la componente se encuentra en alguna posiciónanterior, la eliminamos desplazando hacia laizquierda todas las componentes que hay a su derecha.

c) El anterior algoritmo nos obliga a desplazar muchas componentes cada vez queencontremos una repetida. Proponed una alternativa (sin usar vectores locales)para que el número de desplazamientos sea lo menor posible, e implementadlaen el método EliminaRepetidos

Dificultad Media.

9. Supongamos un fichero en el que hay caracteres cualesquiera. Realizar un programaque vaya leyendo dichos caracteres hasta que se encuentre un punto '.'. Queremoscontar el número de veces que aparece cada una de las letras mayúsculas ('A',· · · , 'Z'). Una posibilidad sería leer el carácter, y después de comprobar si es unamayúscula, ejecutar un conjunto de sentencias del tipo:

if (letra == 'A')conteo_caracteres[0] = conteo_caracteres[0] + 1;

else if (letra == 'B')conteo_caracteres[1] = conteo_caracteres[1] + 1;

else if (letra == 'C')conteo_caracteres[2] = conteo_caracteres[2] + 1;

else ....

Sin embargo, este código es muy redundante. Proponed una solución e implementarla.

Para resolver este ejercicio puede usarse o bien un vector clásico de enteros, o bienun objeto de una clase que construyamos del tipo MiVectorEnteros (en cuyo ca-so, sustituiríamos los corchetes de acceso a las componentes por el correspondientemétodo)

Finalidad: Diseñar un vector en el que los índices de las componentes representanalgo. Dificultad Media.

10. Sobre la clase MiVectorCaracteres, añadir un métodoPosicionCaracteresConsecutivos que calcule la posición donde se en-cuentre la primera secuencia de al menos n caracteres consecutivos e iguales a unoque se pase como parámetro al método. Por ejemplo, en el vector de abajo, si n = 3,y el carácter buscado es 'a', entonces dicha posición es la 4.{'b','a','a','h','a','a','a','a','c','a','a','a','g'}

Dificultad Media.

Guión de Prácticas. Fundamentos de Programación 90

Page 366: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS IV. Vectores

11. Escribir un programa que calcule, almacene en un vector y muestre por pantalla losk primeros términos de la sucesión de Fibonacci de orden n. Tanto n como k seránenteros a leer desde el dispositivo de entrada por defecto.

La sucesión de Fibonacci de orden n es una secuencia de números en la que losdos primeros son el 0 y el 1. A partir del tercero, los elementos se calculan como lasuma de los n anteriores, si ya hay n elementos disponibles, o la suma de todos losanteriores si hay menos de n elementos disponibles.

Por ejemplo, la sucesión de Fibonacci de orden 4 sería la siguiente:

0, 1, 1, 2, 4, 8, 15, 29, . . .

El programa debe definir una clase llamada Fibonacci para generar los números deFibonacci y otra clase del tipo MiVectorEnteros para ir almacenándolos.

Dificultad Media.

Guión de Prácticas. Fundamentos de Programación 91

Page 367: Fundamentos de Programacion

Vectores

Sesión 9

Vectores

I Actividades a realizar en casa

Actividad: Resolución de problemas.

Resolved los siguientes ejercicios de la relación de problemas IV. Entregad un único fiche-ro que contenga la clase MiVectorCaracteres con todos los métodos pedidos en lossiguientes ejercicios.

• Obligatorios:

1 (Palíndromo)2 (Modifica componente)3 (Invierte)4 (Elimina componente)5 (Elimina las mayúsculas)

• Opcionales:

6 (Elimina las mayúsculas eficientemente)

I Actividades a realizar en las aulas de ordenadoresEl profesor irá llamando a los alumnos para que expliquen al resto de compañeros losejercicios de esta sesión.

Guión de Prácticas. Fundamentos de Programación 92

Page 368: Fundamentos de Programacion

Vectores

Sesión 10

I Actividades a realizar en casa

Actividad: Resolución de problemas.

Resolved los siguientes ejercicios de la relación de problemas IV:

• Obligatorios:

8 (Elimina repetidos)

• Opcionales:

7 (Elimina exceso de blancos)

I Actividades a realizar en las aulas de ordenadoresEl profesor irá llamando individualmente a los alumnos para que defiendan los ejercicios deesta sesión. Mientras tanto, el resto de los alumnos pueden trabajar sobre los ejercicios delpróximo examen.

Guión de Prácticas. Fundamentos de Programación 93

Page 369: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS V. Clases (Segunda parte)

RELACIÓN DE PROBLEMAS V. Clases (Segunda parte)

Problemas Básicos

1. A la hora de diseñar una clase debemos poner especial énfasis en intentar que sea lomás reutilizable posible, intentando que su interfaz pública no esté ligada a los detallesde la implementación. Por ejemplo, en el ejercicio 9 de la relación de problemas III sedefinió una clase para leer una opción del usuario. Para ello, se definió una clase Menucon un método LeeOpcion() que devolvía un char. ¿Y si quisiésemos modificarel criterio de entrada y que la opción fuese un entero en vez de un carácter o quefuesen caracteres distintos? Habría que hacerlo en dos sitios: por un parte, dentro dela clase Menu y por otra parte en el programa main en el que se utiliza. Para evitarlo,podemos definir el método LeeOpcion() para que devuelva algo más genérico queun char, por ejemplo, un enumerado que represente la opción leída. De esta forma,si queremos cambiar la forma en la que se lee la opción (por ejemplo '1' en vezde ’P’, '4' en vez de 'I', etc), bastará modificar la implementación interna de laclase Menu, pero los clientes de dicha clase (en nuestro caso el programa principalmain) seguirán utilizándola de la misma forma, a través del enumerado que devuelveel método.

Recuperad la solución al ejercicio 9 disponible en la web del departamento(III_ParejaEnterosMenu.cpp) y realizad la transformación pedida.

Finalidad: Enfatizar la necesidad de abstraer la interfaz de una clase. Dificultad Baja.

2. En clase de teoría se ha definido la siguiente clase para representar una matriz, en laque cada fila puede tener un número distinto de columnas.

class MiMatrizCaracteres{private:

static const int MAXIMO_FILAS = 40;MiVectorCaracteres matriz_privada[MAXIMO_FILAS];int filas_utilizadas;

public:MiMatrizCaracteres()

:filas_utilizadas(0){ }int FilasUtilizadas(){

return filas_utilizadas;}char Elemento(int fila, int columna){

return matriz_privada[fila].Elemento(columna);}

Guión de Prácticas. Fundamentos de Programación 94

Page 370: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS V. Clases (Segunda parte)

MiVectorCaracteres Fila(int indice_fila){return matriz_privada[indice_fila];

}void Aniade(MiVectorCaracteres nueva_fila){

if (filas_utilizadas < MAXIMO_FILAS){matriz_privada[filas_utilizadas] = nueva_fila;filas_utilizadas++;

}}

};

Cread un programa principal en el que se cree una matriz, se le añadan varias filasy se impriman todos sus caracteres. Para imprimir los caracteres, accederemos enprimer lugar a cada fila de la matriz a través del método Fila. Se pide hacerlo de dosformas:

a) Imprimir cada fila con un bucle que vaya recorriendo los caracteres de dicha filaa través del método Elemento.

b) Imprimir cada fila usando la clase ImpresorVectorCaracteres vista en clasede teoría.

Finalidad: Usar matrices desde main. Dificultad Baja.

3. Cread una clase ImpresorMatricesCaracteres para que imprimamatrices de caracteres. En la definición de esta clase, utilizad la claseImpresorVectorCaracteres vista en clase de teoría.

Finalidad: Pasar a un método de una clase un parámetro de otra clase. Dificultad Baja.

4. Añadid un método a la clase MiMatrizCaracteres para que inserte una fila com-pleta en una posición (de fila) determinada. Por ejemplo, c b a l ?

f g h ? ?? ? ? ? ?

→ Insertar(d, d, e, e)en la fila 1

c b a l ?d d e ? ?f g h i ?

dónde ? representa un valor no utilizado. Se quiere que el módulo sea robusto, por loque deben comprobarse las precondiciones pertinentes.

Finalidad: Pasar a un método de una clase un parámetro de otra clase. Dificultad Baja.

5. Cread la clase MiMatrizRectangularCaracteres modificando apropiadamentela clase MiMatrizCaracteres para obligar a que todas las filas tengan el mismonúmero de columnas, es decir, que sea una matriz rectangular.

Finalidad: Diseñar apropiadamente una clase. Dificultad Baja.

Guión de Prácticas. Fundamentos de Programación 95

Page 371: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS V. Clases (Segunda parte)

6. Modificad la clase MiMatrizCaracteres para que las filas sean del tipovector <char> en vez de MiVectorCaracteres. Se pide cambiar la interfaz pú-blica y el dato miembro que representa la matriz, es decir:

vector <vector <char>> matriz_privada;

La clase debe proporcionar, como mínimo, los siguientes métodos públicos:

int FilasUtilizadas()int ColumnasUtilizadas()void Aniade(vector <char> fila_nueva)char Elemento(int indice_fila, int indice_columna)vector <char> Fila(int indice_fila)void Intercambia(int indice_una_fila, int indice_otra_fila)

Obsérvese que el método Aniade añadirá a la matriz rectangular una fila entera. Estafila es un objeto de la plantilla vector.

Finalidad: Diseñar apropiadamente una clase. Dificultad Baja.

7. Modificad la clase definida en el ejercicio 6 de la siguiente forma. En la interfaz pú-blica seguiremos usando el tipo vector <char>, pero para almacenar y manejarinternamente los datos, se usará una matriz clásica de dos dimensiones:

class MiMatrizCaracteres{private:

static const int MAXIMO_FILAS = 50;static const int MAXIMO_COLUMNAS = 40;char matriz_privada[MAXIMO_FILAS][MAXIMO_COLUMNAS];......

};

Finalidad: Diseñar apropiadamente una clase. Dificultad Baja.

8. En el ejercicio 15 de la relación de problemas III se creó una clase para representaruna fracción. Recuperad la solución disponible en la web de la asignatura. Se piderediseñar la clase Fraccion para que, en vez de trabajar con dos datos miembronumerador y denominador, trabaje con un único dato miembro que será un ob-jeto del tipo ParejaEnteros (esta clase se vio en el ejercicio 8 de la relación deproblemas III). Se pide:

• Construid dos constructores para la clase Fraccion:

– Uno de ellos se le pasará como parámetros dos enteros que representenel numerador y el denominador (aunque se le pasen dos enteros, hemosindicado que la clase contendrá un único dato miembro privado de tipoParejaEnteros)

Guión de Prácticas. Fundamentos de Programación 96

Page 372: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS V. Clases (Segunda parte)

– Al otro constructor se le pasará un objeto de la clase ParejaEnteros.

• La clase ParejaEnteros debe proporcionar el método MCD para calcular elmáximo común divisor.

• Añadir también dos métodos para sumar y multiplicar dos fracciones. La declara-ción será de la forma

class Fraccion{......Fraccion Suma(Fraccion otra_fraccion)

};

• Cread un programa principal que cree varios objetos fracciones y ejecute susmétodos.

Finalidad: Declarar un objeto como dato miembro de otro objeto y pasar como pará-metro un objeto de la misma clase. Dificultad Baja.

9. Cread una clase LectorVectorCaracteres que lea los datos de un vector de ca-racteres (de un objeto de la clase MiVectorCaracteres).

Finalidad: Ver un método de una clase que devuelve un objeto de otra clase. DificultadBaja.

Problemas sobre Excepciones

10. Como ya se ha comentado en clase de teoría, si se produce la violación de las pre-condiciones de un método podemos hacer varias cosas:

• El método no hará nada o devolverá un valor indeterminado.El caso típico sería el método Elemento de la clase MiVectorCaracteres.Si se le pasa un índice incorrecto, devolvería cualquier valor.

• El método lanza una excepción para notificar el error producido.El caso típico sería el método Inserta de la clase MiVectorCaracteres. Sise le pasa un índice incorrecto, el método lanza una excepción.Nota: Si se estima oportuno, el mismo método anterior Elemento podría lanzaruna excepción, aunque al ser un método muy usado, optamos por aumentar laeficiencia no comprobando que el índice sea correcto.

En la relación de problemas IV se trabajó con la clase MiVectorCaracteres. Ana-lizar los métodos que deberían lanzar una excepción y programarlos, incluyendo unprograma principal que capture dichas excepciones. Incluir, al menos, los métodos

Guión de Prácticas. Fundamentos de Programación 97

Page 373: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS V. Clases (Segunda parte)

Aniade, TotalUtilizados, Modifica, Elemento y los que resolvían los ejerci-cios 1 (Palíndromo), 3 (Invierte), 4 (Elimina) y 5 (Elimina mayúsculas) de la relaciónde problemas IV.

Las excepciones que se lancen deben ser de la biblioteca estándar stdexcept.

Finalidad: Lanzar excepciones para notificación de errores. Dificultad Baja.

11. Modificad la solución del ejercicio 8 de esta relación de problemas para que incluya ellanzamiento de excepciones en aquellos sitios dónde haya que hacerlo.

Finalidad: Lanzar excepciones para notificación de errores. Dificultad Baja.

Problemas de Ampliación

12. Sobre la clase MiVectorCaracteres, añadidle un método que compruebe sitodos los elementos del vector están en un segundo vector. Debe respetar-se el orden en el que aparecen los caracteres, pero no tienen por qué estarconsecutivos. Por ejemplo, el vector {'f','e'} se encuentra dentro del vector{'c','o','f','r','e','s'}. La cabecera del método será:

int PrimeraOcurrenciaDebil (MiVectorCaracteres otro_vector)

Observad que al método se le pasa como parámetro un objeto de la misma clase a laque pertenece dicho método y devuelve la posición de la primera ocurrencia (-1 si noestá).

Finalidad: Pasar a un método de una clase un parámetro de la propia clase. DificultadBaja.

13. En el ejercicio 12 se veía si todos los caracteres de una subcadena estaban enotra. Haced lo mismo pero obligando a que los caracteres se encuentren en posi-ciones consecutivas. Por ejemplo, el vector {'f','f','e'} se encuentra dentro de{'e','c','o','f','f','f','e','s'} (a partir de la posición 4), pero no den-tro de {'c','o','f','f','s','e'}

Finalidad: Pasar a un método de una clase un parámetro de la propia clase.. DificultadMedia.

14. Se quiere calcular la moda de un vector de caracteres, es decir, el carácter que másveces se repite. Por ejemplo, si el vector fuese

{'l','o','s',' ','d','o','s',' ','c','o','f','r','e','s'}

los caracteres que más se repiten son 'o' y 's' con un total de 3 apariciones. Lamoda sería cualquiera de ellos, por ejemplo, el primero encontrado 'o'. El métododevolverá un struct del tipo:

Guión de Prácticas. Fundamentos de Programación 98

Page 374: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS V. Clases (Segunda parte)

struct ParCaracterEntero{char caracter;int entero;

}

en el que el campo caracter contendrá el carácter en cuestión ('o') y el campoentero el conteo de la moda (3).

15. Modificad el ejercicio 24 de la relación de problemas III (creación de la cla-se Circunferencia) para que use una clase Punto2D en vez del structCoordenadasPunto2D

Finalidad: Declarar un objeto como dato miembro de otro objeto. Dificultad Baja.

16. Supongamos una matriz rectangular M (usad la claseMiMatrizRectangularCaracteres vista en el ejercicio 5 de esta relaciónde problemas). Añadir métodos para:

a) Sumar aquellos valores Mij de la matriz M que verifiquen que i+ j sea igual a:

k∑h=1

h2

para algún valor de k ≥ 1.

b) Comprobar si es igual a otra matriz rectangular.

c) Obtener la traspuesta de la matriz.

d) Comprobar si es simétrica. Hacedlo primero calculando la traspuesta de la matrizy viendo si es igual a su simétrica, usando los métodos de los ejercicios anterio-res. Hacedlo también comprobando directamente si cada componente es igual asu simétrica y parando el recorrido en cuanto encuentre una componente que nolo verifique.

Guión de Prácticas. Fundamentos de Programación 99

Page 375: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS V. Clases (Segunda parte)

Sesión 11

I Actividades a realizar en casa

Para la primera semana de vuelta de vacaciones de Navidad (del 9 al 13 de Enero), nohay que resolver ningún problema, pero sí hay que consultar las soluciones a los siguientesejercicios (las soluciones están disponibles en la web de la asignatura). El profesor explicaráestos ejercicios durante la sesión de prácticas a la vuelta de Navidad. Se recomienda que:

• Se intente plantear la solución de los ejercicios antes de ver la solución

• Se consulten las soluciones antes de empezar a resolver los ejercicios del segundoexamen práctico.

1 (Clase menú de opciones con un enumerado)2 (Imprimir matrices)3 (Imprimir matrices con una clase específica)4 (Insertar una fila en una matriz)5 (Matriz Rectangular)8 (Fracción con pareja de enteros)

Durante la semana del 23 al 27 de Enero se realizará el segundo examen práctico. Dichoexamen se realizará durante las horas de las sesiones prácticas.

Guión de Prácticas. Fundamentos de Programación 100

Page 376: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS VI. Recursividad

RELACIÓN DE PROBLEMAS VI. Recursividad

Problemas Básicos

1. Definir una función recursiva para sumar los dígitos de un entero positivo.

2. Cread sendas funciones recursivas para:

a) Calcular la división entera entre dos números enteros positivos.

b) Calcular el resto de la división entera de dos números enteros positivos.

Pasad como parámetros a cada función los dos enteros, y suponed que en la llamadasiempre pasarán números positivos (es la precondición de la función)

En la definición de las funciones no pueden utilizarse los operadores de división, mul-tiplicación ni módulo.

3. Sobre la clase MiVectorCaracteres, definir un método recursivo que nos diga sies un palíndromo, es decir, que se lee igual de izquierda a derecha que de derecha aizquierda. Por ejemplo, {'a','b','b','a'} sería un palíndromo.

Pasad al método como parámetros las posiciones izquierda y derecha sobre las quetrabajará.

4. Definir una función recursiva a la que se le pasen dos valores enteros n y k y devuel-va como resultado el valor k-ésimo comenzando por la derecha del número n. Porejemplo para n = 427 y k = 3 el resultado sería 4.

Si k es mayor que el número de dígitos de n la función devolverá el valor 0. Porejemplo, para n = 23 y k = 5 el resultado es 0.

5. Definid una función recursiva con prototipo

int MCD(int un_entero, int otro_entero)

para que calcule el máximo común divisor entre dos enteros, aplicando el algoritmode Euclides.

6. Cread una función recursiva con la siguiente cabecera

bool ContieneDesdeInicio(string cadena_grande, string cadena_peque)

que compruebe si la cadena cadena_peque se encuentra al inicio de la cadenacadena_grande (desde la posición cero)

Guión de Prácticas. Fundamentos de Programación 101

Page 377: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS VI. Recursividad

Problemas de Ampliación

7. Cread una función recursiva con la siguiente cabecera

bool Contiene(string cadena_grande, string cadena_peque)

que compruebe si la cadena cadena_peque se encuentra dentro de la cadenacadena_grande. En la definición de esta función, se puede llamar a la funciónContieneDesdeInicio del ejercicio 6

8. Definir una función recursiva que acepte un __int64 y devuelva un vector de carac-teres con los dígitos del mismo incluyendo los puntos de separación cada tres cifrasdecimales. Por ejemplo, para el entero 23456789, la función devolvería el vector decaracteres 23.456.789.

9. Definir una función recursiva para construir un vector de 0 y 1 con la representaciónen binario de un entero. En la página webhttp://es.wikipedia.org/wiki/Sistema_binariose puede consultar cómo pasar un número en decimal a binario. (el mismo procedi-miento para pasar un decimal a binario se aplica sobre cualquier otra base menor oigual que 10).

El bit más significativo (el de la mayor potencia de 2) debe ir en la posición 0 delvector, mientras que el menos significativo (el correspondiente a 20) debe ir en laúltima posición del vector.

La función debe tener la siguiente cabecera:

MiVectorEnteros PasaBinario(int n)

Analizad la eficiencia de esta función.

10. Sobre la clase MiVectorCaracteres, definir un método recursivo que devuelva ladiferencia entre el número de letras mayúsculas y el número de letras minúsculas quehay entres dos posiciones del vector. Por ejemplo, si el vector tuviese los caracteresHay UnAS LeTRas DESpuEs, la diferencia entre mayúsculas y minúsculas entre lasposiciones 4 y 15 sería 6 - 4 = 2.

11. El método de bisección usado para calcular de forma aproximada el punto de corte deuna función f con el eje de abscisas (la raíz de la función) se puede enunciar comosigue:

Sea f(x) una función real, estrictamente monótona en [i, d], donde f(i) y f(d) tienendistinto signo y sea ε una constante real pequeña (del orden de 10−4, por ejemplo).

a) Calcular m, el punto medio entre i y d,

Guión de Prácticas. Fundamentos de Programación 102

Page 378: Fundamentos de Programacion

RELACIÓN DE PROBLEMAS VI. Recursividad

b) Si |i− d| < ε, terminar.

c) Si f(m) tiene igual signo que f(i), repetir considerando el intervalo [m,d]

d) Si f(m) tiene igual signo que f(d), repetir considerando el intervalo [i,m]

Implemente una función recursiva que reciba como datos de entrada los extremos i, ddel intervalo, así como el valor de ε y devuelva la raíz de la función. Se supone que lafunción f(x) ya está definida con anterioridad.

12. Realizar una función recursiva para multiplicar dos enteros según el método de multi-plicación rusa (ver ejercicio 42 de la relación de problemas II de Estructuras de Control-página 51-)

Guión de Prácticas. Fundamentos de Programación 103

Page 379: Fundamentos de Programacion

Recursividad

Sesión 12

Recursividad

I Actividades a realizar en casa

Actividad: Resolución de problemas.

Resolved los siguientes ejercicios de la relación de problemas VI:

• Obligatorios:

1 (Sumar dígitos)2 (División entera)3 (Palíndromo)4 (k-ésimo)5 (Algoritmo de Euclides)

• Opcionales:

6 (Contiene subcadena desde inicio)7 (Contiene subcadena)

I Actividades a realizar en las aulas de ordenadoresEl profesor irá llamando a los alumnos para que expliquen al resto de compañeros losejercicios de esta sesión.

Guión de Prácticas. Fundamentos de Programación 104

Page 380: Fundamentos de Programacion

Proyecto final

Sesión 13

Proyecto final

I Actividades a realizar en casa

Esta sesión es de ampliación. No hay que entregar nada y no entra como materia de exa-men. Corresponde a lo visto en la última semana de clase.Descargad el fichero V_Salario.zip disponible en la web del departamento y descompri-mirlo en el ordenador. Abrir el diagrama de clases UML (salario.pdf) que se encuentradentro de la carpeta del proyecto. Dicho diagrama también está disponible enhttp://decsai.ugr.es/jccubero/salario.pdf

Estudiar la solución propuesta, haciendo especial énfasis en:

• Ver que la solución propuesta implementa el diagrama de clase UML.

• Ver cómo se comunican los objetos a través de los métodos de las clases.

Dentro de la definición de algunas clases hay muchos detalles de manejo de ficheros ode cadenas de caracteres que no son necesarios entender. Lo importante es entendercómo se manejan los objetos de dichas clases (la interfaz pública de las clases)

• Ver cómo se realiza la gestión de errores con throw y try-catch.

Finalidad: Trabajar con un programa que requiere la intervención de varios objetos. Dificul-tad Media.

Guión de Prácticas. Fundamentos de Programación 105

Page 381: Fundamentos de Programacion

EXAMENES

Curso: 2011/2012 Clase: Primero - Grupo: B

Page 382: Fundamentos de Programacion

FUNDAMENTOS DE PROGRAMACIONEXAMEN PRACTICO 1

(Noviembre 2011)¡Importante! No se corregira ninguna practica que no cumpla escrupulosamente

las normas que aparecen a continuacion

Descripcion de la practica

La practica consiste en la realizacion de uno de los problema que se descri-ben mas adelante. El problema concreto que habra que resolver el dıa delexamen, se dara a conocer al inicio de la prueba. El tiempo que se tendra eldıa del examen es de 1 hora.

La resolucion de todos los problemas se hara en ISO C++. Para la resolucionsolo se podran utilizar los conocimientos adquiridos en los temas 1 y 2.

En la evaluacion de las practicas se tendra en cuenta, ademas de la correc-cion de la solucion propuesta, el estilo de programacion, el uso correcto deespacios y tabuladores, ası como la claridad del codigo fuente.

La ejecucion de los programas por parte del profesor se hara de forma au-tomatica, leyendo los datos desde un fichero de validacion y comprobandoque la salida es correcta. En cualquier caso, el alumno puede comprobarque el programa funciona correctamente introduciendo los datos desde unfichero o desde el teclado.

Recordemos que para leer los datos de un fichero hay que ejecutar el progra-ma desde una consola de sistema y redirigir la entrada de datos en la forma:problema.exe < validacion.txt, donde validacion.txt esel nombre del fichero de validacion. Si usa Visual Studio, tambien puedeejecutarlo y depurarlo desde el mismo entorno, indicando el nombre del fi-chero de entrada y el directorio en el que se encuentra. Para ello, hay que irsea la ventana del Explorador de Soluciones y hacer click sobre el nombre delproyecto (no sobre el fichero cpp), y ahora seleccionar desde el menu prin-cipal:

Proyecto/PropiedadesPropiedades de Configuracion/DepuracionArgumentos del comando/Editar/

En esta opcion hay que introducir el caracter < seguido del nombre delfichero de validacion.

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 383: Fundamentos de Programacion

Indicaremos la carpeta en la que se encuentra el fichero de validacion, atraves de la opcion siguiente:

Proyecto/PropiedadesPropiedades de Configuracion/Depuracion

Directorio de trabajo/

En aquellos ejercicios en los que la entrada de datos requiere introducirmuchos valores, se han preparado varios ficheros de validacion. En la pagi-na web de la asignatura (Material de la Asignatura → Examen) se puedenencontrar estos ficheros de validacion.

En los enunciados de los ejercicios encontrara ejemplos de validacion conun formato similar al siguiente:

Entrada: DDDIDDIIDASalida: NO SE ABRE

En el apartado Entrada se describe el formato en el que el programa esperaencontrar los datos en el fichero de validacion. En la Salida, se especificala salida que el programa debe dar. Es importante remarcar que la salidadel programa debe aparecer sola en una lınea de texto siguiendo EXACTA-MENTE el formato especificado.

Instrucciones a seguir el dıa del examen

Para iniciar sesion en las aulas de practicas, tendra que introducir su iden-tificador de usuario y contrasena como siempre. En la casilla Codigo, de-bera introducir el que se le diga el mismo dıa del examen. Con este codigosolo tendra acceso Internet a la pagina de la asignatura. No tendra disponiblesu unidad en red U: ni los puertos USB.

Al inicio del examen, se le indicara el problema que ha de resolver. Tendra quebajar el fichero problema.zip que se encuentra en la web de la asignatu-ra (Material de la Asignatura → Examen) a la carpeta local Mis Documentos.Para copiar el fichero desde la web, hay que pinchar con el boton derechadel raton y seleccionar Guardar destino como.

Una vez copiado el fichero en la carpeta Mis Documentos, pinchad conel boton derecha del raton y seleccionad Extraer todo, para poder extraer losarchivos incluidos y abrir el fichero de solucion correspondiente. Una vezabierto el proyecto, debe modificar los datos que aparecen en la cabecera delfichero problema.cpp. En concreto, su nombre, el nombre del ordenadoren que se sienta y el nombre del problema que aparece entre corchetes en lapagina de los enunciados.

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 384: Fundamentos de Programacion

La entrega de la practica se hara durante la hora que dura el examen. Paraello, se usara el sistema de gestion automatica de practicas (GAP) accesiblea partir de la pagina web de la asignatura (Menu Principal → GAP). Unavez dentro de GAP habra que seleccionar

Practicas -> Entregar -> Examinar

Se abrira un cuadro de dialogo en el que buscara el fichero problema.cpp.Una vez seleccionado, debe pulsar sobre

Entregar practica

Cualquier intento de entregar la practica fuera de la hora del examen con-llevara el suspenso automatico.

Importante: El unico fichero que se debe subir a GAP es el fichero problema.cpp.No debe subirse ningun otro fichero (como por ejemplo los ficheros con ex-tension .vcproj o sln asociados a los proyectos en Visual Studio).

La practica se puede entregar tantas veces como se quiera durante el exa-men. El sistema GAP guarda la ultima entrega. De hecho, se recomiendaque se entregue varias veces a lo largo del examen, ya que si el ordenadorse quedara colgado, habrıa que reiniciarlo y se perderıa toda la informacion.

Tiempo de examen: 1 HORA

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 385: Fundamentos de Programacion

1. [primos] Realizar un programa que compruebe si dos enteros leıdos desdeel teclado son primos relativos, es decir, que no exista ningun valor quedivida de forma entera a ambos. El programa solo debe dar por salida elmensaje “SI” (en el caso de que sean primos relativos) o “NO” (en otrocaso).

Entrada: 2 1246Salida: NO

Entrada: 11 27Salida: SI

2. [elr] El metodo RLE (Run Length Encoding) codifica una secuencia de da-tos formada por series de valores identicos consecutivos como una secuen-cia de parejas de numeros (valor de la secuencia y numero de veces que serepite). Realizar un programa que lea una secuencia de numeros naturalesterminada con un numero negativo que se supone codificada con el metodoRLE y obtenga la secuencia decodificada.

Entrada: 3 1 5 2 6 3 1 5 -1(tres veces 1, cinco veces 2, seis veces 3, una vez 5)

Salida: 1 1 1 2 2 2 2 2 3 3 3 3 3 3 5

3. [nicomaco] Consideremos la siguiente propiedad descubierta por Nicoma-co entre los siglos I y II. Con el primer impar, se obtiene el primer cubo;sumando los dos siguientes impares, se obtiene el segundo cubo; sumandolos tres siguientes, se obtiene el tercer cubo, etc. Por ejemplo:

13 = 1 = 1

23 = 3 + 5 = 8

33 = 7 + 9 + 11 = 27

43 = 13 + 15 + 17 + 19 = 64

Escribir un programa que calcule el cubo de un numero natural dado, apli-cando el anterior metodo (no podra usarse ninguna funcion de la bibliotecacmath).

Entrada: 4Salida: 64

4. [quebrado] Dada una fraccion expresada como numerador y denominador,se desea reducirla a su forma canonica, es decir, de forma que el numeradory el denominador sean primos relativos.

Entrada: 100 25Salida: 4 1

Entrada: 56 32Salida: 7 4

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 386: Fundamentos de Programacion

5. [adn] Un laboratorio de analisis genetico ha descubierto una secuencia enlos genes (ACGTAAATTGGCAA...) que predispone a una enfermedad he-reditaria y que se identifica como “AGA” siempre que no vaya seguida in-mediatamente de una secuencia inhibidora identificada como “TT”. Se pideconstruir un programa que lea una secuencia genetica (terminada con elcaracter ’.’) y nos diga si tiene esa predisposicion o no.

En este ejercicio no puede emplearse la biblioteca cstring

Entrada: ACGTAAATTGAGATTGCAA.Salida: NO

Entrada: ACGTAAATTGAGAATTGCAA.Salida: SI

6. [feliz] Se dice que un numero natural es feliz si cumple que si sumamos loscuadrados de sus dıgitos y seguimos el proceso con los resultados obtenidos,finalmente obtenemos uno (1) como resultado. Por ejemplo, el numero 203es un numero feliz ya que 22+02+32 = 13 → 12+32 = 10 → 12+02 = 1.Se dice que un numero es feliz de grado k si se ha podido demostrar quees feliz en un maximo de k iteraciones. Se entiende que una iteracion seproduce cada vez que se elevan al cuadrado los dıgitos del valor actual y sesuman. En el ejemplo anterior, 203 es un numero feliz de grado 3 (ademas,es feliz de cualquier grado mayor o igual que 3). Otros ejemplos de numerosfelices son:

7 es feliz con cualquier valor de k mayor o igual a 5.

404 es feliz con cualquier valor de k mayor o igual a 4.

383 es feliz con cualquier valor de k mayor o igual a 4.

Ejemplos de numeros no felices para cualquier valor de k: 4, 37, 58, 113

Se pide lo siguiente:

Leer un valor entero n que representara el valor que queremos com-probar si es feliz o no.

Leer un valor entero Gradok que representara el numero maximo deiteraciones que vamos a permitir.

El programa nos dira si n es un numero feliz de grado Gradok. La salidasera SI en el caso afirmativo y NO en caso contrario.

Entrada: 7 6Salida: SI

Entrada: 4 8Salida: NO

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 387: Fundamentos de Programacion

7. [raiz] Escribir un programa para calcular la raız enesima de un numero realX mediante el metodo de biseccion con una precision deseada expresadacomo un numero real ε (p.e. 0.001). Para ello se propone examinar el inter-valo [1, X] y comprobar si alguno de los dos valores extremos del mismo,elevados a n coincide con X (aceptando un error de precision dado por ε),en cuyo caso se habrıa terminado. En caso contrario, habrıa que dividir elintervalo en dos partes tomando un punto central y elegir un subintervaloen funcion de si el punto central elevado a n es mayor o menor que X. Elprograma termina cuando uno de los extremos elevado a n coincide con X(aceptando un error de precision dado por ε), en cuyo caso se muestra dichoextremo, o cuando la amplitud del intervalo sea menor que la precision ε,en cuyo caso se muestra el punto medio del intervalo. Se aconseja utilizarla funcion pow de la biblioteca cmath (pow(x, y) = xy).

Entrada(raız cuadrada de 4 con precision de 0.00001): 4 2 0.00001Salida: 2

Entrada(raız cuarta de 123 con precision de 0.00001): 123 4 0.00001Salida: 3.33025

8. [secuencia] Escribir un programa que lea una secuencia de numeros enterosen el rango de 0 a 100 terminada en un numero mayor que 100 o menor que0 y encuentre la subsecuencia de numeros ordenada, de menor a mayor, demayor longitud, dentro dicha secuencia. El programa dara como salida laposicion donde comienza la subsecuencia y a continuacion su longitud. Enel siguiente ejemplo, la mayor secuencia creciente es 7 40 45 45 73 73que empezo en la posicion 3 y tiene una longitud de 6.

Entrada: 23 25 7 40 45 45 73 73 71 4 9 101Salida: 3 6

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 388: Fundamentos de Programacion

FUNDAMENTOS DE PROGRAMACIONEXAMEN PRACTICO II

(Enero 2012)

Normas generales!Importante! No se corregira ningun examen que no cumpla escrupulosamentelas normas que aparecen a continuacion:

1. El examen consiste en la realizacion de un programa que resuelva el proble-ma que se describe en las siguientes paginas. La resolucion del problema seimplementara en ISO C++98.

2. En la pagina web de la asignatura se encuentran ficheros de validacion quecontienen datos para validar nuestros programas. Su uso nos permite que,en lugar de introducir los datos por teclado, se carguen de un fichero, conlo que la prueba de los programas es mas rapida. Recordemos que para leerlos datos de un fichero hay que ejecutar el programa desde una consola desistema y redirigir la entrada de datos en la forma: problema.exe <validacion.txt, donde validacion.txt es el nombre del ficherode validacion.

Si usa Visual Studio, tambien puede ejecutarlo y depurarlo desde el mismoentorno, indicando el nombre del fichero de entrada y el directorio en el quese encuentra. Para ello, hay que seleccionar:

Proyecto/Propiedades de ....

Propiedades de Configuracion/Depuracion

Argumentos del comando/Editar/

En esta casilla hay que introducir el caracter < seguido del nombre delfichero de validacion.

Indicaremos la carpeta en la que se encuentra el fichero de validacion, atraves de la opcion siguiente:

Proyecto/Propiedades de ....

Propiedades de Configuracion/Depuracion

Directorio de trabajo/

3. Debe incluir la descripcion de los algoritmos implementados.

4. Muy Importante: Para poder realizar una baterıa automatica de valida-ciones, en el programa no deben etiquetarse las entradas de datos con in-strucciones cout del tipoPor favor, introduzca datos. Las unicas sentencias cout queel programa contendra seran las correspondientes a la salida del programa,indicada explıcitamente en el enunciado de cada ejercicio.

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 389: Fundamentos de Programacion

5. En la evaluacion de las practicas se tendra en cuenta, ademas de la cor-reccion de la solucion propuesta, el estilo de programacion, la claridad delcodigo y la calidad del diseno utilizado.

6. El fichero debe llamarse obligatoriamente problema2.cpp.

Tiempo de examen: 1 HORA Y 20 MINUTOS

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 390: Fundamentos de Programacion

1. [similitud] Vamos a definir una medida de similitud entre dos matrices decaracteres cuadradas n× n, M1 y M2, de la siguiente forma:

S(M1,M2) = cI + cP ,

donde cI es el numero de caracteres que estan a la vez en M1 y en M2 (esdecir |M1 ∩M2|) y cP es el numero de posiciones (i, j) (i = 0, · · · , n− 1 yj = 0, · · · , n−1) en las queM1 yM2 tienen el mismo caracter. Por ejemplo,dadas las siguientes matrices:

M1 =x wz k M2 =

z wq f

entonces S(M1,M2) = 2 + 1 = 3, ya que tienen dos caracteres en comun(z y w) y una posicion (i = 0 y j = 1) en la que ambas matrices tienen elmismo caracter (w).

Realizar un programa que dadas dos matrices cuadradas de caracteres, An× n y B m×m con m ≥ n, determine la posicion de comienzo, (ic, jc),de la submatriz n × n de B que tiene mayor similitud con A. Por ejemplo,dadas las siguientes matrices A y B, respectivamente:

a bc d

a b c be f a dc d e fh i a b

la submatriz deB con mayor similitud conA comienza en la posicion (0, 2)(cI = 4 y cP = 2).

Los datos de entrada al programa se deben dar en el siguiente orden: valorde n, datos de la matriz A (primero la fila 0, luego la fila 1, etc.), valor de my datos de la matriz B.

Restricciones del problema:

Debe implementar una clase “MatrizCuadrada”. Dicha clase debe in-corporar la funcionalidad necesaria para resolver el problema.

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 391: Fundamentos de Programacion

No se admitira que la entrada o la salida de datos se realicen dentrode la clase que incorpora la funcionalidad para resolver este problema.Esas operaciones se resolveran fuera de la clase.

Ejemplo de fichero de validacion:2a bc d4a b c be f a dc d e fh i a b

Salida del programa: (ic, jc).

0 2

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 392: Fundamentos de Programacion

2. [MatrizSerie] Desarrolle un programa para sumar aquellos valores Mij deuna matriz rectangular n×m de enteros M (todas las filas tienen el mismonumero de columnas) que verifiquen que i + j (i = 0, · · · , n − 1 y j =0, · · · ,m− 1) sea igual a:

k∑h=1

h2,

para algun valor de k ≥ 1. Por ejemplo, dada la siguiente matriz:

1 5 32 53 22 8 45 0 10 91 20 17 8

16 11 0 2

entonces esta suma serıa 5(0, 1)+3(1, 0)+9(2, 3)+17(3, 2)+11(4, 1) = 45.

Los datos de entrada al programa se deben dar en el siguiente orden: numerode filas, numero de columnas y datos de la matriz (primero la fila 0, luegola fila 1, etc.).

Restricciones del problema:

a) Debe implementar una clase “MatrizRectangular”. Dicha clase debeincorporar la funcionalidad necesaria para resolver el problema.

b) No se admitira que la entrada o la salida de datos se realice dentro dela clase que incorpora la funcionalidad para resolver este problema.Esas operaciones se resolveran fuera de la clase.

Ejemplo de fichero de validacion:5 41 5 32 53 22 8 45 0 10 91 20 17 816 11 0 2

Salida del programa: La suma de los elementos de la matriz que cumplenla restriccion especificada.45

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 393: Fundamentos de Programacion

3. [subcadena] Desarrolle un programa para localizar una cadena de carac-teres dentro de otra. El programa leera dos cadenas desde la entrada estandar,buscara la primera en la segunda, y escribira en la salida estandar la posi-cion donde se encuentra (en caso de encontrarla) o un mensaje indicandoque no se ha localizado.

Un ejemplo es el siguiente:

Cadena 1: mundo.Cadena 2: Hola mumumundo.Salida: 5

Tenga en cuenta que no podra usar ningun metodo de la clase string salvoel acceso a cada uno de los caracteres de las cadenas y al tamano de lascadenas. En particular, no se puede utilizar el metodo find.

El programa debe leer una entrada con el siguiente formato:

a) (Cadena 1). Una primera cadena de caracteres de caracteres que final-iza con el caracter ’.’ (punto).

b) (Cadena 2). Otra cadena con las mismas caracterısticas que la primera.

Restricciones del problema:

a) Debe implementar una clase “CadenaCaracteres”. Dicha clase debeincorporar la funcionalidad necesaria para resolver el problema.

b) No se permite declarar vectores fuera de la clase.

c) Para poder leer caracter a caracter incluidos los espacios en blanco,debe realizar la lectura en la forma caracter = cin.get(). Ca-da vez que se ejecute cin.get() el compilador lee un caracter (in-cluido el espacio en blanco) desde la entrada de datos por defecto.

d) No se admitira que la entrada o la salida de datos se realice dentro dela clase que incorpora la funcionalidad para resolver este problema.Esas operaciones se resolveran fuera de la clase.

Ejemplo de fichero de validacion:mundo.Hola mumumundo.

Salida del programa: La posicion de comienzo de Cadena 1 en Cadena 2si se encuentra.5En el caso de que Cadena 1 no se encuentre en Cadena 2 se imprimira elmensaje NO ESTA

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 394: Fundamentos de Programacion

4. [clasificador] Un clasificador asigna una etiqueta a una entidad, y esa eti-queta lo hace miembro de una categorıa. Una entidad que va a ser etique-tada se modeliza mediante los valores de una serie de rasgos. Por ejemplo,si las entidades a etiquetar son personas, cada persona podrıa representarsemediante los valores de los rasgos altura y peso.

Escribir un programa que etiquete un conjunto de datos n dimensionalesusando dos categorıas: (A y B) empleando un criterio de mınima distancia.

El programa recibira, por este orden cuatro numeros enteros: el numero derasgos (n), el numero de ejemplos de la categorıa A, el numero de ejemplosde la categorıa B, y el numero de entidades a etiquetar. A continuacionrecibira, en orden, los ejemplos A, los ejemplos de B y las entidades aetiquetar.

La regla que se empleara para etiquetar una entidad X consiste en asignar aX la etiqueta de la categorıa mas cercana. En lugar de medir la distancia deuna entidad a una categorıa, se escoge un representante de cada categorıay se mide la distancia entre la entidad a etiquetar y el representante de lacategorıa.Un representante poco discutido es la media: el representante medio de lacategorıa c, al que llamaremos µc tiene n rasgos y cada uno de ellos, µc

i (i =1, 2, . . . , n) es el valor medio del rasgo i, que se calcula como se indica en laecuacion 1, usando los Nc ejemplos de la categorıa c (a los que llamaremosc1, c2, . . . , cNc).

µci =

Nc∑k=1

cki (1)

Entonces, una vez calculados los representantes de las categorıas, puedecalcularse la etiqueta de cada entidad X como se indica en la ecuacion 2:

Etiqueta(X) =

{A si D(X,µA) ≤ D(X,µB)B si D(X,µA) > D(X,µB)

(2)

donde la distancia D se calcula:

D(X,µc) =n∑

i=1

(Xi − µci)

2 (3)

donde el subındice i hace referencia, de nuevo, al rasgo i-esimo.

En lıneas generales el programa:

a) Leera y almacenara todos los datos (ejemplos, entidades a etiquetar yrepresentantes) en memoria.

b) Calculara µA y µB usando los ejemplos proporcionados.

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 395: Fundamentos de Programacion

c) Para cada entidad a etiquetar X calculara D2(X,µA) y D2(X,µB) ymostrara X y la etiqueta asignada.

Restricciones del problema:

a) El programa debe guardar en memoria todos los ejemplos y entidades.Supondremos que los rasgos estan cuantificados por valores numericosde tipo double, para mayor generalidad.

b) Emplear, al menos, la clase “Clasificador” y dotarla de la funcionali-dad necesaria.

c) No se admitira que la entrada o la salida de datos se realice dentro dela clase que incorpora la funcionalidad para resolver este problema.Esas operaciones se resolveran fuera de la clase.

Ejemplo de fichero de validacion:3 5 4 60 -1 -2

-2 -2 -11 0 00 2 1

-1 1 06 5 54 7 46 6 55 4 61 1 1

-3 -2 08 7 2

10 15 8-6 -3 04 4 4

Salida del programa: media de las categorıas, las entidades clasificadas yla etiqueta asignada a cada una.

-0.40 0.00 -0.40 A5.25 5.50 5.00 B

1 1 1 A-3 -2 0 A8 7 2 B

10 15 8 B-6 -3 0 A4 4 4 B

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 396: Fundamentos de Programacion

5. [limpia] Escribir un programa que lea un texto y elimine todos los espaciosque contiene.

El usuario introducira el texto original por la entrada estandar de una man-era natural: escribira una serie de lıneas (terminadas todas ellas con la pul-sacion de la tecla ENTER) y finalizara la entrada de texto con una lıneavacıa (pulsando unicamente ENTER). Entonces el programa mostrara en lasalida estandar el mismo texto introducido, lınea a lınea, pero sin espacios.

Restricciones del problema:

a) No puede emplearse la clase string

b) Para la lectura del texto se empleara la estrategia de leer cacracter acaracter, de la forma caracter = cin.get(). Cada vez que seejecuta cin.get() se lee de la entrada estandar un solo caracter(incluıdo el espacio en blanco y el salto de lınea) y el caracter leıdo esdevuelto.

Debera implementarse, al menos, la clase “Texto”, que modeliza una colec-cion de vectores de caracteres. Los caracteres introducidos se guardaran enun objeto de esta clase y todo el procesamiento se realizara sobre este ob-jeto. No se admitira que la entrada o la salida de datos se realice dentro dela clase que incorpora la funcionalidad para resolver este problema. Esasoperaciones se resolveran fuera de la clase.

Ejemplo de fichero de validacion:En un lugar de la Mancha de cuyo nombre[ENTER]

no quiero acordarme, [ENTER]no ha mucho tiempo que vivıa [ENTER]un hidalgo de los de lanza [ENTER]

en astillero, [ENTER]adarga antigua, rocın flaco y [ENTER]galgo corredor. [ENTER][ENTER]

Salida del programa: El texto introducido sin espacios:

EnunlugardelaManchadecuyonombre[ENTER]noquieroacordarme,[ENTER]nohamuchotiempoquevivıa[ENTER]unhidalgodelosdelanza[ENTER]enastillero,[ENTER]adargaantigua,rocınflacoy[ENTER]galgocorredor.[ENTER][ENTER]

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 397: Fundamentos de Programacion

6. [liga] Escribir un programa que lea los resultados de los partidos disputadosen una liga y presente ordenadamente la clasificacion final, en base a lospuntos obtenidos por los equipos participantes.

Si la liga consta de N equipos, y se juega a dos vueltas, cada vuelta tieneN − 1 jornadas, por lo que en toda la liga se disputaran 2 (N − 1) jornadasy en total se jugaran N (N − 1) partidos, de manera que cada pareja deequipos se enfrenta dos veces. Las puntuaciones se asignan de la maneratradicional: en caso de empate, 1 punto para cada equipo, y en otro caso, 3puntos al ganador y 0 al perdedor.

El programa recibira el numero de equipos que forman la liga (N ) y a con-tinuacion los resultados de los N (N − 1) partidos. Cada resultado se ex-presa como una pareja de enteros que indican los goles marcados y encaja-dos, tomando como referencia al equipo local. Cada equipo juega contra losdemas una vez como local y otra como visitante. Por comodidad, los dosresultados entre cualquiera pareja de equipos se indican de manera consec-utiva en la misma lınea.

Implementar, al menos, la clase “Liga” y dotarla de la funcionalidad nece-saria.

Ejemplo de fichero de validacion:40 2 4 13 1 1 04 2 1 10 0 0 02 1 0 03 0 0 2

El primer numero indica el numero de equipos: la liga esta formada por4 equipos. Los resultados de los 4 · 3 = 12 partidos se proporcionan en2 · (4− 1) = 6 lıneas de manera que reflejan los resultados que se escribenusualmente en tablas como la siguiente:

1 2 3 41 0-2 3-1 4-22 4-1 0-0 2-13 1-0 0-0 3-04 1-1 0-0 0-2

Salida del programa: Una lınea por cada equipo, indicando los puntosconseguidos, los goles a favor, en contra, y la diferencia total de goles, enorden decreciente de puntuacion:

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 398: Fundamentos de Programacion

Equipo 2 = 12 puntos, favor = 8, contra = 2, dif = 6Equipo 3 = 11 puntos, favor = 7, contra = 3, dif = 4Equipo 1 = 9 puntos, favor = 9, contra = 11, dif = -2Equipo 4 = 2 puntos, favor = 4, contra = 12, dif = -8

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 399: Fundamentos de Programacion

7. [permutacion] Una permutacion de un conjunto de enteros,C = {1, · · · , n},tiene l lecturas, si para leer sus elementos en orden creciente (de izquierdaa derecha) tenemos que recorrer la permutacion l veces. Por ejemplo, lasiguiente permutacion del conjunto {1, . . . , 9}:

4 9 1 8 2 5 3 6 7

necesita 4 lecturas. En la primera obtendrıamos 1, 2 y 3. En la segunda 4, 5,6 y 7. En la tercera 8. Y finalmente, en la cuarta 9.

Implementa un programa que lea un conjunto de enteros y que muestre elnumero de lecturas de dicha permutacion.

Los datos de entrada al programa se deben dar en el siguiente formato:

a) El cardinal n del conjunto C.

b) La permutacion: una secuencia de numeros enteros distintos entre 1 yn.

Restricciones del problema:

a) Debe implementar una clase “Permutacion”. Dicha clase debe incor-porar la funcionalidad necesaria para resolver el problema.

b) No se permite declarar vectores fuera de la clase “Permutacion”.

c) No se admitira que la entrada o la salida de datos se realice dentro dela clase que incorpora la funcionalidad para resolver este problema.Esas operaciones se resolveran fuera de la clase.

d) Observe que, por definicion, en un “conjunto” de numeros no existenelementos repetidos.

Ejemplo de fichero de validacion:94 9 1 8 2 5 3 6 7

Salida del programa: El numero de lecturas de la permutacion.4

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 400: Fundamentos de Programacion

8. [biblioteca] Se desea gestionar una biblioteca. Para cada libro, se desea al-macenar un identificador numerico (unico) y el ano de su publicacion unica-mente.

Debe construir un programa que lea una serie de datos de libros y que losmuestre ordenados por ano de publicacion (de menor a mayor). En el casode que haya varios libros de un mismo ano, se deben ordenar por el identi-ficador, pero esta vez de mayor a menor.

Por ejemplo, a continuacion tenemos una serie de parejas de numeros. Cadauna de ellas corresponde a un libro y es de la forma (identificador,ano):

{(5, 2006), (8, 2000), (30, 2001), (25, 2000), (11, 2005), (21, 2005), (7, 2005),

(63, 2006), (27, 2006)}

El resultado de la ordenacion de nuestro programa deberıa ser el siguiente:

{(25, 2000), (8, 2000), (30, 2001), (21, 2005), (11, 2005), (7, 2005), (63, 2006),

(27, 2006), (5, 2006)}

Los datos de entrada al programa se proporcionan con el siguiente formato:

a) Numero de libros.

b) Secuencia de pares con los identificadores y ano de publicacion.

Restricciones del problema:

a) Debe implementar una clase “Biblioteca”. Dicha clase debe incorporarla funcionalidad necesaria para resolver el problema.

b) No se permite declarar vectores fuera de la clase.

c) No se admitira que la entrada o la salida de datos se realice dentro dela clase que incorpora la funcionalidad para resolver este problema.Esas operaciones se resolveran fuera de la clase.

Ejemplo de fichero de validacion:95 20068 200030 200125 200011 200521 20057 200563 200627 2006

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 401: Fundamentos de Programacion

Salida del programa: Los libros ordenados segun el criterio anterior.

25 2000 8 2000 30 2001 21 2005 11 2005 7 2005 63 2006 27 2006 5 2006

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 402: Fundamentos de Programacion

9. [maximin] Se pide construir un programa que lea una matriz rectangular deenteros y que indique si existe algun elemento que sea maximo de su fila ymınimo de su columna a la vez. En caso afirmativo, el programa mostrara laposicion (fila y columna) de dicho elemento. Si existen varios podemos de-volver uno cualquiera. Si no hay ningun elemento que cumpla la condicionel programa mostrara la posicion -1 -1

Por ejemplo, dada la matriz M (3× 4),

4 9 5 52 18 2 27 13 2 5

el valor 9 que esta en la posicion (0, 1) es maximo de su fila y mınimo desu columna (podrıa haber mas).

Los datos de entrada al programa se deben dar en el siguiente orden:

a) Numero de filas de la matriz.

b) Numero de columnas de la matriz.

c) Los elementos de la matriz.

Restricciones del problema:

a) Debe implementar una clase “MatrizRectangular”. Dicha clase debeincorporar la funcionalidad necesaria para resolver el problema.

b) No se admitira que la entrada o la salida de datos se realice dentro dela clase que incorpora la funcionalidad para resolver este problema.Esas operaciones se resolveran fuera de la clase.

Ejemplo de fichero de validacion:344 9 5 52 18 2 27 13 2 5

Salida del programa: Dos enteros que representan la fila y columna delelemento buscado.0 1

C/ Periodista Daniel Saucedo Aranda s/n, ETSI Informatica, 18071 Granada, Tlf.: +34.958.244019, Fax: +34.958.243317

Page 403: Fundamentos de Programacion

Fundamentos de Programacion. Convocatoria de FebreroCurso 2010/20118 de Febrero de 2011

Tiempo: dos horas y media.IMPORTANTE: Los algoritmos han de ir correctamente explicados.

1. (2.5 puntos) El metodo de biseccion usado para calcular de forma aproximada el punto de corte de una funcionf con el eje de abscisas (la raız de la funcion) se puede enunciar como sigue:

Sea f(x) una funcion real, estrictamente monotona en [i, d], donde f(i) y f(d) tienen distinto signo y sea ε unaconstante real pequena (del orden de 10−4, por ejemplo).

a) Calcular m, el punto medio entre i y d,

b) Si |i− d| < ε, terminar.

c) Si f(m) tiene igual signo que f(i), repetir considerando el intervalo [m, d]

d) Si f(m) tiene igual signo que f(d), repetir considerando el intervalo [i,m]

Implemente una funcion recursiva que reciba como datos de entrada los extremos i, d del intervalo, ası comoel valor de ε y devuelva la raız de la funcion. Se supone que se dispone de la funcion f(x) ya implementada enC++.

2. (2 puntos) Desarrolle un programa para localizar una cadena dentro de otra. El programa leera dos cadenasdesde la entrada estandar, buscara la primera en la segunda, y escribira en la salida estandar la posicion dondese encuentra -en caso de encontrarla- o un mensaje indicando que no se ha localizado. Un ejemplo de ejecuciones el siguiente:

Introduzca la primera cadena: mundo

Introduzca la segunda cadena: Hola mumumundo

"mundo" Se encuentra en la posicion 5 de "Hola mundo"

Tenga en cuenta que no podra usar ningun metodo de la clase string salvo el acceso a cada uno de los caracteresde las cadenas y al tamano de las cadenas. En particular, no se puede utilizar el metodo find.

3. Defina la clase MatrizEnteros para poder trabajar con una matriz de enteros, de forma que todas las filastengan el mismo numero de columnas.

a) (0.25 puntos) Definir un metodo para anadir una fila completa y otro metodo para acceder a una componentei, j de la matriz.

b) (1.75 puntos) Definir un metodo para insertar una fila completa en una posicion (de fila) determinada. Porejemplo, 3 1 4 5 6

9 0 4 3 2? ? ? ? ?

→ Insertar(8, 5, 0, 1, 2)en la fila 1

3 1 4 5 68 5 0 1 29 0 4 3 2

donde ? representa un valor no utilizado. Se quiere que el modulo sea robusto, por lo que deben comprobarselas precondiciones pertinentes.

c) (1.5 puntos) Definir un metodo que construya y devuelva una matriz con los datos traspuestos de la primera,es decir,

matriz traspuestaij = matriz originalji

d) (2 puntos) Definir un metodo para sumar aquellos valores Mij de la matriz M que verifiquen que i+ j seaigual a:

k∑h=1

h2

para algun valor de k ≥ 1.

Page 404: Fundamentos de Programacion

Fundamentos de Programacion. Convocatoria de Septiembre. Curso 2010/2011

Recuperacion de la parte practica de Febrero (40 % de la nota final)Tiempo: una hora y media.IMPORTANTE: Los algoritmos han de ir correctamente explicados.

Se pide construir un programa que lea una matriz y que calcule la posicion de aquel elemento que sea el mayorde entre los mınimos de cada fila. El programa mostrara la posicion de dicho elemento (fila y columna). Por ejemplo,dada la matriz M (3 × 4),

9 7 4 52 18 2 127 9 1 5

el maximo entre 4, 2 y 1 (los mınimos de cada fila) es 4 que se encuentra en la posicion (0, 2). Los datos de entradaal programa se deben dar en el siguiente orden:

1. Numero de filas de la matriz.

2. Numero de columnas de la matriz.

3. Los elementos de la matriz.

Restricciones del problema:

1. Debe implementar una clase “Matriz”. Dicha clase debe incorporar la funcionalidad necesaria para resolver elproblema.

2. No se admitira que la entrada o la salida de datos se realice dentro de la clase que incorpora la funcionalidadpara resolver este problema. Esas operaciones se resolveran fuera de la clase.

Ejemplo de fichero de validacion:

3

4

9 7 4 5

2 18 2 12

7 9 1 5

Salida del programa: Dos enteros que representan la fila y columna del elemento buscado:0 2

Page 405: Fundamentos de Programacion

Fundamentos de Programacion. Convocatoria de Septiembre. Curso 2010/2011

Recuperacion de la parte escrita de Febrero (60 % de la nota final)Tiempo: dos horas y media.IMPORTANTE: Los algoritmos han de ir correctamente explicados.

1. (2 puntos) Definir una funcion recursiva a la que se le pasen dos valores de tipo int n y k y devuelva comoresultado la suma de todos los k dıgitos menos significativos de n. Por ejemplo para n = 61427 y k = 3 elresultado es 7 + 2 + 4 = 13, y para n = 23 y k = 4 el resultado es 2 + 3 = 5 .

2. Implemente la clase Texto para representar una coleccion de cadenas de caracteres (string). Esta clase debeimplementar la siguiente funcionalidad publica:

Bloque 1 (2 puntos). Tareas generales. Escribir metodos para: 1) consultar cuantas cadenas contiene, 2)obtener la cadena i-esima, 3) anadir una nueva cadena, 4) insertar una cadena en la posicion i-esima, y 5)eliminar la cadena i-esima. Para todas estas funciones, 0 ≤ i < n donde n es el numero actual de cadenas.

Bloque 2 (2 puntos). Tareas de “limpieza”. Escribir metodos para: 1) eliminar los “blancos” iniciales detodas las cadenas, 2) eliminar los “blancos” finales de todas las cadenas, y 3) eliminar los “blancos” iniciales yfinales de todas las cadenas.

Bloque 3 (2 puntos). Tareas de reorganizacion. Puede ser interesante reordenar las cadenas que componen lacoleccion en un momento dado. En lugar de los criterios clasicos (orden lexicografico, longitud, . . . ) proponemosemplear otro criterio, basado en lo que llamaremos ındice de ocupacion de una cadena. Un ındice de ocupaciones un numero real entre 0.0 y 1.0, que indica cuantas casillas de la cadena contienen espacios en blanco. El valor1.0 indica que no hay ninguna casilla en blanco y el valor 0.0 que todas son blancos. El alumno debe escribirun metodo que modifique el objeto Texto de manera que reorganice las cadenas de mayor a menor ındice deocupacion.

Notas:

a) En todos los casos se deberan comprobar y tratar las situaciones posibles de error.

b) Se pueden implementar tantos metodos/funciones como considere oportuno para conseguir la solucionoptima.

3. (2 puntos)

Desarrolle un programa que lea una secuencia de numeros enteros en el rango de 0 a 100 terminada en un numeromayor que 100 o menor que 0 y encuentre la subsecuencia de numeros creciente (ordenada de menor a mayor),de mayor longitud, dentro de dicha secuencia. Supondremos que dos valores iguales consecutivos forman parte dela misma subsecuencia creciente. El programa nos debe decir la posicion (empezando desde 1) donde comienzala subsecuencia y su longitud.

Entrada: 23 23 7 45 45 45 73 73 71 4 9 101Salida: POSICION = 3

LONGITUD = 6