Вы находитесь на странице: 1из 108

Estructuras de Datos y Algoritmos

Facultad de Informatica
Universidad Politecnica de Valencia
Curso 2009/2010
Tema 1:
Introduccion a la programacion con C++
FI UPV: Curso 2009/2010
EDA-Tema1
TEMA 1. Introduccion a la programacion con C++
Objetivos
Aprender algunos conceptos del lenguaje C++ con el n de poder utilizarlo a lo largo
de la asignatura. Es decir, no necesitamos saber todos los detalles y conceptos de este
lenguaje.
Conocimientos previos
Se asume que ya se sabe programar en lenguaje C.
Contenidos
1 Conceptos basicos de C++.
2 Clases en C++.
3 Algunas libreras estandar.
Bibliografa
C++ estandar , de Enrique Hernandez Orallo et al.
The C++ Programming Language, de Bjarne Stroustrup.
FI UPV: Curso 2009/2010 Pagina 1.1
EDA-Tema1
El lenguaje C++
Dise nado por Bjarne Stroustrup en los Laboratorios AT&T a principios de los a nos 80. Es
una extension de C (salvo detalles, C es un subconjunto de C++).
Objetivos del dise no de C++:
Soporte para la programacion modular: Espacios de nombres.
Soporte para la programacion orientada a objetos: Clases.
Soporte para la programacion generica (plantillas). No todos los lenguajes orientados a
objetos la soportan.
Al igual que C, se trata de un lenguaje donde la eciencia en tiempo de ejecucion se
considera importante.
Por tanto, hay dos clases de extensiones respecto de C:
Extensiones no orientadas a objetos: Espacios de nombre, sobrecarga de funciones y
de operadores, plantillas, nuevos tipos de datos, funciones inline, nuevos comentarios,
nuevas libreras, etc.
Extensiones relacionadas con la programacion orientada a objetos: Clases.
FI UPV: Curso 2009/2010 Pagina 1.2
EDA-Tema1
C++ no tiene soporte (estandar) para:
Concurrencia.
Recoleccion automatica de memoria (como ocurre, por ejemplo, en Java).
C++ soporta programacion orientada a objetos, pero no es imprescindible (se puede
utilizar C++ sin objetos).
Compatibilidad con librerias C y herramientas UNIX (make) para reutilizacion de codigo.
Se ha convertido en un estandar de programacion: iso/iec 98-14882. Esto proporciona
estabilidad al lenguaje. Este estandar incluye una biblioteca estandar muy amplia que
incluye, entre otras cosas, la Standard Template Library: STL consistente en contenedores
(vectores, listas, diccionarios, etc.), algoritmos e iteradores genericos que se pueden
instanciar a diversos tipos de datos.
FI UPV: Curso 2009/2010 Pagina 1.3
EDA-Tema1
Conceptos basicos de C++
Comentarios.
/
*
...
... comentario que puede abarcar multiples lneas
...
*
/
Estos comentarios no se pueden anidar.
// ... comentario hasta el final de la lnea
http://xkcd.com/156/
FI UPV: Curso 2009/2010 Pagina 1.4
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
Tipos fundamentales
Vienen denidos por el propio lenguaje, en C++ se dividen en:
Enteros o discretos (integral types)
Tipos maquina: bool, char, short, int, long.
Tipos enumerados: enum.
Reales (coma otante): float, double, long double.
void.
se usa en funciones y punteros.
no se pueden declarar variables de ese tipo.
no consume memoria y no hay ningun operador aplicable a el.
FI UPV: Curso 2009/2010 Pagina 1.5
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
Tipo bool
Puede tener dos valores: true y false
El tama no no esta establecido en el estandar, suele ser un byte.
Los valores numericos se convierten implcitamente a tipos booleanos.
Valores distintos de cero se convierten a true y el cero a false.
Los punteros tambien se convierten implcitamente.
Puntero a NULL o cero se convierte a false y el resto se considera true.
Literales: los valores true y false
FI UPV: Curso 2009/2010 Pagina 1.6
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
Tipos enteros
Podemos tener distintos tama nos mnimos: short, int, long.
2 sizeof(short)
4 sizeof(long)
sizeof(short) sizeof(int) sizeof(long)
Literales: Podemos utilizar distintas bases numericas:
Decimal: No empieza por 0 (para el literal 0 da igual la base).
Octal: Empiezan por 0. Ejemplo: 010 es como poner 8
Hexadecimal: Empiezan por 0x o por 0X.
Para los valores de 10 a 15 se utilizan las letras ABCDEF o tambien abcdef.
El sujo fuerza el tipo del literal:
u o U para que sea de tipo unsigned.
l o L para que sea de tipo long.
Ejemplo: 0xAAuL es un valor 10 16 + 10 = 170 unsigned long.
FI UPV: Curso 2009/2010 Pagina 1.7
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
Tipos reales
Diferentes representaciones: float, double, long double.
Tama no dependiendo de la arquitectura, ejemplo:

oat 32 bits
double 64 bits
long double 96 bits
Literales: Consiste en una parte entera, un punto decimal, una parte fraccionaria y, opcional-
mente, un caracter e o E, un exponente entero con signo opcional. Se puede a nadir un sujo
para indicar el tipo (sin sujo se considera double, con f o con F se considera float y
con l o con L es long double). Ejemplos:
0.5F 0,5 float
0.25 0,25 double
-1.0e5L 100 000 long double
FI UPV: Curso 2009/2010 Pagina 1.8
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
Caracteres
Tipo char, tama no: 1 byte.
Las variables y literales de tipo char se pueden sumar, restar, etc. ya que son de tipo
aritmetico.
Literales: Se delimita por dos apostrofes . El caracter de escape \ sirve para codicar
algunos caracteres como \n, etc.
Cadenas: Secuencia (vector) de caracteres acabados en el caracter nulo \0
Literales: Las cadenas se delimitan con comillas "", ejemplo: "Hola\nmundo\n"
FI UPV: Curso 2009/2010 Pagina 1.9
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
Tipos enumerados
Sirven para denir un tipo que solo puede tomar valores dentro de un conjunto nito.
La sintaxis es:
enum nombre {Valor1, Valor2, Valor3, ...};
Ejemplos:
enum palo {Oro, Basto, Espada, Copa};
enum respuesta {SI, NO};
Los nombres de los valores deben ser distintos entre s:
enum palo {Oro, Basto, Espada, Copa};
enum premio {Oro, Plata, Bronce}; // PROBLEMA!!!!
program.cc:5: error: conflicting types for oro
program.cc:4: error: previous declaration as palo oro
FI UPV: Curso 2009/2010 Pagina 1.10
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
Tipos derivados
Se obtienen de los tipos fundamentales usando los siguientes smbolos de declaracion:
*
Punteros
& Referencias
[] Vectores (arrays)
() Funciones
FI UPV: Curso 2009/2010 Pagina 1.11
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
Punteros
Para un tipo dado T, el tipo puntero a ese tipo es T
*
. Ejemplos:
int
*
p; // puntero a entero
int
*
q,r; // q es puntero a entero pero r es de tipo int
char
**
c; // puntero a un puntero a caracter
El puntero NULL Se trata de un puntero 0. Cualquier indireccion de este puntero se convierte
en un error de ejecucion. El identicador NULL no es reservado y hay que incluirlo desde
alguna de estas cabeceras:
<cstddef> // definiciones estandar de C
<cstdlib> // librera estandar de C
Puesto que el 0 tiene conversion estandar a puntero, podemos usar simplemente el 0 en vez
de NULL.
FI UPV: Curso 2009/2010 Pagina 1.12
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
Vectores
Una variable indexable que contiene muchos objetos de un mismo tipo que se almacenan
consecutivamente en memoria. Para un vector de n elementos, los ndices validos son los
enteros del 0 al n-1.
Controlar el acceso dentro del vector es responsabilidad del programador.
Los vectores se pueden inicializar poniendo elementos entre llaves y separados por comas.
Ejemplo:
int m[2][3] = { {1,2,3}, {4,5,6} };
char cad1[5] = {H,o,l,a,\0}; // OJO, HAY QUE PONER \0
char cad2[5]= "Hola"; // es equivalente a lo anterior
char cad2[]= "Hola"; // es equivalente a lo anterior
FI UPV: Curso 2009/2010 Pagina 1.13
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
Relacion entre vectores y punteros
Cuando denimos un vector, por ejemplo:
int v[10];
se dene a como un vector de 10 enteros y se reserva espacio necesario para esos diez
enteros.
El operador [] se convierte a operaciones sobre punteros, as es equivalente:
v[4]; // quinto elemento de v
*
(v+4); // equivalente a lo anterior
En general a[b] es equivalente a
*
((a)+(b))
El tipo de v es int[]. Hay una conversion desde T[] a T
*
, por tanto si escribimos:
int v[10];
int
*
p = v;
resulta que p y v son punteros al mismo tipo, pero v es un puntero constante no ocupando
memoria.
FI UPV: Curso 2009/2010 Pagina 1.14
EDA-Tema1
p = v; /
*
es valido
*
/ v = p; /
*
INVALIDO
*
/
p += 4; /
*
valido
*
/ v++; /
*
INVALIDO
*
/
En el caso de vectores multidimensionales hay que saber como se organizan en memoria.
1 #include <iostream>
2 using namespace std;
3 int main () {
4 int m[4][5];
5 // poner int
*
p = m; da error:
6 // error: cannot convert int (
*
)[5] to int
*

7 int (
*
p)[5] = m; // esto s que funciona
8 // forzando un casting vemos la matriz como vector por filas:
9 int
*
q = (int
*
)m;
10 for (int i=0;i<20;i++) q[i] = i;
11 // imprimimos el vector:
12 for (int i=0;i<4;i++)
13 for (int j=0;j<5;j++)
14 cout << "m["<<i<<"]["<<j<<"] = "<<m[i][j]<<endl;
15 cout << "m[2][2] = "<<
*
(
*
(m+2)+2) << endl;
16 return 0;
17 }
FI UPV: Curso 2009/2010 Pagina 1.15
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
Memoria dinamica
Para pedir memoria dinamica se utilizan los operadores new y delete que son una
alternativa a las funciones malloc() y free() de C. Ejemplo:
1 int main() {
2 int
*
a = new int; // poco habitual reservar un int
3 int j = 20;
4 int
*
v = new int[j]; // reservamos un vector de 20 enteros
5 // observa que el argumento j no es constante...
6 v[0] = 5;
7 delete a;
8 delete[] v; // OJO! Es un error frecuente poner delete v
9 return 0;
10 }
FI UPV: Curso 2009/2010 Pagina 1.16
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
Memoria dinamica
Para crear vectores multidimensionales, solo la primera de las dimensiones puede venir dada
en tiempo de ejecucion:
1 #include <iostream>
2 using namespace std;
3 int main () {
4 int n = 10, k=0;
5 const int cols = 5; // DEBE SER CONSTANTE
6 int (
*
m)[cols] = new int [n][cols];
7 for (int i=0;i<n;i++)
8 for (int j=0;j<cols;j++)
9 m[i][j] = k++;
10 for (int i=0;i<n;i++)
11 for (int j=0;j<cols;j++)
12 cout<<"m["<<i<<"]["<<j<<"] = "<<m[i][j]<<endl;
13 delete[] m;
14 return 0;
15 }
FI UPV: Curso 2009/2010 Pagina 1.17
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
Referencias
Una referencia es como un nombre alternativo o alias. La notacion T& signica referencia a
tipo T. Por ejemplo:
int a = 1;
int &r = a; // r y a se refieren al mismo entero
int x = r; // x = 1
r = 2; // a = 2
Restricciones:
Las referencias deben inicializarse cuando se declaran (excepto en argumentos por referencia
a funciones y referencias externas).
Una vez inicializadas, no pueden modicarse.
No se pueden crear referencias a referencias ni punteros a referencias.
El principal uso de las referencias es la denicion de argumentos y retorno por referencia en
funciones.
FI UPV: Curso 2009/2010 Pagina 1.18
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
Paso de parametros por referencia
Pasando punteros a la variable a modicar (como en C).
Utilizar el tipo derivado tipo &variable
Ejemplo:
1 void intercambio1(int
*
a, int
*
b) { // (utilizando punteros)
2 int temp =
*
a;
3
*
a =
*
b;
4
*
b = temp;
5 }
6 // la llamada: intercambio1(&i,&j);
7 void intercambio2(int &a, int &b) { // (utilizando referencias)
8 int temp = a;
9 a = b;
10 b = temp;
11 }
12 // la llamada: intercambio2(i,j);
FI UPV: Curso 2009/2010 Pagina 1.19
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
Tipos compuestos
Sirven para poder agrupar un conjunto o coleccion de variables del mismo o diferente tipo en
un nuevo tipo. Cada variable perteneciente a un tipo compuesto se llama miembro o campo.
Hay 4 tipos compuestos en C++:
Estructuras (struct)
Uniones (union)
Campos de bits
Clases (class)
No vamos a estudiar ni las uniones ni los campos de bits. Las clases se veran mas tarde.
FI UPV: Curso 2009/2010 Pagina 1.20
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
Estructuras
Permiten agrupar distintos elementos bajo un mismo tipo.
Los miembros de una estructura se acceden por su identicador (nombre del campo o
miembro).
Los distintos miembros se almacenan consecutivamente en memoria, pero ojo! el com-
pilador puede a nadir bytes extra entre distintos miembros para forzar determinados
alineamientos de la memoria.
Sintaxis:
struct nombre {
tipo1 vartipo1;
tipo2 vartipo2;
....
} variable1,variable2,...,variable_n;
donde o bien nombre o bien las variables variable1,. . . son opcionales.
FI UPV: Curso 2009/2010 Pagina 1.21
EDA-Tema1
Al declarar una variable, argumento,. . . de un tipo struct previamente podemos poner
o no la palabra struct, ejemplo:
struct tupla { int a, b; }; // definimos una tupla
....
tupla x; // valido
struct tupla y; // tambien es valido, as es como en C.
Los distintos campos de una estructura se acceden con el operador . (es decir, un punto).
Ejemplo:
struct complejo { double real, imaginaria; };
complejo a,b,c;
a.real = a.imaginaria = 0; // a = 0
b.real = 1;
b.imaginaria = 2;
c.real = a.real + b.real;
c.imaginaria = a.imaginaria + b.imaginaria;
// ;) en breve podremos hacer c = a+b;
FI UPV: Curso 2009/2010 Pagina 1.22
EDA-Tema1
Conceptos basicos de C++
Tipos de datos
typedef
Se utiliza para crear un nuevo tipo, por ejemplo:
typedef int entero;
A partir de esta declaracion podemos utilizar enteros para cualquier cosa que pudiesemos
hacer con int. Ademas, ambos tipos son completamente compatibles entre s:
entero a = 5;
int b;
b = a;
FI UPV: Curso 2009/2010 Pagina 1.23
EDA-Tema1
Esquema de tipos de datos
Fundamentales
& referencia
puntero
*
[]
funcion ()
vector
Discretos
(integrales)
Coma flotante
float
double
long double
bool
char
int
short
long
enum
Aritmeticos
Derivados
Compuestos
struct
class
union
campo de bit
TIPOS
void
FI UPV: Curso 2009/2010 Pagina 1.24
EDA-Tema1
Operadores
C++ dispone de gran n umero de operadores
De distintas aridades: los hay unarios, binarios y ternarios.
Con distintas notaciones: preja, inja, suja.
Para evitar ambiguedades cuando no hay parentesis:
Distintos tipos de asociatividad: a la derecha y a la izquierda.
Distintas precedencias.
Los tipos basicos de operadores son:
Aritmeticos.
De comparacion y logicos.
De bit.
De asignacion.
De indireccion.
De evaluacion.
Condicional.
Operadores sizeof.
Operadores de conversion.
FI UPV: Curso 2009/2010 Pagina 1.25
EDA-Tema1
Operadores
Operandos destino (lvalue)
Un operador act ua sobre uno o mas operandos. Estos operandos pueden ser muy diversos:
variables, constantes, funciones, etc.
Hay un tipo de operando que interesa caracterizar: los operandos destino (tambien llamados
lvalue) son aquellos a los que se les pueden asignar valores. Por tanto, deben designar una
region de almacenamiento. Por ejemplo, dadas las deniciones:
char cadena[100];
int i,
*
p;
struct complejos { double real, imaginaria } co1;
Algunos ejemplos validos de operando destino son:
p // puntero a int
i // un entero int
cadena[20] // un caracter
co1.real // un double
FI UPV: Curso 2009/2010 Pagina 1.26
EDA-Tema1
Operadores
Operadores aritmeticos
+ Suma.
- Resta.
*
Producto.
/ Division.
% M odulo, solo para valores integrales (enteros,char,. . . )
+(unario) No hace nada, mantiene el signo.
-(unario) Cambio de signo.
Incremento y decremento
El operador ++ suma una unidad.
El operador -- resta una unidad.
Se aplican a operandos destino.
Se aplican a todos los tipos fundamentales excepto void y tambien a los punteros.
Aplicado sobre punteros avanza tantos bytes como sizeof del tipo que apunte el puntero.
Devuelven el valor. Se pueden situar antes o despues. Si lo situamos antes (pre), realiza
la operacion antes de devolver el valor. Si lo situamos despues (post), devuelve el valor
antes de la operacion.
FI UPV: Curso 2009/2010 Pagina 1.27
EDA-Tema1
Operadores
Operadores de comparacion y logicos
< Estrictamente menor.
> Estrictamente mayor.
<= Menor o igual.
>= Mayor o igual.
== Igual. No confundir con la asignacion (=).
!= Distinto de.
Otros operadores son:
! Negacion.
&& Producto (y,and) logico de 2 expresiones.
|| Suma (o,or) logica de 2 expresiones.
El orden de evaluacion de || y de && esta denido de izquierda a derecha.
Si el operador && no cumple la primera expresion, no se eval ua la segunda.
Si el operador || cumple la primera expresion, no se eval ua la segunda.
FI UPV: Curso 2009/2010 Pagina 1.28
EDA-Tema1
Operadores
Operadores de bit
& Producto (y,and) unario de bits.
| Suma (o,or) binaria de bits.
Suma binaria exclusiva (xor,orex) de bits.
<< Desplazamiento del primer operando hacia la izquierda
un n umero de bits marcado por el segundo operando.
>> Desplazamiento del primer operando hacia la derecha
un n umero de bits marcado por el segundo operando.
Complemento a 1 (cambia unos por ceros y viceversa).
- Complemento a 2 (cambia de signo).
No se deben confundir con los operadores logicos. Por ejemplo, 2 & 1 vale 0 pero
2 && 1 da true puesto que tanto 2 como 1 son != 0.
Los operadores de bit pueden ser utiles para hacer mascaras de bit. Ejemplo: n & 31 es
como hacer n % 32. Tambien para multiplicar o dividir por potencias de 2.
FI UPV: Curso 2009/2010 Pagina 1.29
EDA-Tema1
Operadores
Operadores de asignacion
= Asignacion.
+= Asignacion-suma.
-= Asignacion-resta.
*
= Asignacion-producto.
/= Asignacion-division.
%= Asignacion-resto.
<<= Asignacion-desplazamiento izquierda.
>>= Asignacion-desplazamiento derecha.
&= Asignacion-producto binario.
|= Asignacion-suma binaria.
= Asignacion-suma binaria exclusiva.
El operador de asignacion necesita un operando destino a la izquierda. El operando de la
izquierda toma el valor del de la derecha. Todo el conjunto se puede utilizar como operando
de otra expresion (este es uno de los motivos por el cual el compilador no se queja cuando
confundes un = por un ==). Por tanto, las siguientes sentencias son totalmente validas:
i = j = k = 5; a = (b = funcion(12))
*
3;
FI UPV: Curso 2009/2010 Pagina 1.30
EDA-Tema1
Operadores
Operadores de indireccion
*
Indireccion.
& Direccion (referencia).
-> Indireccion de objeto y seleccion de miembro.
. Seleccion de miembro.
[] Indexacion (subndice).
->
*
Indireccion de objeto e indireccion de miembro.
.
*
Indireccion a miembro.
Los veremos mas tarde.
FI UPV: Curso 2009/2010 Pagina 1.31
EDA-Tema1
Operadores
Nombres alternativos
Palabra reservada Equivalencia
and &&
or ||
not !
not_eq !=
bitand &
and_eq &=
bitor |
or_eq |=
xor
xor_eq =
compl
FI UPV: Curso 2009/2010 Pagina 1.32
EDA-Tema1
Operadores
Operandor de evaluacion
El operador de evaluacion es la coma (,). Sirve para evaluar expresiones consecutivas pero
quedandose con el resultado de una sola. La evaluacion es de izquierda a derecha y el
resultado es el de la derecha. Ejemplo:
int i,j;
for (i=0, j = 10; i < 10; i++,j--)
cout << i << " + " << j << " = 10\n";
en este caso el resultado de la expresion daba igual. Otro ejemplo:
if (f1(),f2()) { ... }
el resultado del if depende de f2(), pero f1() se ha evaluado primero.
FI UPV: Curso 2009/2010 Pagina 1.33
EDA-Tema1
Operadores
Operandor condicional
Tiene una sintaxis peculiar, es un operador ternario. Sintaxis:
(expresion1) ? expresion2 : expresion3
Su uso no es muy com un y puede ser sustituido por una expresion if else.
Ejemplo:
if (a > b)
maximo = a;
else
maximo = b;
Utilizando el operador ? : quedara as:
maximo = (a > b) ? a : b;
FI UPV: Curso 2009/2010 Pagina 1.34
EDA-Tema1
Operadores
Operandor sizeof
Devuelve la longitud (en bytes) de un tipo de datos.
Retorna un valor de tipo size_t denido en <cstddef> y que suele ser similar al tipo
unsigned.
En realidad, este operador no realiza ninguna operacion. El compilador lo convierte en una
constante.
Se puede aplicar tanto a tipos como a variables, teniendo distinta sintaxis:
sizeof (x); // tamano de x un tipo o variable
sizeof variable; // tamano de una variable
Para vectores, sizeof devuelve el tama no en bytes, no el n umero de elementos.
El tama no de una estructura puede diferir de la suma de tama nos de cada miembro debido
al alinemiento que fuerza el compilador. Ejemplo:
struct variopinto { char c; int a; char d; };
sizeof(variopinto) vale 12 y no 1+4+1=6 (con g++ en Linux PC)
struct variopinto2 { char c,d; int a; };
sizeof(variopinto2) vale 8
FI UPV: Curso 2009/2010 Pagina 1.35
EDA-Tema1
Operadores
Precedencia y asociatividad
La asociatividad indica en que orden se asocian los operandos. Puede ser:
De izquierda a derecha. Ej: a
*
b
*
c sera (a
*
b)
*
c
De derecha a izquierda. Ej: a=b=c sera a=(b=c)
No tiene asociatividad. Ej: &a
No hay que confundir la asociatividad de los operandos con la evaluacion de los mismos.
Que se asocien de izquierda a derecha no quiere decir que tambien se eval uen de ese
modo. Ejemplo:
i = f1() + f2() + f3();
se puede ejecutar primero f1() y despues f2() o al reves. Si el orden fuese importante
tendramos que hacer lo siguiente:
i = f1(); i += f2(); i += f3();
En C++ existe una precedencia ja, una asociatividad bien denida, pero el orden de
evaluacion no esta prejado y dependera del compilador. Por tanto, en casos en que sea
importante el orden de evaluacion hay que separar las expresiones convenientemente.
FI UPV: Curso 2009/2010 Pagina 1.36
EDA-Tema1
Tablas de precedencia y asociatividad (I)
La tabla esta organizada de mayor a menor precedencia.
ID = Izquierda a Derecha, DI = Derecha a Izquierda, NO = No hay asociatividad.
Operando As. Descripcion Sintaxis
:: NO Resolucion de ambito nombre_clase::miembro
:: NO Operador de ambito ::nombre
. ID Seleccion de miembro estructura.miembro
-> ID Puntero a miembro puntero->miembro
[] ID Subndice puntero[ expr ]
() ID Llamada a funcion nombre_funcion()
() NO Conversion estilo C++ tipo ( expr )
++ NO Post-incremento lvalue++
-- NO Post-decremento lvalue--
sizeof NO Tama no de un objeto sizeof expr.
sizeof() NO Tama no de un tipo sizeof ( tipo ).
++ NO Pre-incremento ++lvalue
-- NO Pre-decremento --lvalue
- NO Complemento - expr
! NO Negacion logica ! expr
- NO Negativo (unario) - expr
+ NO Positivo (unario) + expr
FI UPV: Curso 2009/2010 Pagina 1.37
EDA-Tema1
Tablas de precedencia y asociatividad (II)
Operando As. Descripcion Sintaxis
& NO Referencia & lvalue
*
NO Indireccion
*
expr
new NO Crear objeto new tipo
delete NO Destruir objeto delete puntero
delete[] NO Destruir array delete [] puntero
() DI Conversion estilo C (tipo) expr
.
*
ID Seleccion miembro objeto.ptr_miembro
->
*
ID Puntero miembro ptr->ptr_miembro
*
ID Multiplicacion expr
*
expr
/ ID Division expr / expr
% ID Resto expr % expr
+ ID Suma expr + expr
- ID Resta expr - expr
<< ID Desplazamiento izquierda expr << expr
>> ID Desplazamiento derecha expr >> expr
< ID Menor que expr < expr
<= ID Menor o igual que expr <= expr
> ID Mayor que expr > expr
>= ID Mayor o igual que expr >= expr
== ID Igual que expr == expr
!= ID No igual que expr != expr
FI UPV: Curso 2009/2010 Pagina 1.38
EDA-Tema1
Tablas de precedencia y asociatividad (III)
Operando As. Descripcion Sintaxis
& ID Producto de bits (AND) expr & expr
ID Suma exclusiva (XOR) expr expr
| ID Suma de bits (OR) expr | expr
&& ID Y logico (AND) expr && expr
|| ID O logico (OR) expr || expr
?: DI Expresion condicional expr ? expr : expr
= DI Asignacion simple lvalue = expr
*
= DI Multiplicacion y asignacion lvalue
*
= expr
/= DI Division y asignacion lvalue /= expr
%= DI Resto y asignacion lvalue %= expr
+= DI Suma y asignacion lvalue += expr
-= DI Resta y asignacion lvalue -= expr
<<= DI Despl.izq. y asignacion lvalue <<= expr
>>= DI Despl.der. y asignacion lvalue >>= expr
&= DI AND y asignacion lvalue &= expr
|= DI OR y asignacion lvalue |= expr
= DI XOR y asignacion lvalue = expr
, ID Coma (eval. secuencia) expr , expr
FI UPV: Curso 2009/2010 Pagina 1.39
EDA-Tema1
Conversion de tipos
C++ es estricto con respecto a los tipos. Un valor de un tipo no se puede asignar a un
operador destino de otro tipo (con bastantes excepciones que vamos a ver). Para evitar
un error, se puede forzar una conversion entre tipos utilizando un casting al estilo de C,
por ejemplo:
char c;
int i;
c = (char)i;
c = char(i); // esta forma es valida en algunos casos
Los tipos aritmeticos pueden ser mezclados libremente en asignaciones y expresiones. La
asignacion de un tipo de mas bits a un operador destino de menos bits conlleva una
perdida de informacion, es una causa de errores y la conversion puede depender de la
implementacion. Como regla general:
Entre tipos integrales cuando queramos pasar de un escalar de mayor tama no a uno
de menor tama no habra un trucamiento de los bits de mayor orden.
Los tipos reales (float, double, long double) pueden asignarse entre s y con
los discretos se utiliza redondeo.
FI UPV: Curso 2009/2010 Pagina 1.40
EDA-Tema1

Ambito de las variables


A diferencia de C, en C++ podemos declarar un identicador (variables) en cualquier
bloque (incluso despues de haber escrito sentencias) y esta activo hasta que el bloque
donde ha sido declarado se cierra.
1 #include <iostream>
2 using namespace std;
3 int main() {
4 int t;
5 cout << "De que valor quieres la tabla? ";
6 cin >> t;
7 for (int x = 1; x <= 10; x++) {
8 int producto = x
*
t;
9 cout << t <<
*
<< x << = << producto << endl;
10 }
11 return 0;
12 }
Observa en este ejemplo como la variable x se declara y se utiliza en la lnea 7. El ambito
de esta variable alcanza todo el bloque for (lneas 7 y 8). La variable producto tiene
un scope que alcana las lneas 8 y 9.
FI UPV: Curso 2009/2010 Pagina 1.41
EDA-Tema1

Ambito de las variables


Es posible denir variables con el mismo nombre siempre que no se hayan denido en el
mismo ambito.
Operador de resolucion de ambito :: permite acceder a una variable del ambito global
con el mismo nombre que otra de ambito local, no esta permtido anidar este operador.
1 #include <iostream>
2 using namespace std;
3 float v; // al ser global toma valor inicial 0.0F
4 void funcion() {
5 float v = 1.0;
6 if (v > 0) {
7 float v = 2.0; // ahora la v q vale 1.0 es inaccesible
8 cout << "v = " << ::v << endl; // la global
9 cout << "v = " << v << endl; // la local
10 }
11 }
12 int main() {
13 funcion(); // imprime: v=0
14 return 0; // v=2
15 }
No obstante, es aconsejable utilizar nombres distintos siempre que sea posible.
FI UPV: Curso 2009/2010 Pagina 1.42
EDA-Tema1
Variables
Cualicador const
El cualicador const sirve para indicar que la variable no cambia de valor. C utiliza
#define pero de esta manera no se puede controlar el tipo.
Las variables declaradas con const deben inicializarse obligatoriamente en el momento
de la declaracion.
Se puede utilizar para indicar el tama no de un vector (no se podra utilizar una variable
no constante):
const int L=100;
int vector[L];
Los parametros de funciones denidos con const denotan que la funcion no modica
dicho valor:
void funcion(const char
*
cadena) {
cadena[0] = \0; // <-- ERROR, imposible modificar cadena!!!!
}
En la conversion de tipos el cambio a const es directo, el inverso no esta permitido sin
forzar un casting.
FI UPV: Curso 2009/2010 Pagina 1.43
EDA-Tema1
Variables
Cualicador const
La colocacion de const es muy importante:
int i; // variable
const int j = 5; // variable constante, se inicializa en la declaracion
int const
*
p = &j; // puntero a un "int constante"
const int
*
q = &j; // idem
int
*
const r = &i; // puntero constante a int, el constante es el puntero.
const int
*
const s = &j; // puntero constante a "int constante"
FI UPV: Curso 2009/2010 Pagina 1.44
EDA-Tema1
Variables
Cualicador const
1 #include <iostream>
2 using namespace std;
3 int main () {
4 const int i = 1;
5 int const j = 1;
6 cout << i << endl
7 << j << endl;
8 const int
*
a = &i;
9 a = &j;
10 int const
*
b = &i;
11 b = &j;
12 int
*
const c = &i;
13 return 0;
14 }
: In function int main():
12: error: invalid conversion from const int
*
to int
*

FI UPV: Curso 2009/2010 Pagina 1.45


EDA-Tema1
Control de ujo
El control de ujo en C++ es igual que en C, tenemos:
Sentencias condicionales: if else, switch case.
Sentencias de repeticion: while, do while, for,
Sentencias de salto: break, continue, goto y return.
Hay que evitar el uso de las sentencias de salto, salvo break en un switch case y
quizas return.
FI UPV: Curso 2009/2010 Pagina 1.46
EDA-Tema1
Entrada y salida con stream
Cuando hablamos de entrada/salida nos referimos a la gestion de la salida estandar (consola)
y entrada (teclado) as como la gestion de cheros.
C++ ofrece el concepto de stream que se puede traducir a castellano como ujo y que
proporciona facilidades para entrada/salida de un ujo de datos desde cualquier dispositivo
logico o fsico.
A pesar de que no es dependiente del entorno ni del sistema operativo, recordemos que, ante-
rior a C++, Unix ya ofrece el concepto de chero y lo aplica tambien para la entrada/salida
por consola y teclado y para los dispositivos fsicos.
Respecto a las funciones fprintf y fscanf pensadas para trabajar con tipos predenidos,
las caractersticas de los streams del C++ son las siguientes:
Entrada/salida uniforme para todos los tipos (incluidos los denidos por el usuario).
Comprobacion de tipos.
Extensible. Podemos crear nuevos streams.
FI UPV: Curso 2009/2010 Pagina 1.47
EDA-Tema1
Entrada y salida con stream
Se debe incluir la libreria iostream (#include <iostream>)
cout Permite enviar datos a la salida estandar (tpicamente pantalla). Ejemplo:
cout << "Hola, 2+2 = " << 2+2 << endl;
cin Permite recibir datos de la entrada estandar (tpicamente teclado). Por ejemplo:
cin >> i >> j >> k; cin >> i;
cin >> j;
cin >> k;
En ambos casos podemos introducir los valores en una lnea o en varias:
17 36 125 17 36 17 17
125 36 125 36
125
cerr Permite enviar datos a la salida de error (tpicamente pantalla). Podemos redirigir
las salidas estandar para que salida estandar y salida de error vayan a sitios distintos. La
ventaja de la salida de error es que no esta buferizada y, en caso de error en el programa,
podemos estar seguros de que si no salio un mensaje de error es porque la ejecucion no
paso por all ;)
FI UPV: Curso 2009/2010 Pagina 1.48
EDA-Tema1
Metodos de la clase stream
Ademas de los operadores de insercion y de extraccion << y >>, tenemos una serie de
metodos a nuestra disposicion, entre ellos:
Metodo Prototipo
put ostream& put(char)
get int get()
getline istream& getline(char
*
, streamsize, char = \n)
flush ostream& flush()
read istream& read(char
*
, int)
write ostream& write(const char
*
, int)
Ejemplo:
1 #include <iostream>
2 using namespace std;
3 int main() {
4 cout.put(H);
5 cout.put(o);
6 cout.put(l);
7 cout.put(a);
8 cout.put(\n);
9 }
FI UPV: Curso 2009/2010 Pagina 1.49
EDA-Tema1
Ejemplo:
1 #include <iostream>
2 using namespace std;
3 int main() {
4 int c;
5 c = cin.get();
6 cout << c << \t << (char)c << endl;
7 }
Ejemplo:
1 #include <iostream>
2 using namespace std;
3 int main() {
4 const int longlinea = 1000;
5 char linea[longlinea];
6 int i;
7 while (cin.getline(linea,longlinea)) {
8 cout << linea << endl;
9 }
10 }
FI UPV: Curso 2009/2010 Pagina 1.50
EDA-Tema1
Streams chero
Para poder leer y escribir datos en cheros se utiliza la librera <fstream>
Dene las clases ifstream para entrada y ofstream para salida. Ejemplo:
ifstream fent;
ofstream fsal;
Tras denir alg un objeto de estas clases, podemos asociarle un chero y abrirlo mediante
su metodo open pasandole el nombre del chero:
fent.open("datos.txt")
fsal.open("resultados.txt")
Tras ejecutar open conviene comprobar que los cheros se han abierto correctamente
antes de leer o escribir en ellos:
if (!fent) { ... // Error en la apertura
la evaluacion de un objeto ofstream o ifstream como condicion produce true
cuando el chero esta en estado correcto y false cuando esta en un estado de error.
Podemos utilizar los operadores << y >> y tambien los demas metodos vistos en
<iostream>.
FI UPV: Curso 2009/2010 Pagina 1.51
EDA-Tema1
Un objeto ofstream o ifstream cierra su chero con su metodo close:
fent.close()
fsal.close()
Ejemplo:
1 #include <iostream>
2 #include <fstream>
3 using namespace std;
4 int main() {
5 const int tamlinea = 1000;
6 char cadena[tamlinea];
7 ifstream fich;
8 fich.open("datos.txt"); // abrimos en modo lectura
9 while (fich.getline(cadena,tamlinea)) {
10 cout << cadena << endl;
11 }
12 fich.close(); // cerramos el fichero
13 }
FI UPV: Curso 2009/2010 Pagina 1.52
EDA-Tema1
Streams cadena
Se utiliza la librera <sstream> que contiene las clases istringstream y
ostringstream.
La clase istringstream se inicializa con una cadena.
La clase ostringstream contiene una cadena que se obtiene con el metodo str().
Su uso vendra a sustituir las funciones sprintf y sscanf de la librera <cstdio>
pero la clase <sstream> nos permite trabajar con streams de manera transparente.
Ejemplo de stream cadena:
1 #include <iostream>
2 #include <sstream>
3 using namespace std;
4 int main() {
5 int i;
6 float f;
7 char pal1[100],pal2[100];
8 istringstream cincadena("entero 5 real 2.3");
9 cincadena >> pal1 >> i >> pal2 >> f;
10 cout << pal1 << , << i << , << pal2 << , << f << endl;
11 }
Salida:
entero,5,real,2.3
FI UPV: Curso 2009/2010 Pagina 1.53
EDA-Tema1
Ejemplo de stream cadena:
1 #include <iostream>
2 #include <sstream>
3 using namespace std;
4 int main() {
5 ostringstream coutcadena;
6 coutcadena << "Hola, 2+2 = " << 2+2 << endl;
7 cout << coutcadena.str();
8 }
Salida:
Hola, 2+2 = 4
FI UPV: Curso 2009/2010 Pagina 1.54
EDA-Tema1
Estado de un stream
Los objetos stream pueden atravesar diferentes estados. Estos estados pueden conocerse
mediante los siguientes metodos p ublicos:
Metodo Descripcion
iostate rdstate(); Retorna el estado del stream.
int good(); Retorna verdadero si esta en buen estado.
int eof(); Retorna verdadero si esta al nal del chero-
int fail(); Retorna verdadero si failbit o badbit estan a uno.
bad(); Retorna badbit
void clear(iostate = goodbit); Modica el estado, por defecto es goodbit
operator void
*
(); Retorna NULL si failbit o badbit estan a uno.
bool operator !(); Retorna verdadero si failbit o badbit estan a uno.
clear() se suele utilizar para recuperarse de los errores.
La funcion operator void
*
() sirve para hacer cosas tan breves como:
while (cin >> c) { // Extraer caracter
... // procesamos el caracter
}
El operador bool operator !() se puede utilizar de manera similar:
cin >> a;
if (!cin) cerr << "Ha habido un error leyendo a";
FI UPV: Curso 2009/2010 Pagina 1.55
EDA-Tema1
Formato de entrada/salida en streams
El formato predenido para los tipos elementales se puede modicar.
Una manera comoda de modicar el formato es mediante manipuladores. Es decir,
insertemos operaciones como width() directamente en la lista de operaciones de entrada
y salida. Pertenecen a la librera <iomanip> y destacamos los siguientes:
setbase El valor puede ser 8,10,16.
setll Para indicar el caracter de relleno.
setprecision La precision en coma otante: n umero de dgitos totales.
xed Modica el comportamiento de setprecision: n umero de dgitos tras el . decimal.
setw La anchura del campo. Solo afecta al siguiente item!
left A nade los caracteres de relleno a la derecha
right A nade los caracteres de relleno a la izquierda
El uso del ancho de campo puede ser util en la entrada para no desbordar la capacidad de
una cadena:
const int capacidad = 1000;
char cad[capacidad];
cin >> setw(capacidad) >> cad; // no desbordamos la capacidad
Para poder combinar los streams con las funciones de <cstdio> hay que llamar
previamente al metodo estatico sync_with_stdio de la clase ios_base antes de
empezar a utilizar las clases de C++ o en main()
FI UPV: Curso 2009/2010 Pagina 1.56
EDA-Tema1
1 #include <iostream>
2 #include <iomanip>
3 using namespace std;
4 int main() {
5 cout << "a) \"" << "hola" << "\"\n"
6 << "b) \"" << setw(10) << "hola" << "\"\n"
7 << "c) \"" << left << setw(10) << "hola" << "\"\n"
8 << "d) \"" << setw(10) << 5 << "\"\n"
9 << "e) \"" << setfill(x) << setw(10) << 5 << "\"\n"
10 << "f) \"" << right << setfill(x) << setw(10) << 5 << "\"\n"
11 << "g) \"" << setbase(16) << 51966 << "\"\n"
12 << "h) \"" << setprecision(5)<< 1234.56789012345<< "\", fixed: "
13 << fixed << 1234.56789012345 << "\"\n";
14 }
a) "hola"
b) " hola"
c) "hola "
d) "5 "
e) "5xxxxxxxxx"
f) "xxxxxxxxx5"
g) "cafe"
h) "1234.6", con fixed: "1234.56789"
FI UPV: Curso 2009/2010 Pagina 1.57
EDA-Tema1
Jerarqua de las clases stream
<ios> <istream> <iostream> <fstream> <sstream>
<ostream>
<streambuf>
istringstream
stringbuf
iostream ios
ios_base
cin
ostream
streambuf
ifstream
istream
stringstream
fstream
ofstream
ostringstream
filebuf
cout,cerr,clog
FI UPV: Curso 2009/2010 Pagina 1.58
EDA-Tema1
Funciones
Declaracion de funciones
Declaracion de prototipo opcional.
En el prototipo no es necesario el nombre de los argumentos, pero s el tipo.
Se puede declarar un prototipo mas de una vez.
En la dencion de la funcion tampoco es necesario el nombre de los argumentos que no
se vayan a utilizar.
Solo se permite una denicion de una misma funcion.
No se permite anidar funciones, aunque s declarar prototipos de una funcion en el cuerpo
de otra.
Variables locales automaticas y estaticas:
Las automaticas se crean y destruyen en la pila.
Las estaticas existen durante toda la ejecucion del programa y se declaran con static.
Por defecto, los argumentos se pasan por valor.
Los argumentos por referencia se pueden utilizar para devolver valores o para mejorar
eciencia (Ej. evitar copiar un vector). Si no se modican, es mejor hacer uso de const.
FI UPV: Curso 2009/2010 Pagina 1.59
EDA-Tema1
Funciones
Argumentos por defecto
Se declaran en el prototipo de la funcion y no es necesario denirlos en la denicion.
Una funcion puede tener mas de un argumento por defecto. Deben ir consecutivos y al
nal.
El valor por defecto no tiene por que ser una constante. Puede ser una variable global.
1 #include <iostream>
2 using namespace std;
3 void funcion(int arg1, int arg2 = 0, char arg3 = a) {
4 cout << "arg1 = " << arg1 << ", arg2 = " << arg2
5 << ", arg3 = " << arg3 << endl;
6 }
7 int main() { // las tres llamadas son correctas:
8 funcion(1,2,b); funcion(3,4); funcion(5);
9 }
Salida:
arg1 = 1, arg2 = 2, arg3 = b
arg1 = 3, arg2 = 4, arg3 = a
arg1 = 5, arg2 = 0, arg3 = a
FI UPV: Curso 2009/2010 Pagina 1.60
EDA-Tema1
Funciones inline
La llamada a una funcion supone cierta sobrecarga (pase de argumentos, retorno, etc.).
Por ello, muchos programadores utilizan macros cuando programan en C. Ejemplo:
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define SQR(x) ((x)
*
(x))
No se controla el tipo de datos y puede haber problemas como en la llamada SQR(x++).
Cuando una funcion se declara como inline, el compilador expande su codigo donde
aparece la llamada a la funcion logrando en muchos casos eciencia en tiempo de ejecucion
a costa de un mayor tama no del codigo.
1 #include <iostream>
2 using namespace std;
3 #define SQR(x) ((x)
*
(x))
4 inline int sqr(int a) { return a
*
a; }
5 int main() {
6 int x = 4;
7 cout << SQR(x++) << ,; cout << x << endl; // escribe 16,6
8 x = 4;
9 cout << sqr(x++) << ,; cout << x << endl; // escribe 16,5
10 }
FI UPV: Curso 2009/2010 Pagina 1.61
EDA-Tema1
Sobrecarga de funciones
La sobrecarga de funciones consiste en denir varias funciones con el mismo nombre (y
en el mismo ambito) pero con distinto n umero y/o tipo de argumentos. El compilador se
encarga de elegir la funcion adecuada en funcion de los parametros de llamada.
Es aconsejable que la sobrecarga se utilice unicamente cuando las diferentes funciones
tienen un proposito similar. Es una tecnica que hay que utilizar con moderacion.
La sobrecarga puede causar problemas de ambig uedad (sobre todo combinado con el
problema de las conversiones entre tipos de datos).
FI UPV: Curso 2009/2010 Pagina 1.62
EDA-Tema1
Sobrecarga de funciones
1 #include <iostream>
2 using namespace std;
3
4 void f(int a, int b = 1) {
5 cout << "implementacion con argumento por defecto\n";
6 }
7
8 void f(int a) {
9 cout << "implementacion con 1 argumento\n";
10 }
11
12 int main () {
13 f(5);
14 return 0;
15 }
ambiguedad.cc: In function int main():
ambiguedad.cc:13: error: call of overloaded f(int) is ambiguous
ambiguedad.cc:4: error: candidates are: void f(int, int)
ambiguedad.cc:8: error: void f(int)
FI UPV: Curso 2009/2010 Pagina 1.63
EDA-Tema1
Sobrecarga de operadores
Se utiliza la palabra reservada operator. Ejemplo:
1 struct complejo {
2 double real,imaginaria;
3 };
4 complejo operator + (const complejo& c1, const complejo& c2) {
5 complejo temp;
6 temp.real = c1.real + c2.real;
7 temp.imaginaria = c1.imaginaria + c2.imaginaria;
8 return temp;
9 } // ahora podemos hacer: complejo c1,c2,c3; ... ; c1 = c2+c3;
10 // pero tambien llamar explicitamente asi: c1 = operator + (c2,c3);
Casi todos los operadores pueden ser sobrecargados. Excepciones:
. .
*
:: ?: sizeof
La precedencia y sintaxis de los operadores sobrecargados no vara. Ejemplo: La salida con
streams sobrecarga el operador <<, si escribimos:
cout << a & b << " da problemas\n";
es incorrecto porque el operador << tiene precedencia sobre &
Los smbolos de preprocesado (#,##, etc.) no son sobrecargables.
FI UPV: Curso 2009/2010 Pagina 1.64
EDA-Tema1
Los operadores que son binarios y unarios al mismo tiempo (ej. -) se pueden sobrecargar
de dos formas.
Los operadores sobrecargados no pueden tener argumentos por defecto.
Solo se puede sobrecargar lo que no esta denido (Ej. no se puede redenir la suma de
enteros).
No se permite crear operadores nuevos.
Algunos operadores solo se pueden sobrecargar cuando son denidos en una clase:
[] = -> () (cast)
FI UPV: Curso 2009/2010 Pagina 1.65
EDA-Tema1
Utilizar clases en C++
Por lo que hemos visto, a nivel sintactico lo que podemos hacer con un objeto es invocar
metodos sobre ellos. La manera de hacerlo sera:
variable_objeto.nombre_metodo(argumentos);
puntero_objeto->nombre_metodo(argumentos);
por ejemplo:
ifstream fent1,
*
fent2;
fent1.open("datos.txt")
fent2 = &fent1; // necesito inicializar el puntero
fent2->close() // antes de poder invocar un metodo...
A nivel sintactico, una diferencia entre un metodo y una funcion es que un metodo se aplica
a un objeto en particular, no es un argumento mas de la funcion.
Hay objetos que ofrecen metodos similares. Por ejemplo, si hago
ostringstream a,b;
esta claro que puedo aplicar el mismo repertorio de metodos tanto a a como a b esto
es as porque los dos objetos son instancias de la misma clase (en este caso, la clase
ostringstream).
FI UPV: Curso 2009/2010 Pagina 1.66
EDA-Tema1
Utilizar clases en C++
Que pinta podra tener un programa que calcule la moda estadstica (el valor mas frecuente)
utilizando clases?
1 #include <iostream>
2 using namespace std;
3 #include "muestra.h" // teoricamente tendriamos una clase muestra
4 const int tam = 30000;
5 int main() {
6 muestra m;
7 m.inicializar(tam); // le decimos el rango de valores valido
8 while (cin >> num)
9 m.procesar(num);
10 cout << "La moda es " << m.obtener_moda() << endl;
11 return 0;
12 }
Es decir, suponemos que la clase muestra nos ofrece los siguientes metodos:
void inicializar(int tamanyo);
void procesar(int valor);
int obtener_moda();
FI UPV: Curso 2009/2010 Pagina 1.67
EDA-Tema1
Denir clases en C++
Veamos como se denira la clase muestra en C++, en primer lugar declaramos la clase:
1 class muestra {
2 int tam,
*
vector;
3 public:
4 muestra(int tamanyo); // constructor
5 muestra(); // destructor
6 void procesar(int numero);
7 int obtener_moda();
8 };
Observa que es muy parecido a declarar una estructura. La diferencia es que dentro de la
misma ademas de declarar algunos miembros o campos estamos declarando lo que parecen
funciones pero en realidad son metodos.
En particular, hay 2 metodos que son en cierta manera especiales porque uno tiene el mismo
nombre que la clase y el otro igual pero precedido del smbolo . Son, respectivamente, un
constructor y el destructor de la clase.
Ademas, en la lnea 3 aparece la palabra reservada public: que sirve para indicar que a
partir de ese punto los miembros y metodos declarados se pueden utilizar desde fuera de la
propia clase.
FI UPV: Curso 2009/2010 Pagina 1.68
EDA-Tema1
Denir clases en C++
Todava nos falta denir los metodos, fuera de la sentencia class.
1 muestra::muestra(int tamanyo) { // valores a procesar entre 0 y tam-1
2 int i;
3 tam = tamanyo;
4 vector = new int[tamanyo];
5 for (i=0; i<tam;i++) vector[i] = 0;
6 }
7 muestra::muestra() { delete[] vector; }
8 void muestra::procesar(int numero) {
9 vector[numero]++;
10 }
11 int muestra::obtener_moda() {
12 int i,max,imax;
13 max = vector[0]; imax = 0;
14 for (i=1; i < tam; i++) {
15 if (vector[i] > max) {
16 max = vector[i]; imax = i;
17 }
18 }
19 return imax;
20 }
FI UPV: Curso 2009/2010 Pagina 1.69
EDA-Tema1
Clases en C++
Se denen con class.
Declaracion de prototipos dentro de class
Niveles de acceso (en esta asignatura podemos obviar el tema y utilizar siempre public:):
public: Un miembro (atributo o metodo) declarado p ublico en una clase es accesible
para el codigo de la clase y para cualquier codigo externo a la misma.
private: Un miembro (atributo o metodo) declarado privado en una clase es
accesible solo (en principio) para el codigo de la clase.
protected: es como private: pero s permite el acceso en las clases heredadas,
lo que ocurre es que en esta asignatura no vamos a explicar ni utilizar el concepto de
herencia.
Los metodos que no modiquen ning un atributo se declaran const, la palabra const se
sit ua despues del parentesis de cierre de los argumentos. Ejemplo:
int muestra::obtener_moda() const { ... }
Denicion externa de los metodos. Los nombres de los metodos deben prejarse con:
nombre:: (el operador de ambito nombre_clase::) para que el compilador sepa que
son miembros de la clase y los distinga de funciones y de metodos de otras clases con el
mismo nombre.
FI UPV: Curso 2009/2010 Pagina 1.70
EDA-Tema1
Esquema de declaracion de clases en C++
1 class nombre_clase {
2 int i; // atributos privados, class es privado por defecto
3 nombre_clase
*
puntero; // correcto, pero nunca "nombre_clase valor;"
4 int nombre_metodo(int, float, float); // declaracion
5 public: // a partir aqui atributos y metodos publicos
6 nombre_clase(int); // constructor, puede haber >=0
7 nombre_clase(); // destructor
8 float metodo_publico(int) const; // metodo CONSTANTE
9 // no puede modificar atributos
10 friend float funcion_amiga(nombre_clase, float);
11 // una funcion "amiga" no es un metodo de la clase,
12 // es externa pero puede utilizar atributos privados
13 }; // el ; es necesario
14 nombre_clase::nombre_clase(int i) { ... } // implementacion constructor
15 nombre_clase::nombre_clase() { ... } // implementacion destructor
16 int nombre_clase::nombre_metodo(int i, float u, float v) { ... }
17 float nombre_clase::metodo_publico(int j) const { ... }
18 float funcion_amiga(nombre_clase obj, float f) { ... }
FI UPV: Curso 2009/2010 Pagina 1.71
EDA-Tema1
Metodos Constructores
Un Constructor es un metodo que se invoca automaticamente tras crear el objeto.
Se utiliza para inicializarlo. Normalmente la inicializacion consiste en:
dar valores iniciales a los atributos, y/o
reservar memoria dinamica apuntada por alg un atributo puntero.
Una clase puede declarar varios constructores (sobrecarga) y cada uno:
Debe declararse como metodo p ublico en su classe.
El nombre de un constructor es igual que el de su clase.
No debe especicar ning un tipo de retorno, no debe devolver nada.
El n umero y tipo de parametros, y los valores por defecto de los mismos, que demos a los
constructores determina las formas en las que podemos crear los objetos de una clase.
En ausencia de constructores denidos por nosotros, el compilador genera uno sin ar-
gumentos que no hace nada. Es muy conveniente cuando denimos constructores con
argumentos denir tambien otro con cero argumentos.
Ejemplo:
1 muestra::muestra(int tamanyo) { // valores a procesar entre 0 y tam-1
2 tam = tamanyo;
3 vector = new int[tamanyo];
4 for (int i=0; i<tam;i++) vector[i] = 0;
5 }
FI UPV: Curso 2009/2010 Pagina 1.72
EDA-Tema1
Metodo destructor
Una clase puede tener varios metodos constructores, pero solamente un metodo destructor
Se suele utilizar para liberar los recursos asociados al objeto. Por ejemplo, para liberar la
memoria dinamica utilizada por alg un atributo del objeto.
Su nombre es exactamente igual que su clase precedido del smbolo tilde
Se invoca automaticamente al nalizar el ambito local de un objeto o al hacer un delete
sobre un puntero a objeto.
No devuelve nada.
No debe terner argumentos.
Debe declararse como metodo p ublico en su clase.
Si no declaramos el destructor, el compilador crea uno por defecto cuyo cuerpo esta vaco.
Ejemplo:
1 muestra::muestra() {
2 delete[] vector;
3 }
FI UPV: Curso 2009/2010 Pagina 1.73
EDA-Tema1
Inicializacion miembro a miembro
Constructores de copia
Un objeto puede inicializarse con otro objeto de su misma clase.
muestra m1(1000);
... // codigo donde modificamos m1
muestra m2(m1);
La inicializacion de un objeto a partir de otro la realiza un contructor especial denominado
constructor de copia. Si no se proporciona uno el compilador genera uno de manera
automatica.
El constructor de copia generado por el compilador realiza una inicializacion miembro a
miembro, es decir, cada atributo de m2 se inicializa con el valor correspondiente a cada
atributo de m1.
En este ejemplo una inicializacion miembro a miembro es incorrecta porque resultara que
los 2 vectores apuntados por el atributo vector en realidad son el mismo, al liberar uno
de ellos el otro apunta a una zona no reservada. Necesitamos un constructor de copia:
1 muestra::muestra(const muestra& der) { // constructor de copia
2 tam = der.tam; vector = new int[tam];
3 for (int i=0; i<tam;i++) vector[i] = der.vector[i];
4 }
FI UPV: Curso 2009/2010 Pagina 1.74
EDA-Tema1
Inicializacion miembro a miembro
Constructor de copia (II)
Como has podido observar en el ejemplo anterior, este metodo tiene el mismo nombre de
la clase (es un constructor) y tiene un argumento que es una referencia constante a un
objeto de la misma clase y que representa el objeto que se va a copiar.
El constructor de copia (generado por el compilador o proporcionado por nosotros) se
invoca en las siguientes situaciones (entre otras):
Inicializacion explcita de un objeto con otro.
Paso de un objeto como parametro por valor a una funcion.
Devolucion por valor de un objeto como retorno de una funcion.
FI UPV: Curso 2009/2010 Pagina 1.75
EDA-Tema1
Asignacion miembro a miembro
operador =
Un objeto tambien puede asignarse a otro de su misma clase:
muestra m1(1000),m2;
... // codigo donde modificamos m1
m2 = m1;
Nota: Para que este ejemplo fuese correcto necesitaramos un metodo constructor de la
clase muestra con 0 argumentos.
La asignacion de un objeto a otro la realiza el operador de asignacion.
Al igual que ocurra con la inicializacion, a menos que denamos nuestro operador de copia,
el compilador crea uno por defecto que efect ua una asignacion miembro a miembro: a
cada atributo de m2 se le asigna el valor del correspondiente atributo de m1.
1 muestra& muestra::operator=(const muestra &der) {
2 if (this != &der) {
3 tam = der.tam;
4 vector = der.vector;
5 }
6 return (
*
this);
7 }
FI UPV: Curso 2009/2010 Pagina 1.76
EDA-Tema1
Asignacion miembro a miembro
operador =
Si queremos que una copia distinta a la asignacion miembro a miembro debemos crear
nuestro propio operador = para la clase correspondiente. Ejemplo:
1 muestra& muestra::operator=(const muestra &der) {
2 if (this != &der) {
3 tam = der.tam; vector = new int[tam];
4 for (int i=0; i<tam;i++) vector[i] = der.vector[i];
5 }
6 return (
*
this);
7 }
El nombre operator= es el que recibe el metodo de una clase encargado de implementar
las acciones a realizar al copiar un objeto a otro.
As, m2 = m1; equivale a m2.operator=(m1);
La condicion this != &der previene la asignacion innecesaria o incorrecta de un objeto
a s mismo (ejemplo: m1 = m1;).
El tipo de retorno muestra& y el return
*
this permiten realizar asignaciones
encadenadas (ejemplo: m4 = m3 = m2 = m1;), manteniendo el comportamiento del
operador de asignacion en C++.
FI UPV: Curso 2009/2010 Pagina 1.77
EDA-Tema1
Clases en C++
Compilacion separada
La denicion de una clase se sit ua en un chero de cabecera .h con el nombre apropiado
(por ejemplo, el mismo que el de la clase).
La implementacion de los metodos se sit ua en un chero de codigo .cc con el mismo
nombre que el de la cabecera (el cual debe incluir).
Al compilar una aplicacion formada por modulos que a su vez requiren otros, un chero de
cabecera puede llegar a incluirse mas de una vez. Para evitar problemas, conviene englobar
el chero de cabecera dentro de una directiva #ifndef de la siguiente forma:
1 #ifndef NOMBRE
2 #define NOMBRE
3
4 // declaracion de la clase, etc.
5
6 #endif // que cierra el #ifndef NOMBRE
FI UPV: Curso 2009/2010 Pagina 1.78
EDA-Tema1
Ejemplo (I)
Fichero muestra.h
1 #ifndef _MUESTRA_
2 #define _MUESTRA_
3 class muestra {
4 int tam,
*
vector;
5 public:
6 muestra(int tamanyo); // constructor
7 muestra(); // otro constructor, cero argumentos
8 muestra(); // destructor
9 muestra(const muestra& der); // constructor de copia
10 muestra& muestra::operator=(const muestra &der); // operador= de copia
11 void procesar(int numero);
12 int obtener_moda();
13 };
14 #endif // de #define _MUESTRA_
FI UPV: Curso 2009/2010 Pagina 1.79
EDA-Tema1
Ejemplo (II)
Fichero muestra.cc
1 #include "muestra.h"
2 muestra::muestra(int tamanyo) { // valores a procesar entre 0 y tam-1
3 tam = tamanyo;
4 vector = new int[tamanyo];
5 for (int i=0; i<tam;i++) vector[i] = 0;
6 }
7 muestra::muestra() { }
8 muestra::muestra() { delete[] vector; }
9 muestra::muestra(const muestra& der) { // constructor de copia
10 tam = der.tam;
11 vector = new int[tam];
12 for (int i=0; i<tam;i++) vector[i] = der.vector[i];
13 }
14 void muestra::procesar(int numero) {
15 vector[numero]++;
16 }
17 int muestra::obtener_moda() {
18 int i,max,imax;
19 max = vector[0]; imax = 0;
FI UPV: Curso 2009/2010 Pagina 1.80
EDA-Tema1
Ejemplo (III)
Fichero muestra.cc
20 for (i=1; i < tam; i++) {
21 if (vector[i] > max) {
22 max = vector[i]; imax = i;
23 }
24 }
25 return imax;
26 }
27 muestra& muestra::operator=(const muestra &der) { // operador= de copia
28 if (this != &der) {
29 tam = der.tam; vector = new int[tam];
30 for (int i=0; i<tam;i++) vector[i] = der.vector[i];
31 }
32 return (
*
this);
33 }
Compilacion de muestra.o
g++ -c muestra.cc
FI UPV: Curso 2009/2010 Pagina 1.81
EDA-Tema1
Ejemplo (IV)
Fichero ppal.cc
1 #include <iostream>
2 using namespace std;
3 #include "muestra.h"
4 const int tam = 30000;
5 int main() {
6 muestra m1(tam),m2;
7 int num;
8 while (cin >> num) {
9 cout << "Proceso valor " << num << endl;
10 m1.procesar(num);
11 }
12 cout << "La moda es " << m1.obtener_moda() << endl;
13 m2 = m1; // se utiliza operador =
14 cout << "La moda es " << m2.obtener_moda() << endl;
15 muestra m3(m1); // se utiliza el constructor de copia
16 cout << "La moda es " << m3.obtener_moda() << endl;
17 }
Compilacion de ppal
g++ -o ppal ppal.cc muestra.o
FI UPV: Curso 2009/2010 Pagina 1.82
EDA-Tema1
Sobrecarga de operadores en clases
La sobrecarga de operadores permite denir el comportamiento de operadores predenidos
en C++ para operandos que sean objetos de clases.
Para ello, en la denicion de la clase (o externamente a ella, siendo uno de los argumentos
un objeto de la clase) declaramos e implementamos funciones que se nombran mediante la
palabra operator y el smbolo del correspondiente operador.
Si la declaracion es externa, se hace exactamente igual a como se vio con funciones. Pero si
es interna, un operador de aridad n se implementa como un metodo de aridad n 1 y el
primer argumento es siempre el propio objeto:
1 #include <iostream> // fichero ejoperator2.h
2 using namespace std;
3 class complejo {
4 double real,imaginaria;
5 public:
6 complejo();
7 complejo(double re, double im);
8 complejo operator + (const complejo& c2);
9 friend ostream& operator << (ostream &s, complejo c);
10 };
11 ostream& operator << (ostream &s, complejo c);
FI UPV: Curso 2009/2010 Pagina 1.83
EDA-Tema1
1 #include "ejoperator2.h" // fichero ejoperator2.cc
2 complejo::complejo() {};
3 complejo::complejo(double re, double im) {
4 real = re; imaginaria = im;
5 }
6 complejo complejo::operator+(const complejo& c2) {
7 complejo temp;
8 temp.real = real + c2.real;
9 temp.imaginaria = imaginaria + c2.imaginaria;
10 return temp;
11 }
12 ostream& operator << (ostream &s, complejo c) {
13 return s << c.real << ((c.imaginaria >= 0) ? "+" : "")
14 << c.imaginaria << i;
15 }
FI UPV: Curso 2009/2010 Pagina 1.84
EDA-Tema1
Fichero: usaoperator.cc
1 #include <iostream>
2 using namespace std;
3 #include "ejoperator2.h"
4 int main() {
5 complejo c1(2,3),c2(1,1);
6 cout << c1 << " + " << c2 << " = "
7 << c1+c2 << endl;
8 }
Salida: 2+3i + 1+1i = 3+4i
FI UPV: Curso 2009/2010 Pagina 1.85
EDA-Tema1
Sobrecarga de operadores en clases
Otro ejemplo: chero tupla.h
1 #ifndef TUPLA
2 #define TUPLA
3 #include <iostream>
4 using namespace std;
5 class tupla {
6 int x,y;
7 public:
8 tupla(); tupla(int x, int y); // dos constructores
9 bool operator < (const tupla& otra) const;
10 bool operator > (const tupla& otra) const;
11 bool operator <= (const tupla& otra) const;
12 bool operator >= (const tupla& otra) const;
13 bool operator == (const tupla& otra) const;
14 bool operator != (const tupla& otra) const;
15 tupla operator + (const tupla& otra) const;
16 tupla operator - (const tupla& otra) const;
17 void imprime(ostream &s) const;
18 };
19 ostream& operator << (ostream& s, const tupla& t);
20 #endif // de #ifndef TUPLA
FI UPV: Curso 2009/2010 Pagina 1.86
EDA-Tema1
Fichero tupla.cc
1 #include "tupla.h"
2 tupla::tupla(int x, int y) { // constructor
3 this->x = x;
4 this->y = y;
5 }
6 tupla::tupla() { // constructor
7 x = y = 0;
8 }
9 bool tupla::operator < (const tupla& otra) const {
10 return (x < otra.x) || (x == otra.x && y < otra.y);
11 }
12 bool tupla::operator > (const tupla& otra) const {
13 return (x > otra.x) || (x == otra.x && y > otra.y);
14 }
15 bool tupla::operator <= (const tupla& otra) const {
16 return (x < otra.x) || (x == otra.x && y <= otra.y);
17 }
18 bool tupla::operator >= (const tupla& otra) const {
19 return (x > otra.x) || (x == otra.x && y >= otra.y);
20 }
FI UPV: Curso 2009/2010 Pagina 1.87
EDA-Tema1
21 bool tupla::operator == (const tupla& otra) const {
22 return (x == otra.x) && (y == otra.y);
23 }
24 bool tupla::operator != (const tupla& otra) const {
25 return (x != otra.x) || (y != otra.y);
26 }
27 tupla tupla::operator + (const tupla& otra) const {
28 return tupla(x+otra.x,y+otra.y);
29 }
30 tupla tupla::operator - (const tupla& otra) const {
31 return tupla(x-otra.x,y-otra.y);
32 }
33 void tupla::imprime(ostream &s) const {
34 s << ( << x << , << y << );
35 }
36 ostream& operator << (ostream& s, const tupla& t) {
37 t.imprime(s);
38 return s;
39 }
FI UPV: Curso 2009/2010 Pagina 1.88
EDA-Tema1
Fichero tupla ppal.cc
1 #include <iostream>
2 using namespace std;
3 #include "tupla.h"
4 int main() {
5 tupla t1(1,2), t2(2,1), t3(t1), t4;
6 t4 = t2+t3;
7 cout << t2 << " + " << t3 << " = " << t4 << endl
8 << "La menor de " << t1 << " y de " << t2
9 << " es " << ((t1 < t2) ? t1 : t2) << endl;
10 }
FI UPV: Curso 2009/2010 Pagina 1.89
EDA-Tema1
Sobrecarga del operador de indexacion [ ]
El operador de indexacion [] tiene sentido denirlo en clases que representen colecciones
y en las que se acceda a elementos individuales.
Los elementos a los que se accede deben poder leerse o escribirse (la indexacion puede
aparecer a la derecha o a la izquierda de una asignacion).
El tipo de retorno de la indexacion debe ser una referencia.
Hay que considerar 2 posibilidades: que el objeto sea constante o que no lo sea. Por ello
hay que denir 2 instancias del mismo metodo, una para valores constantes y la otra para
no constantes.
Esquema:
const tipo_contenido& clase::operator [] (tipo_indice) const;
tipo_contenido& clase::operator [] (tipo_indice);
Ejemplo: Clase que simula un tipo de datos diccionario o map (mas adelante veremos la
clase map que ofrece la librera stl).
Vamos a implementar un diccionario que asocia a cada clave (una cadena) un valor (otra
cadena). Se utilizara una lista enlazada, con lo que el coste de b usqueda es lineal. . .
FI UPV: Curso 2009/2010 Pagina 1.90
EDA-Tema1
1 #ifndef MIMAP
2 #define MIMAP
3 #include <string>
4 #include <iostream>
5 using namespace std;
6 typedef string tipoclave; typedef string tipovalor;
7 class nodo_map {
8 public:
9 tipoclave clave;
10 tipovalor valor;
11 nodo_map
*
siguiente;
12 };
13 class mimap {
14 nodo_map
*
cabeza_lista;
15 public:
16 mimap(); mimap(); // constructor y destructor
17 const tipovalor & operator [] (tipoclave clv) const;
18 tipovalor & operator [] (tipoclave clv);
19 void imprime(ostream& s) const;
20 };
21 ostream& operator << (ostream &s, const mimap& m);
22 #endif // de #ifndef MIMAP
FI UPV: Curso 2009/2010 Pagina 1.91
EDA-Tema1
1 #include "mimap.h"
2 mimap::mimap() { // constructor
3 cabeza_lista = 0;
4 }
5 mimap::mimap() { //destructor
6 while (cabeza_lista != 0) {
7 nodo_map
*
r = cabeza_lista;
8 cabeza_lista = cabeza_lista->siguiente;
9 delete r;
10 }
11 }
12 const tipovalor & mimap::operator [] (tipoclave clv) const {
13 nodo_map
*
r = cabeza_lista;
14 while (r != 0 && r->clave != clv)
15 r = r->siguiente;
16 return r->valor; // daria error si clv no esta en el diccionario
17 }
FI UPV: Curso 2009/2010 Pagina 1.92
EDA-Tema1
18 tipovalor & mimap::operator [] (tipoclave clv) {
19 nodo_map
*
r = cabeza_lista;
20 while (r != 0 && r->clave != clv) r = r->siguiente;
21 if (r == 0) {
22 r = new nodo_map;
23 r->clave = clv;
24 r->siguiente = cabeza_lista;
25 cabeza_lista = r;
26 }
27 return r->valor;
28 }
29 void mimap::imprime(ostream& s) const {
30 const nodo_map
*
r;
31 s << [;
32 for(r = cabeza_lista; r != 0; r = r->siguiente)
33 s << ( << r->clave << , << r->valor << )
34 << ((r->siguiente == 0) ? ] : ,);
35 }
36 ostream& operator << (ostream &s, const mimap& m) {
37 m.imprime(s);
38 return s;
39 }
FI UPV: Curso 2009/2010 Pagina 1.93
EDA-Tema1
1 #include <iostream>
2 #include <string>
3 using namespace std;
4 #include "mimap.h"
5 int main() {
6 mimap m;
7 m[string("uno")] = string("one");
8 m[string("dos")] = string("two");
9 m[string("tres")] = string("three");
10 cout << "El diccionario es: " << m << endl
11 << "El valor de uno es " << m[string("uno")] << endl;
12 }
FI UPV: Curso 2009/2010 Pagina 1.94
EDA-Tema1
Ejercicio
la clase pila
Crea una clase que implemente una pila de enteros utilizando una representacion mediante
lista enlazada.
Debes de sobrecargar el operador de asignacion y el constructor de copia porque no sirve la
asignacion miembro a miembro.
Tambien sera conveniente sobrecargar el operador << de la clase ostream.
Sobrecargar el operador de indexacion para que m[0] se reera al tope de la pila, m[1] al
objeto por debajo, etc. donde m es una variable de tipo pila.
FI UPV: Curso 2009/2010 Pagina 1.95
EDA-Tema1
Libreras estandar
Libreras estandar ISO C.
Nombre C++ Contenido
<cassert> Dene la macro assert
<cctype> Clasicacion lexicograca de caracteres
<cerrno> Tratamiento de errores
<cfloat> Valores oat dependientes de implementacion
<climits> Limites numericos dep. implem.
<cmath> Deniciones y funciones matematicas
<cstdarg> Para implementar paso argumentos variable
<cstdio> Entrada y salida estandar
<cstdlib> Funciones estandar
<cstring> Manipulacion cadenas terminadas en \0
<ctime> Medida de tiempo del sistema
Librera <ctime> para la medida de tiempos.
La librera y la clase string.
La librera stl (Standard Template Library).
<vector> Para acceder a elementos por su posici on.
<list> Para acceder a los elementos de manera secuencial.
<set> Para representar conjuntos y determinar pertenencia.
<map> Para guardar valores asociados a una clave unica.
FI UPV: Curso 2009/2010 Pagina 1.96
EDA-Tema1
Libreras estandar: medidas de tiempo
Se utiliza la librera <ctime>, algunos tipos y funciones:
clock_t Tipo similar a un long
clock_t clock() Retorna el n umero de tics de reloj
CLOCKS_PER_SEC Constante para transformar tics a segundos
1 clock_t t_inicial = clock();
2 g(); // queremos medir lo que tarda una llamada
3 // a esta funcion en segundos
4 double tiempo = (clock() - t_inicial)/(double)CLOCKS_PER_SEC;
FI UPV: Curso 2009/2010 Pagina 1.97
EDA-Tema1
Libreras estandar: medidas de tiempo
El reloj tiene una precision bastante limitada. Para medir cosas con mayor precision, siempre
que se pueda repetir varias veces esas operaciones sin problema, podemos hacer lo siguiente:
1 clock_t t_inicial, t_final;
2 double t;
3 int iteraciones = 0;
4 do {
5 // aqui codigo para preparar la llamada a g();
6 t_inicial = clock();
7 g(); // queremos medir lo que tarda una llamada
8 // a esta funcion en segundos
9 t_final = clock();
10 t += (t_final - t_inicial)/(double)CLOCKS_PER_SEC;
11 iteraciones++;
12 } while (t < 0.01); // este valor puede variar...
13 t /= iteraciones;
FI UPV: Curso 2009/2010 Pagina 1.98
EDA-Tema1
Cadenas: La clase string
Del lenguaje C sabemos que es posible utilizar funciones sobre secuencias de caracteres
terminadas en \0 utilizando las libreras <cstring> y <cstdlib>. Existen funciones
de conversion entre cadenas y otros tipos de datos en la librera <cctype>.
No obstante, C++ nos ofrece una representacion de cadenas de caracteres alternativa a
utilizar punteros a char, se trata de la clase string denida en la libreria <string>
y que tiene las siguientes caractersticas:
Se copia en las asignaciones (a tener muy en cuenta).
Tiene comprobacion de lmites y permite trabajar con operadores sobrecarga-
dos (puedes usar comparaciones del estilo c1 < c2 en lugar de cosas como
strcmp(c1,c2) < 0).
La clase string incluye mas de 5 constructores y una gran cantidad de metodos, entre
los cuales citamos: length, size, max_size, resize, capacity, reserve,
clear, empty, begin, end, append, assign, insert, erase, replace, copy,
swap, data, find, substr, compare, etc.
FI UPV: Curso 2009/2010 Pagina 1.99
EDA-Tema1
STL: Librera estandar vector
El contenedor vector permite realizar operaciones de insercion y eliminacion al nal con
coste temporal constante.
Las inserciones en cualquier otro lugar tienen coste temporal lineal.
Soporta acceso directo a cualquier elemento.
Ejemplo:
1 #include <iostream>
2 using namespace std;
3 #include <vector>
4 typedef vector<float> vector_de_floats;
5 int main() {
6 vector_de_floats vf;
7 vf.push_back(3.5); // inserta 3.5 al final
8 vf.push_back(2.8); // inserta 2.8 al final, i.e. [3.5,2.8]
9 vf.push_back(4.3); // inserta 2.8 al final, i.e. [3.5,2.8,4.3]
10 vf[1] =5.7; // coloca 5.7 en la posicion 1, i.e. [3.5,5.7,4.3]
11 vf.pop_back(); // borra el ultimo elemento, i.e. [3.5,5.7]
12 for (vector_de_floats::iterator i=vf.begin(); i != vf.end(); i++)
13 cout <<
*
i << endl;
14 }
FI UPV: Curso 2009/2010 Pagina 1.100
EDA-Tema1
STL: Librera estandar list
El contenedor list implementa una lista bidireccional. En una lista se puede acceder
solo secuencialmente.
Se puede acceder del inicio al nal con los metodos begin() y end().
Podemos tener varios iteradores accediendo a distintas partes de la lista.
Ejemplo:
1 #include <iostream>
2 using namespace std;
3 #include <list>
4 typedef list<int> lista_enteros;
5 ostream& operator << (ostream& s, lista_enteros &l) {
6 lista_enteros::iterator i;
7 s << [; i = l.begin();
8 while (i != l.end())
9 { s <<
*
i; i++; if (i != l.end()) s << ,; else s << ]; }
10 return s;
11 }
FI UPV: Curso 2009/2010 Pagina 1.101
EDA-Tema1
12 int main() {
13 lista_enteros mi_lista;
14 mi_lista.insert(mi_lista.begin(),23); // insertamos 23 al ppio
15 mi_lista.push_front(1); // insertamos 1 al ppio de la lista
16 mi_lista.push_back(12); // insertamos 12 al final de la lista
17 cout << "La lista es: " << mi_lista << endl;
18 }
FI UPV: Curso 2009/2010 Pagina 1.102
EDA-Tema1
STL: Librera estandar set
El contenedor set implementa un conjunto. No soporta elementos duplicados.
1 #include <iostream>
2 using namespace std;
3 #include <set>
4 class tupla {
5 int x,y;
6 public:
7 tupla(int,int);
8 bool operator < (const tupla& t2) const;
9 };
10 tupla::tupla(int u,int v) { x = u; y = v; }
11 bool tupla::operator < (const tupla& t2) const {
12 return ((x < t2.x) or ((x == t2.x) and (y < t2.y)));
13 }
14 typedef set<tupla> conjunto_tuplas;
FI UPV: Curso 2009/2010 Pagina 1.103
EDA-Tema1
15 int main() {
16 conjunto_tuplas cjt_tpl;
17 cjt_tpl.insert(tupla(1,2));
18 cjt_tpl.insert(tupla(5,7));
19 cout << "Introduce tupla: ";
20 int x,y; cin >> x >> y; tupla t(x,y);
21 if (cjt_tpl.count(t) > 0)
22 cout << "La tupla esta en el conjunto\n";
23 else
24 cout << "La tupla introducida no pertenece al conjunto\n";
25 }
FI UPV: Curso 2009/2010 Pagina 1.104
EDA-Tema1
STL: Librera estandar map
El contenedor map sirve para guardar pares (clave,valor) donde las claves no pueden estar
duplicadas. Permite realizar b usquedas rapidas basandose en la clave.
1 #include <iostream>
2 using namespace std;
3 #include <string>
4 #include <map>
5 typedef map<int,string> diccionario;
6 int main() {
7 diccionario d;
8 d[1] = string("uno"); d[2] = string("dos");
9 d[30] = string("treinta"); d[2000] = string("dos mil");
10 cout << "Introduce un valor: ";
11 int valor; cin >> valor;
12 diccionario::iterator it = d.find(valor);
13 if (it != d.end()) {
14 cout<<"El valor de "<<it->first<<" es "<<it->second<<endl;
15 } else
16 cout << "No encontrado\n";
17 }
FI UPV: Curso 2009/2010 Pagina 1.105
EDA-Tema1
Terminacion anormal de un programa
Para salir directamente de un programa existen dos funciones denidas en <cstdlib>
void abort();
void exit(int Estado);
La funcion exit realiza una serie de pasos que no realiza abort: llamar funciones
registradas en atexit(), llamar a los destructores de objetos globales y estaticos, cerrar
los cheros abiertos, liberar memoria ocupada.
FI UPV: Curso 2009/2010 Pagina 1.106
EDA-Tema1
Palabras clave
asm auto bool break case
catch char class const const cast
continue default delete do double
dynamic cast else enum explicit export
extern false oat for friend
goto if inline int long
mutable namespace new operator private
protected public register reinterpret cast return
short signed sizeof static static cast
struct switch template this throw
true try typedef typeid typename
union unsigned using virtual void
volatile wchar t while
FI UPV: Curso 2009/2010 Pagina 1.107

Вам также может понравиться