Sei sulla pagina 1di 7

Exámen de LP.

Junio 2006

1. (2 puntos) Detecta los posibles errores en los siguientes segmentos de programa e intenta corregirlos razonando
su corrección:
(a) c l a s s Empleado {
public :
Empleado ( i nt s ) : s a l a r i o ( s ) {}
i nt L e e S a l a r i o ( ) { return s a l a r i o ; }
protected :
i nt s a l a r i o ;
};
class Estudiante {
public :
E s t u d i a n t e ( f l o a t no ) : no ta ( no ) {}
void Mo difica No ta ( f l o a t &no = 0 ) { no ta = no ; }
protected :
f l o a t no ta ;
};
c l a s s B e c a r i o : private Empleado , public E s t u d i a n t e {
public :
B e c a r i o ( ) {}
B e c a r i o ( char ∗n , i nt s , f l o a t no )
{ s t r c p y ( nombre , n ) ; }
char ∗LeeNombre ( ) { return nombre ; }
private :
char nombre [ 3 0 ] ;
};
i nt main ( )
{
B e c a r i o b1 ( ” Pepe” , 3 0 0 , 7 . 5 ) ;
v e c t o r <B e c a r i o> v e c t o r b ;
v e c t o r <B e c a r i o > : : i t e r a t o r i t e ;
co ut << ” S a l a r i o : ” << b1 . L e e S a l a r i o ( ) << e n d l ;
v e c t o r b . push ba ck ( b1 ) ;
i t e = vectorb . begin ( ) ;
co ut <<”Nombre : ” << i t e . LeeNombre ( ) <<e n d l ;
return 0 ;
}

Solución:

el parámetro no de ModificaNota no puede tener valor por defecto pues se toma por referencia
el constructor vacı́o de Becario ha de llamar a los constructores adecuados de Empleado y
Estudiante por ejemplo con Becario( ):Estudiante(0.0), Empleado(0){}
en el otro constructor ocurre lo mismo. Debe ser
B e c a r i o ( char ∗n , i nt s , f l o a t no ) : E s t u d i a n t e ( no ) , Empleado ( s ) {
s t r c p y ( nombre , n ) ;
}

no podemos acceder al método LeeSalario() de Becario pues, al heredar de manera privada lo


ha ocultado. Deberı́a heredar publicamente para poder usarlo.
si ite es un iterador, para usar el método hay que hacer ite->LeeNombre()

(b) i nt main ( )
{ enum { Norte , Sur , Este , O este } zona ;
char ∗ p u n t o s C a r d i n a l e s [ ] = { ” Norte ” , ” Sur ” , ” E ste ” , ” O este ” } ;
char ∗nombre ;

Página 1 de 7
Exámen de LP. Junio 2006

try {
co ut << ” \ n I n t r o d u c e e l nombre de l a zona : ” ;
c i n >> nombre ;
co ut << ” \ n I n t r o d u c e e l punto c a r d i n a l : ” ;
c i n >> zona ;
i f ( zona == ” Norte ” )
throw 0 ;
e l s e cout<<” \nLa zona e s : ” <<p u n t o s C a r d i n a l e s [ zona ] ;
catch ( i nt )
{ co ut << ” \ nHace mucho f r i o . \ n” ; }
}
return 0 ;
}

Solución:

a un enumerado no se le puede asignar un entero, al revés sı́. En lugar de pedir zona deberı́a
pedirse un entero numZona y luego cambiar la linea de comparación if ( zona == "Norte" )
por if ( numZona == Norte ) y luego obtener el nombre con puntosCardinales[numZona]
falta una llave de cierre antes de catch
sobra la llave que hay antes de return

2. (2.5 puntos) Supongamos que tenemos un fichero de nombre “Clasificacion” para almacenar los datos de las
distintas selecciones de fútbol que participan en el mundial (no están ordenados por ningún criterio). Para ello,
la estructura empleada es la siguiente:
const i nt TAM1 ( 6 ) ;
const i nt TAM2 ( 2 0 ) ;
struct Tequipo
{ char c o d i g o [ TAM1 ] ; // Formado por 4 d i g i t o s y un c a r a c t e r
char s e l e c c i o n [ TAM2 ] ; // Con t ien e e l nombre de l a s e l e c c i o n
unsigned i nt p a r t i d o s J u g a d o s : 5 ;
unsigned i nt : 0 ;
unsigned i nt p a r t i d o s G a n a d o s : 5 ;
unsigned i nt p a r t i d o s P e r d i d o s : 5 ;
unsigned i nt pa r tido sE mpa ta do s : 5 ;
};

Teniendo en cuenta dicho fichero, y sin usar ningún fichero auxiliar, hay que implementar:
(a) (1 punto) una función que permita añadir al final del fichero una nueva selección (todavı́a no ha jugado
ningún partido del mundial). Esta función deberá leer del teclado el código (debe validarse) y el nombre de
la selección, y almacenarlos en el fichero;

Solución:
void l e e r E q u i p o ( ) {
Tequipo e q u i p o ;
o f s t r e a m c l a s i f i c a c i o n ( ” C l a s i f i c a c i o n ” , i o s : : app | i o s : : b i n a r y ) ;
char c o d i g o [TAM1 ] ;
do{
co ut << ” Codigo d e l e q u i p o : ” ;
c i n >> c o d i g o ;
} while ( ! c o d i g o C o r r e c t o ( c o d i g o ) ) ;
s t r n c p y ( e q u i p o . c o d i g o , c o d i g o , TAM1) ;
co ut << ”Nombre d e l e q u i p o : ” ;
cin . ignore ( ) ;
c i n . g e t l i n e ( e q u i p o . s e l e c c i o n , TAM2) ;

Página 2 de 7
Exámen de LP. Junio 2006

e q u i p o . p a r t i d o s J u g a d o s =0;
e q u i p o . pa r tido sE mpa ta do s =0;
e q u i p o . p a r t i d o s G a na d o s=0;
e q u i p o . p a r t i d o s P e r d i d o s =0;
c l a s i f i c a c i o n . w r i t e ( ( char ∗ ) &equipo , s i z e o f ( Tequipo ) ) ;
clasificacion . close ();
}
bool c o d i g o C o r r e c t o ( char ∗ c o d i g o ) {
for ( i nt n= 0 ; n<3; n++){
i f ( ! i s d i g i t ( codigo [ n ] ) ) {
return f a l s e ;
}
}
i f ( ! isalpha ( codigo [ 4 ] ) ) {
return f a l s e ;
}
return true ;
}

(b) (1.5 puntos) una función que actualice los datos almacenados en el fichero a partir de los resultados obtenidos
en los partidos jugados en una determinada jornada (se supone que una selección sólo puede jugar un partido
en una jornada). Estos resultados serán proporcionados a la función mediante un parámetro de tipo jornada,
estructura descrita a continuación:
struct j o r n a d a
{ unsigned i nt numero ; // I n d i c a e l numero de p a r t i d o s j u g a d o s .
partido ∗ vector ; // Puntero a un a r r a y din amico cu yos e l e m e n t o s
// r e f l e j a n l o s d a t o s n e c e s a r i o s de cada p a r t i d o
};
Donde la estructura partido corresponde a:
struct p a r t i d o
{ char c o d i g o 1 [ TAM1 ] ; // Codigo d e l primer e q u i p o p a r t i c i p a n t e
char c o d i g o 2 [ TAM1 ] ; // Codigo d e l segu n do e q u i p o p a r t i c i p a n t e
unsigned i nt g o l e s 1 : 4 ; // Numero de g o l e s marcados por e l primer e q u i p o
unsigned i nt g o l e s 2 : 4 ; // Numero de g o l e s marcados por e l segu n do e q u i p o
};

Solución:
void a c t u a l i z a r ( j o r n a d a j ) {
Tequipo e q u i p o ;
i nt numPartido = 0 ;
f s t r e a m c l a s i f i c a c i o n ( ” C l a s i f i c a c i o n ” , i o s : : i n | i o s : : out | i o s : : b i n a r y ) ;
str ea mpo s a c t u a l = c l a s i f i c a c i o n . t e l l g ( ) ;
c l a s i f i c a c i o n . r ea d ( ( char ∗ ) &equipo , s i z e o f ( Tequipo ) ) ;
while ( ! c l a s i f i c a c i o n . e o f ( ) ) {
numPartido = busca r E quipo ( j , e q u i p o . c o d i g o ) ;
i f ( numPartido >= 0 ) { // e q u i p o e n c o n t r a d o
e q u i p o . p a r t i d o s J u g a d o s++;
i nt g o l e s 1 = j . v e c t o r [ numPartido ] . g o l e s 1 ;
i nt g o l e s 2 = j . v e c t o r [ numPartido ] . g o l e s 2 ;
i f ( ! strcmp ( e q u i p o . c o d i g o , j . v e c t o r [ numPartido ] . c o d i g o 1 ) ) {
i f ( g o l e s 1 > g o l e s 2 ){
e q u i p o . p a r t i d o s G a n a d o s++;
} else i f ( g o l e s 2 > g o l e s 1 ){
e q u i p o . p a r t i d o s P e r d i d o s++;

Página 3 de 7
Exámen de LP. Junio 2006

} else{
e q u i p o . pa r tido sE mpa ta do s++;
}
} e l s e i f ( ! strcmp ( e q u i p o . c o d i g o , j . v e c t o r [ numPartido ] . c o d i g o 2 ) ) {
i f ( g o l e s 1 < g o l e s 2 ){
e q u i p o . p a r t i d o s G a n a d o s++;
} else i f ( g o l e s 2 < g o l e s 1 ){
e q u i p o . p a r t i d o s P e r d i d o s++;
} else{
e q u i p o . pa r tido sE mpa ta do s++;
}
}
c l a s i f i c a c i o n . seekp ( actual ) ;
c l a s i f i c a c i o n . w r i t e ( ( char∗)& equipo , s i z e o f ( Tequipo ) ) ;
}

actual = c l a s i f i c a c i o n . t e l l g ( ) ;
c l a s i f i c a c i o n . r ea d ( ( char ∗ ) &equipo , s i z e o f ( Tequipo ) ) ;
}
}
i nt busca r E quipo ( j o r n a d a j , char ∗ c o d i g o ) {
for ( i nt n=0; n< j . numero ; n++){
i f ( ! strcmp ( c o d i g o , j . v e c t o r [ n ] . c o d i g o 1 ) ) {
return n ;
}
i f ( ! strcmp ( c o d i g o , j . v e c t o r [ n ] . c o d i g o 2 ) ) {
return n ;
}
}
return −1;
}

3. (3.25 puntos) Dadas las clases nodo y cola de la práctica 10.5 que implementan una cola de enteros (suponer
implementadas las funciones miembro que aquı́ aparecen):
c l a s s nodo {
nodo ∗ s i g u i e n t e ;
i nt numero ;
public :
void e n l a z a r ( nodo ∗n ) { s i g u i e n t e=n ; }
nodo ∗ d e v o l v e r s i g u i e n t e ( ) { return s i g u i e n t e ; }
void c a r g a r n o d o ( i nt e ) { numero=e ; }
i nt s a c a r n o d o ( ) { return numero ; }
nodo ( ) { s i g u i e n t e =0;}
};
class cola {
nodo ∗ p r i n c i p i o ;
nodo ∗ f i n a l ;
public :
c o l a ( ) { p r i n c i p i o= f i n a l =0;}
i nt v a c i a ( ) ;
void a lma cena r ( i nt e ) ;
i nt s a c a r ( ) ;
};

(a) (1 punto) ¿Por qué el siguiente código no es correcto? Añade lo necesario para que funcione adecuadamente
c o l a c1 , c2 ;

Página 4 de 7
Exámen de LP. Junio 2006

c1 . a lma cena r ( 1 ) ;
c2=c1 ;
cout<< c1 . s a c a r ()<< e n d l ;
cout<< c2 . s a c a r ()<< e n d l ;

Solución:
Para hacer c2=c1 necesitamos sobrecargar operador de asignacion, si no se copiarán los punteros.
class cola {
...
// agregamos o p e r a d o r de a s i g n a c i o n
c o l a & operator=(const c o l a &);
};
c o l a & c o l a : : operator=(const c o l a &c ) {
while ( ! v a c i a ( ) ) {
sacar ( ) ;
}
nodo ∗ next = c . p r i n c i p i o ;
while ( next != 0 ) {
a lma cena r ( next−>s a c a r n o d o ( ) ) ;
next = next−>d e v o l v e r s i g u i e n t e ( ) ;
}
return ∗ t h i s ;
}

(b) (2.25 puntos) Añade lo necesario para que la siguiente secuencia de instrucciones sea también correcta:
c o l a c3 , c4 ;
c3 = c1+c2 ;
c4 = 1+c3 ;
cout<<c3<<c4 ;

Solución:
Para hacer c1+c2 sobrecargamos el operator+ y creamos una función global para que sume a un entero
una cola. Para poder crear copias de colas necesitaremos también un constructor de copias. También
haremos una función operator global para que un flujo pueda recibir una cola.
class cola {
...
// agregamos c o n s t r u c t o r y o p e r a t o r+
c o l a ( const c o l a &c ) {
c o l a operator+(const c o l a &c ) {
};
c o l a c o l a : : operator+(const c o l a &c ) {
co la a (∗ this ) ;
nodo ∗ next = c . p r i n c i p i o ;
while ( next != 0 ) {
a lma cena r ( next−>s a c a r n o d o ( ) ) ;
next = next−>d e v o l v e r s i g u i e n t e ( ) ;
}
return a ;
}
c o l a operator+( i nt n , c o l a &c ) {
cola a( c ) ;
a . a lma cena r ( n ) ;
return a ;
}
c o l a : : c o l a ( const c o l a &c ) {

Página 5 de 7
Exámen de LP. Junio 2006

p r i n c i p i o= f i n a l =0;
nodo ∗ next = c . p r i n c i p i o ;
while ( next != 0 ) {
a lma cena r ( next−>s a c a r n o d o ( ) ) ;
next = next−>d e v o l v e r s i g u i e n t e ( ) ;
}
return ∗ t h i s ;
}
o str ea m& operator <<(o str ea m& out , c o l a &c ) {
nodo ∗ next = c . p r i n c i p i o ;
while ( next ) {
out << next−>s a c a r n o d o ( ) ;
next = next−>d e v o l v e r s i g u i e n t e ( ) ;
}
return out ;
}

4. (2.25 puntos) Para un programa de gestión de una Librerı́a se tienen las clases Autor y Publicación siguientes:
c l a s s Autor {
private :
s t r i n g nombre ;
public :
Autor ( const s t r i n g &n ) { nombre=n ; }
s t r i n g getNombre ( ) { return nombre ; }
};
class Publicacion {
private :
s tr i n g codigo ;
public :
P u b l i c a c i o n ( const s t r i n g &c ) { c o d i g o=c ; }
s t r i n g g etCo dig o ( ) { return c o d i g o ; }
};

(a) (0.5 puntos) Define una clase Libro que contenga un Autor y que herede a partir de la clase Publicación.
Añade también a la clase una variable numEjemplares para almacenar el número de ejemplares de cada
libro que existen en la librerı́a. Implementa un constructor donde se le pasen (al menos) el número concreto
de ejemplares de ese libro y una función calcularEjemplares que devuelva el número de ejemplares de ese
libro.

Solución:
c l a s s L i b r o : public P u b l i c a c i o n {
Autor a u t o r ;
i nt numEjemplares ;
public :
L i b r o ( s t r i n g c o d i g o , s t r i n g nombre , i nt n )
: P u b l i c a c i o n ( c o d i g o ) , a u t o r ( nombre ) , numEjemplares ( n ){
}
i nt c a l c u l a r E j e m p l a r e s ( ) {
return numEjemplares ;
}
};

(b) (0.5 puntos) A partir de la clase Publicación define una clase Revista con dos variables volumenes y numeros.
Implementa un constructor al que se le pasen (al menos) el número de volúmenes de los que consta la revista

Página 6 de 7
Exámen de LP. Junio 2006

y los números de cada volumen y una función calcularEjemplares que devuelva el numero de ejemplares de
esa revista (p.e. si volumenes es 4 y numeros 6 el total de ejemplares será 24).

Solución:
c l a s s R e v i s t a : public P u b l i c a c i o n {
i nt volumenes ;
i nt numEjemplares ;
public :
R e v i s t a ( s t r i n g c o d i g o , i nt n , i nt v )
: P u b l i c a c i o n ( c o d i g o ) , volumenes ( v ) , numEjemplares ( n ) {
}
i nt c a l c u l a r E j e m p l a r e s ( ) {
return numEjemplares ∗ volumenes ;
}
};

(c) (1 punto) Implementa una función calcularInventario( ) que reciba como argumento un vector de punteros
a publicación, apuntando a cada uno de los libros o revistas de la librerı́a y calcule utilizando ligadura
dinámica el total de ejemplares de la librerı́a.

Solución:
i nt c a l c u l a r I n v e n t a r i o ( P u b l i c a c i o n ∗ p u b l i c a c i o n e s [ ] , i nt n u m P u b l i c a c i o ne s ) {
i nt t o t a l = 0 ;
for ( i nt n=0; n<n u m P u b l i c a c i o n es ; n++){
t o t a l+=p u b l i c a c i o n e s [ n]−> c a l c u l a r E j e m p l a r e s ( ) ;
}
return t o t a l ;
}

(d) (0.25 puntos) Escribe un programa de prueba.

Solución:
i nt main ( ) {
Publicacion ∗ l i b r e r i a [ 3 ] ;
l i b r e r i a [ 0 ] = new L i b r o ( s t r i n g ( ” aaa ” ) , s t r i n g ( ” l a colmena ” ) , 2 ) ;
l i b r e r i a [ 1 ] = new R e v i s t a ( s t r i n g ( ”XXX” ) , 2 , 3 ) ;
l i b r e r i a [ 2 ] = new L i b r o ( s t r i n g ( ”bbb” ) , s t r i n g ( ” e l q u i j o t e ” ) , 8 ) ;
co ut << c a l c u l a r I n v e n t a r i o ( l i b r e r i a , 3 ) ;
}

Página 7 de 7