Professional Documents
Culture Documents
Programming 2
4. Recommended methodology
5. Exercises
1
Algorithms and program design
How to make a program
2
Basic elements of C++
Identifiers
• Bad examples:
const int EIGHT=8;
int p,q,r,a,b;
int counter1,counter2; // More usual: int i,j;
3
Reserved words
Terminal
error: expected unqualified-id before '=' token
4
Variables > Definition and types
6
Variables > Scope (1/3)
if(i<10){
// numBoxes can be used here
int numBoxes=100; // Same name but different scope
cout << numBoxes << endl; // Output is 100
}
7
Variables > Scope (2/3)
• Global variable:
• A variable declared out of the function scope
• It is recommended not to use global variables (they are dangerous)
• In Programming 2 it is forbidden to use global variables
8
Variables > Scope (3/3)
void countDown(void){
while(counter>0){
cout << counter << " ";
counter--;
}
cout << endl;
}
int main(){
countDown();
countDown(); // Prints nothing
9
Constants
Types Examples
char → int int a='A'+2; // a is 67
int → float float pi=1+2.141592;
float → double double halfPi=pi/2.0;
bool → int int b=true; // b is 1
int → bool bool c=77212; // c is true
11
Data types > Conversion (2/2)
Terminal
warning: comparison between signed and unsigned integer...
12
Data types > Definition of new types
• In C++ names that appear after struct, class, and union are
also types
13
Increment and decrement operators
15
Arithmetic expressions (2/2)
• Operators precedence:*
*From highest to lower precedence. The operators of a row have the same precedence
16
Relational expressions
• Operands are grouped two by two from left to right: a < b < c
must be coded as a<b && b<c
• The result is 0 if the comparison is false and different from 0 if it
is true*
*In the GCC compiler it is 1, but the C++ standard does not impose this
17
Logical expressions
• Short-circuit evaluation:
• If the left operand of && is false, the right operand is not evaluated
(false && whatever is always false)
• If the left operand of || is true, the right operand is not evaluated
(true || whatever is always true)
18
Input and output
19
Flow control > if
20
Flow control > while
21
Flow control > do-while
22
Flow control > for
initialisation;
while(condition){
// Instructions
completion;
}
23
Flow control > switch (1/2)
switch(option){
case 'a': cout << "Option A" << endl;
break; // Exits the switch
case 'b': cout << "Option B" << endl;
break;
case 'c': cout << "Option C" << endl;
break;
default: cout << "Another option" << endl;
}
24
Flow control > switch (2/2)
25
Arrays and matrices (1/3)
26
Arrays and matrices (2/3)
28
Character arrays
"hello" → h e l l o \0
29
Functions > Definition (1/2)
instruction1;
instruction2;
...
return ret;
}
30
Functions > Definition (2/2)
31
Functions > Parameters (1/2)
33
Functions > Prototypes
char anotherFunction(){
double vr[20];
// myFunction has not yet been declared
// but we can use it thanks to the prototype
myFunction(true,'a',vr);
}
*Since it is a class, its methods are called by putting a point after the name of the variable
35
STL vectors (2/2)
• With clear we can delete all the elements and with erase a
specific one:
vec.erase(vec.begin()+3); // Deletes the fourth element
vec.clear(); // Deletes all the elements of the vector
36
Structures
• Fields are accessed indicating the name of the variable and the
field, separated by a period (member access operator):
Student a,b;
a.dni=123133; // Assignment to a field
b=a; // Assignment of a complete structure bit by bit
37
Enumerated types
• Variables of this type can take any value from this set of
enumerators:
colour myColour=blue;
if(myColour==green){
cout << "Green!" << endl;
}
38
Arguments (1/4)
39
Arguments (2/4)
40
Arguments (3/4)
• Example of use:
int main(int argc,char *argv[]){
for(int i=0;i<argc;i++){
cout << "Arg. " << i << " : " << argv[i] << endl;
}
}
Terminal
$ ./myProgram -a -h X // Example of call with three parameters
Arg. 0 : ./myProgram
Arg. 1 : -a
Arg. 2 : -h
Arg. 3 : X
41
Argument (4/4)
42
Structure of a program
43
Compilation and debugging
The compilation process
• Example of use:
Terminal
$ g++ -Wall -g prog.cc -o prog
*The complete list of arguments can be accessed by running man g++ on the Linux terminal
44
Debugging (1/2)
45
Debugging (2/2)
46
Recommended methodology
Recommended methodology for programming
47
Exercises
Exercises
Exercise 1
• -L print each number on a separate line (by default they are all
printed on the same line)
• -N n print the n first prime numbers (10 by default)
Execution examples:
Terminal
$ primes -N 5
1 2 3 5 7
$ primes -N -L 5
Error: primes [-L] [-N n]
48
Tema 2: La clase string
Programación 2
1. Cadenas de caracteres en C
3. Conversiones de tipos
4. Comparativa
5. Ejercicios
1
Cadenas de caracteres en C
Declaración (1/3)
*Como aquellas que pertenecen a la librería string.h y que veremos más adelante
2
Declaración (2/3)
3
Declaración (3/3)
4
Salida por pantalla
cout << cad << " -> " << num; // Muestra "Nota -> 10"
5
Entrada por teclado > Operador >> (1/2)
6
Entrada por teclado > Operador >> (2/2)
7
Entrada por teclado > getline (1/4)
Terminal
$ miPrograma
Cadena 1: hola a todo el mundo
Leído 1: hola a to
Cadena 2: Leído 2:
9
Entrada por teclado > getline (3/4)
Terminal
$ miPrograma
Num: 10
Escribe una cadena: Lo que he leído es:
10
Entrada por teclado > getline (4/4)
• Solución:
...
cin >> num;
cin.get(); // Añadimos esta línea
// Saca el '\n' del buffer
// Ya se puede usar getline sin problema
...
11
La librería string.h (1/2)
12
La librería string.h (2/2)
13
Conversión a int y float
char cad[]="100";
int num=atoi(cad); // num vale 100
char cad2[]="10.5";
float num2=atof(cad2); // num2 vale 10.5
14
La clase string en C++
Definición (1/2)
15
Definición (2/2)
16
Salida por pantalla
• Salida por pantalla con cout y cerr igual que con los vectores
de caracteres en C:
string s="Nota";
int num=10;
cout << s << " -> " << num; // Muestra "Nota -> 10"
17
Entrada por teclado > Operador >>
18
Entrada por teclado > getline (1/2)
19
Entrada por teclado > getline (2/2)
20
Extraer palabras de un string
21
Métodos de string (1/3)
22
Métodos de string (2/3)
23
Métodos de string (3/3)
• Ejemplo de uso:
string a="Hay una taza en esta cocina con tazas";
string b="taza";
unsigned int tam=a.length(); // Longitud de a
// Buscamos la primera palabra "taza"
size_t encontrado=a.find(b);
if(encontrado!=string::npos){
cout << "Primera en: " << encontrado << endl;
// Buscamos la segunda palabra "taza"
encontrado=a.find(b,encontrado+b.length());
if(encontrado!=string::npos)
cout << "Segunda en: " << encontrado << endl;
}
else{
cout << "Palabra '" << b << "' no encontrada";
}
// Sustituimos la primera "taza" por "botella"
a.replace(a.find(b),b.length(),"botella");
cout << a << endl;
24
Operadores (1/2)
25
Operadores (2/2)
*El método c_str devuelve un vector de caracteres en C con el contenido del string
27
Conversión entre string y número
ss << num;
s=ss.str(); // Convierte el stringstream a string
*Las funciones stoi y stof están disponibles a partir de la versión 2011 de C++ 28
Comparativa
Vector de caracteres en C vs. string
strlen(cad) s.length()
cin.getline(cad,TAM); getline(cin,s);
if(!strcmp(cad1,cad2)){...} if(s1==s2){...}
strcpy(cad1,cad2); s1=s2;
strcat(cad1,cad2); s1=s1+s2;
strcpy(cad,s.c_str()); s=cad;
29
Ejercicios
Ejercicios (1/4)
Ejercicio 1
Ejercicio 2
30
Ejercicios (2/4)
Ejercicio 3
buscarSubcadena("oool","hoooola") // Devuelve 2
Ampliaciones:
31
Ejercicios (3/4)
Ejercicio 4
32
Ejercicios (4/4)
Ejercicio 5
Ejercicio 6
33
Tema 3: Ficheros
Programación 2
1. Introducción
2. Ficheros de texto
3. Ficheros binarios
1
Introducción
Qué es un fichero (1/3)
• Todos los datos con los que hemos trabajado hasta ahora se
almacenan en la memoria principal del ordenador (RAM)
• El tamaño de la memoria principal es bastante limitado (unos
pocos Gigabytes)
• Todos los datos se borran cuando el programa termina (memoria
volátil)
2
Qué es un fichero (2/3)
3
Qué es un fichero (3/3)
4
Ficheros de texto
Definición (1/2)
5
Definición (2/2)
6
Declaración de variables
7
Apertura y cierre (1/4)
8
Apertura y cierre (2/4)
ifstream ficheroLec;
ofstream ficheroEsc;
// Abrimos solo para leer
ficheroLec.open("miFichero.txt",ios::in);
// Abrimos para añadir información al final
ficheroEsc.open("miFichero.txt",ios::out|ios::app);
9
Apertura y cierre (3/4)
10
Apertura y cierre (4/4)
11
Lectura con el operador >> (1/3)
12
Lectura con el operador >> (2/3)
13
Lectura con el operador >> (3/3)
14
Lectura por líneas
15
Detección de final de fichero
16
Escritura con el operador <<
17
Ejercicios (1/6)
Ejercicio 1
18
Ejercicios (2/6)
Ejercicio 2
Ejemplo:
fichero.txt FICHERO.TXT
Hola, mundo. HOLA, MUNDO.
Como estamos? COMO ESTAMOS?
Adios, adios... ADIOS, ADIOS...
19
Ejercicios (3/6)
Ejercicio 3
Ejemplo:
f1.txt f2.txt
hola, mundo. hola, mundo.
como estamos? como vamos?
adios, adios... adios, adios...
Ejercicio 4
Ejemplo:
finFichero(3,"cadenas.txt")
21
Ejercicios (5/6)
Ejercicio 4 (continuación)
22
Ejercicios (6/6)
Ejercicio 5
Ejemplo:
23
Ficheros binarios
Definición (1/2)
24
Definición (2/2)
25
Declaración de variables
26
Apertura y cierre
27
Lectura (1/3)
fichero.open("miFichero.dat",ios::in | ios::binary);
if(fichero.is_open()){
// En cada iteración leemos un registro TAlumno
while (fichero.read((char *)&alumno, sizeof(TAlumno))){
// Mostramos el nombre y la nota de cada alumno
cout << alumno.nombre << ": " << alumno.nota << endl;
}
fichero.close();
}
*Para saber el número de bytes que ocupa una variable se puede usar la función sizeof
28
Lectura (2/3)
29
Lectura (3/3)
30
Escritura (1/3)
if(fichero.is_open())
{
strcpy(alumno.nombre,"Pepe Pi");
alumno.notaMedia=7.8;
alumno.grupo=5;
31
Escritura (2/3)
32
Escritura (3/3)
33
Posición actual
34
Ejercicios (1/3)
Ejercicio 6
35
Ejercicios (2/3)
Ejercicio 7
Ejercicio 8
36
Ejercicios (3/3)
Ejercicio 9
37
TEMA 7: Ficheros
TEMA 7: Ficheros
7.1.-Concepto de fichero
Todas las estructuras de datos que hemos visto hasta ahora utilizan memoria principal.
Esto tiene dos limitaciones importantes:
1. Los datos desaparecen cuando el programa termina.
2. La cantidad de los datos no puede ser muy grande debido a la limitación de la
memoria principal.
Por eso existen también estructuras especiales que utilizan memoria secundaria: los
ficheros.
El fichero es además una estructura dinámica, en el sentido de que su tamaño puede
variar durante la ejecución del programa dependiendo de la cantidad de datos que tenga.
7.2.-Tipos de acceso
Al estar en memoria secundaria, no todos los elementos del fichero son accesibles de
forma inmediata. Solamente se puede acceder cada vez a un único elemento del fichero,
que se denomina ventana del fichero.
Ejemplo:
ofstream f;
Esta sentencia nos declara una variable (fichero lógico) de tipo fichero de
salida.
Pero esta variable, para que nos sea de utilidad tiene que estar asociada con un fichero
"real", es decir, por un fichero reconocido por el sistema operativo (por ej.
"datos.txt") puesto que al final será el sistema operativo quien realice la escritura o
lectura de ese fichero. Este fichero es lo que se denomina fichero físico.
Para relacionar el fichero lógico con el fichero físico necesitamos realizar una operación
de apertura del fichero.
En C++ esta operación se realiza con la instrucción open:
nombre_fichero_logico.open (nombre_fichero_fisico);
Ejemplo:
f.open("datos.txt");
7.5.-Procesamiento de un fichero
Siempre que queramos realizar cualquier operación con ficheros se debe seguir el
siguiente esquema:
Apertura de Fichero → Operaciones → Cierre del fichero
Ejemplo:
f.open("datos.txt", ios::app);
Para saber si la apertura del fichero ha dado error se utiliza el operador ! aplicado al
fichero:
Ejemplo:
if (!f)
cout << "Error abriendo el fichero" << endl;
Esta condición se debe poner siempre que abramos un fichero, puesto que si ha habido
un error, no se podrá realizar ninguna operación con él.
7.5.2.-Operaciones:
Las operaciones que se pueden realizar sobre un fichero son exactamente las mismas
que se pueden realizar sobre cin (para ficheros de entrada) y cout (para ficheros de
salida). De hecho cin y cout son ficheros predefinidos, que están asociados con la
entrada estándar y la salida estándar del sistema operativo.
Ejemplo:
Cuando se han acabado de realizar todas las operaciones, SIEMPRE hay que cerrar el
fichero. Esta operación destruye las estructuras que se han creado para abrirlo (tanto del
programa como del sistema operativo). También actualiza totalmente el fichero,
escribiendo toda la información que pudiera quedar en el buffer (normalmente la
información pasa a través de un buffer).
Para cerrar el fichero se utiliza la instrucción close:
nombre_fichero_logico.close ();
Ejemplo:
f.close();
#include<fstream.h>
int main()
{
ofstream f;
int i;
Ejemplo: Programa para leer los 10 números del fichero y mostrarlos por pantalla.
#include<fstream.h>
#include<iostream.h>
int main()
{
ifstream f;
int i, dato;
f.open("datos.txt");
if(!f)
cout << "Error abriendo el fichero" << endl;
else
{
for(i = 1; i <= 10; i++)
{
f >> dato;
cout << dato << endl;
}
f.close();
}
return 0;
}
Sin embargo, lo normal es que no sepamos cuantos elementos vamos a leer, sino que
queremos leer hasta que lleguemos al final del fichero. Para ello se puede utilizar un
bucle while de la siguiente forma:
while (f >> dato)
cout << dato << endl;
Cuando una instrucción para leer de fichero acaba con éxito, devuelve cierto, y cuando
se produce algún tipo de error (entre los que se incluye llegar al final del fichero),
devuelve falso. De esta forma, la instrucción anterior leerá, mientras sea posible, todos
los números del fichero.
Ejemplo: Programa para leer los números de un fichero y mostrarlos por pantalla.
#include<fstream.h>
#include<iostream.h>
int main()
{
ifstream f;
int dato;
f.open("datos.txt");
if(!f)
cout << "Error abriendo el fichero" << endl;
else
{
while(f >> dato)
cout << dato << endl;
f.close();
}
return 0;
}
Esta forma de leer del fichero se puede utilizar con cualquier tipo de lectura con >> y
también con getline.
Si queremos leer el fichero carácter a carácter, lo más normal será utilizar el método
get(), sin embargo éste no devuelve cierto o falso para saber si se ha podido leer con
éxito, puesto que tiene que devolver el carácter que ha leído. La forma de leer un
fichero con get() será por tanto ligeramente distinta a la que hemos visto.
#include<fstream.h>
#include<iostream.h>
int main()
{
ifstream f;
char dato;
f.open("datos.txt");
if(!f)
cout << "Error abriendo el fichero" << endl;
else
{
dato = f.get();
while(! f.eof())
{
cout << dato << endl;
dato = f.get();
}
f.close();
}
return 0;
}
El método eof() es cierto si el dato que hemos leído era un final de fichero y falso en
caso contrario. Por esta razón hay que leer primero el carácter y después comprobar si
hemos llegado a final de fichero.
7.5.5.-Lectura de estructuras
Cuando queremos leer datos simples de un fichero, se puede realizar fácilmente
introduciendo la lectura dentro de la condición de un bucle while. Sin embargo, para
leer una estructura se deben leer primero cada uno de sus campos antes de considerar la
lectura correcta, por lo que para poder efectuar la lectura en la condición del while,
habrá que definir una función que realice dicha lectura y devuelva true si se ha podido
realizar sin errores y false en caso contrario.
Ejemplo:
#include<fstream.h>
#include<iostream.h>
struct Telefono
{
string nombre;
string telefono;
};
int main(void)
{
Telefono tel;
ifstream guia;
guia.open("guia.dat");
if(!guia)
cout << "Error abriendo el fichero" << endl;
else
{
while (F_IntroTel(guia, tel) )
{
EscribeTel(tel);
cout << endl;
}
guia.close();
}
return 0;
}
Por último conviene indicar que los ficheros se han de pasar siempre como parámetros
por referencia, no importa si los vamos a modificar o no. En la función anterior
F_IntroTel se puede ver un ejemplo.
7.6.-Acceso directo
Consiste en poder mover la ventana del fichero a la posición del fichero que queramos,
sin necesidad de leer todas las anteriores. En C++ la ventana del fichero corresponde
únicamente a un carácter y se mueve carácter a carácter, por tanto la posición
Ejemplo:
Fichero f
HOLA\n
PEPE\n
Carácter en la posición 0: H
Carácter en la posición 3: A
Carácter en la posición 6: P (en DOS o WINDOWS)1
Para ofstream:
nombre_fichero_logico.seekp(pos)
nombre_fichero_logico.tellp()
Ejemplo:
// Colocar la ventana del fichero al principio del fichero
f.seekg(0);
1
En el sistema operativo Windows, el salto de línea se escribe en fichero utilizando 2 caracteres,
concretamente los correspondientes a los códigos 13 y 10.
#include<fstream.h>
#include<iostream.h>
int main()
{
ifstream f;
int dato;
f.open("datos.bin");
if(!f)
cout << "Error abriendo el fichero" << endl;
else
{
while(f.read((char *)(& dato), sizeof(dato) ) )
cout << dato << endl;
f.close();
}
return 0;
}
#include<fstream.h>
#include<iostream.h>
int main()
{
ofstream f;
int i;
f.open("datos.bin");
if(!f)
cout << "Error abriendo el fichero" << endl;
else
{
for(i = 1; i <= 10; i++)
f.write((char *)(& i), sizeof(i) );
f.close();
}
return 0;
}
1. Organización de la memoria
2. Punteros
3. Uso de punteros
4. Referencias
1
Organización de la memoria
Memoria estática
2
Memoria dinámica
3
Zonas de la memoria
4
Punteros
Definición y declaración
5
Operadores de punteros (1/2)
6
Operadores de punteros (2/2)
7
Declaración con inicialización
8
Ejercicios
Ejercicio 1
Indica cuál sería la salida por pantalla de estos fragmentos de código:
int e1;
int *p1,*p2;
e1=7;
p1=&e1;
p2=p1;
e1++;
(*p2)+=e1;
cout << *p1;
int a=7;
int *p=&a;
int **pp=&p;
cout << **pp;
9
Uso de punteros
Reserva y liberación de memoria (1/2)
pd
2000 4.75
1000 1002 … 2000 2002
10
Reserva y liberación de memoria (2/2)
• Siempre que se reserva con new hay que liberar con delete
• Un puntero se puede reutilizar tras liberar su contenido y
reservar memoria otra vez con new:
double *pd;
pd=new double; // Reserva memoria
...
delete pd; // Libera la memoria apuntada por pd
pd=new double; // Reservamos de nuevo memoria
...
11
Punteros y arrays (1/3)
12
Punteros y arrays (2/3)
13
Punteros y arrays (3/3)
14
Punteros definidos con typedef
15
Punteros a registros
tPunteroRegistro pr;
pr=new tRegistro;
pr->c='a'; // Equivalente a (*pr).c='a';
pr->i=88; // Equivalente a (*pr).i=88;
16
Punteros como parámetros de funciones (1/2)
17
Punteros como parámetros de funciones (2/2)
18
Errores comunes (1/2)
19
Errores comunes (2/2)
20
Ejercicios
Ejercicio 2
Dado el siguiente registro:
struct tCliente{
char nombre[32];
int edad;
}tCliente;
21
Referencias
Referencias (1/4)
22
Referencias (2/4)
23
Referencias (3/4)
int main(){
int a=10,b=20;
swap(&a,&b);
cout << a << " " << b; // Muestra "20 10"
}
24
Referencias (4/4)
int main(){
int a=10,b=20;
swap(a,b);
cout << a << " " << b; // Muestra "20 10"
}
25
Implementación de una pila
Implementación de una pila (1/6)
26
Implementación de una pila (2/6)
27
Implementación de una pila (3/6)
28
Implementación de una pila (4/6)
29
Implementación de una pila (5/6)
31
Tema 5: Introducción a la programación
orientada a objetos
Programación 2
1. Introducción
2. Conceptos básicos
3. POO en C++
5. Relaciones
6. Compilación
7. Ejercicios
1
Introducción
Definición
2
Clases y objetos (1/4)
3
Clases y objetos (2/4)
4
Clases y objetos (3/4)
*Decimos que es “cutre” porque no ofrece ninguna ventaja con respecto a struct Fecha
5
Clases y objetos (4/4)
6
Conceptos básicos
Conceptos básicos
7
Abstracción
8
Encapsulación
9
Modularidad (1/2)
10
Modularidad (2/2)
11
Herencia (1/2)
Mamífero
Perro Gato
12
Herencia (2/2)
13
Polimorfismo
14
POO en C++
Declaración e implementación (1/2)
15
Declaración e implementación (2/2)
SpaceShip::~SpaceShip(){} // Destructor
16
Diagrama UML (1/3)
Rect
- x1 : int
- x2 : int
- y1 : int
- y2 : int
+ Rect(ax : int, ay : int, bx : int, by : int)
+ ~Rect()
+ base() : int
+ altura() : int
+ area() : int
17
Diagrama UML (2/3)
18
Diagrama UML (3/3)
19
Accesores
Fecha
- dia : int
- mes : int
- anyo : int
+ getDia () : int
+ getMes () : int
+ getAnyo() : int
+ setDia (d : int) : void
+ setMes (m : int) : void
+ setAnyo (a : int) : void
+ isBisiesto () : bool
• Los accesores set nos permiten controlar que los valores de los
atributos sean correctos
20
Forma canónica
21
Constructor (1/6)
22
Constructor (2/6)
• Ejemplos de constructor:
Fecha::Fecha(){ // Sin parámetros
dia=1;
mes=1;
anyo=1900;
}
• Llamadas al constructor:
Fecha f;
Fecha f(10,2,2010);
Fecha f(); // ¡Error de compilación!
23
Constructor (3/6)
24
Constructor (4/6)
25
Constructor (5/6)
int main(){
try{ // Intentamos ejecutar estas instrucciones
int result=root(-1); // Provoca una excepción
cout << result << endl; // Esta línea no se ejecuta
}
catch(...){ // Si hay una excepción la capturamos aquí
cout << "Negative number" << endl;
}
}
26
Constructor (6/6)
int main(){
try{
Coordenada c(-2,4); // Este objeto no llega a crearse
}
catch(...){
cout << "Coordenada incorrecta" << endl;
}
}
27
Destructor (1/2)
28
Destructor (2/2)
29
Constructor de copia (1/2)
// Implementación
Fecha::Fecha(const Fecha &f){
dia=f.dia;
mes=f.mes;
anyo=f.anyo;
}
30
Constructor de copia (2/2)
31
Operador de asignación
32
Declaraciones inline (1/2)
33
Declaraciones inline (2/2)
34
Métodos constantes (1/2)
Línea
- cantidad: int
- precio: float
- descripcion: string
+ Linea()
+ <<const>> getSubtotal(): float
+ <<const>> getCantidad(): int
+ <<const>> getPrecio(): float
+ <<const>> getDescripcion(): string
+ setCantidad(cant: int): void
+ setPrecio(precio: float): void
+ setDescripcion(descripcion: string): void
36
Funciones amigas
37
Sobrecarga de la entrada/salida (1/4)
38
Sobrecarga de la entrada/salida (2/4)
• Declaración:
class Fecha{
friend ostream& operator<<(ostream &os,const Fecha &f);
friend istream& operator>>(istream &is,Fecha &f);
public:
Fecha(int dia=1,int mes=1,int anyo=1900);
...
private:
int dia,mes,anyo;
};
39
Sobrecarga de la entrada/salida (3/4)
• Implementación:
ostream& operator<<(ostream &os,const Fecha &f){
os << f.dia << "/" << f.mes << "/" << f.anyo;
return os;
}
40
Sobrecarga de la entrada/salida (4/4)
Factura
- nextId: int = 1
+ IVA: const int = 21
- fecha: string
- id: int
41
Atributos y métodos de clase (1/4)
42
Atributos y métodos de clase (2/4)
43
Atributos y métodos de clase (3/4)
Factura
- nextId: int = 1
+ IVA: const int = 21
- fecha: string
- id: int
44
Atributos y métodos de clase (4/4)
// Fecha.cc
const string Fecha::finMundo="2020"; // No se pone static
45
El puntero this
46
Objetos y gestión de memoria
Objetos automáticos y objetos dinámicos (1/5)
47
Objetos automáticos y objetos dinámicos (2/5)
48
Objetos automáticos y objetos dinámicos (3/5)
49
Objetos automáticos y objetos dinámicos (4/5)
50
Objetos automáticos y objetos dinámicos (5/5)
Asociación
Entre objetos Agregación
Composición
Uso
53
Agregación y composición (1/6)
54
Agregación y composición (2/6)
Equipo Avión
1..* 1
* 2
Jugador Ala
55
Agregación y composición (3/6)
56
Agregación y composición (4/6)
• Implementación de la composición:
A A A A
1 -b 10 -b 0..10 -b * -b
B B B B
57
Agregación y composición (5/6)
• Implementación de la agregración:
A A A A
1 -b 10 -b 0..10 -b * -b
B B B B
58
Agregación y composición (6/6)
59
Compilación
El proceso de compilación
60
Compilación separada (1/2)
61
Compilación separada (2/2)
62
La herramienta make (1/5)
63
La herramienta make (2/5)
64
La herramienta make (3/5)
• Ejemplo:*
prog : C1.o C2.o prog.o
g++ -Wall -g C1.o C2.o prog.o -o prog
C1.o : C1.cc C1.h
g++ -Wall -g -c C1.cc
C2.o : C2.cc C2.h C1.h
g++ -Wall -g -c C2.cc
prog.o : prog.cc C1.h C2.h
g++ -Wall -g -c prog.cc
*La opción -Wall muestra todos los warnings y -g añade información para el depurador
65
La herramienta make (4/5)
66
La herramienta make (5/5)
prog : $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o prog
C1.o : C1.cc C1.h
$(CC) $(CFLAGS) -c C1.cc
C2.o : C2.cc C2.h C1.h
$(CC) $(CFLAGS) -c C2.cc
prog.o : prog.cc C1.h C2.h
$(CC) $(CFLAGS) -c prog.cc
clean:
rm -rf $(OBJS)
*Más información en: http://es.wikipedia.org/wiki/Make 67
Ejercicios
Ejercicios (1/3)
Ejercicio 1
Implementa la clase del siguiente diagrama:
Coordenada
- x : float
- y : float
+ Coordenada (cx: float=0, cy: float = 0)
+ Coordenada (const Coordenada &)
+ ~Coordenada()
+ <<const>> getX() : float
+ <<const>> getY() : float
+ setX (cx:float) : void
+ setY (cy:float) : void
+ <<friend>> operator << : ostream &
Ejercicio 2
Implementa el código correspondiente al siguiente diagrama UML:
Linea Factura
- cantidad : int * - sigId : int = 1
- precio : float + IVA : const int = 18
- descripcion : string -lineas - fecha : string
+ Linea() - id : int
+ <<const>> getSubtotal() : float + Factura(c: Cliente*, fecha : string)
+ <<const>> getCantidad() : int + anyadirLinea(cant : int, desc : string, prec : float) : void
+ <<const>> getPrecio() : float - getSigId() : int
+ <<const>> getDescripcion() : string + <<friend>> operator<< : ostream &
+ setCantidad(cant : int) : void
+ setPrecio(precio : float) : void
+ setDescripcion(descripcion : string) : void 1 -cliente
Cliente
- nombre : string
- direccion : string
- telefono : string
+ Cliente(nom: string, dir : string, tel : string)
+ <<const>> getNombre() : string
+ <<const>> getTelefono() : string
+ <<const>> getDireccion(): string
+ setNombre(nombre : string) : void
+ setTelefono(telefono : string) : void
+ setDireccion(direccion : string) : void
69
Ejercicios (3/3)
Ejercicio 2 (continuación)
Se debe hacer un programa que cree una nueva factura, añada un
producto y lo imprima. Desde el constructor de Factura se llamará
al método getSigId, que devolverá el valor de sigId y lo
incrementará. Ejemplo de salida al imprimir una factura:
Factura nº: 12345
Fecha: 18/4/2011
Detalle de la factura
---------------------
Línea;Producto;Cantidad;Precio ud.;Precio total
--
1;Ratón USB;1;8,43;8,43
2;Memoria RAM 2GB;2;21,15;42,3
3;Altavoces;1;12,66;12,66
Subtotal: 63,39 €
IVA (18%): 11,41 €
TOTAL: 74.8002 €
70