You are on page 1of 11

Exámen de LP.

Septiembre 2003

1. (2 puntos) Detecta los posibles errores en los siguientes segmentos de programa e intenta corregirlos razonando
su corrección:
(a) i n l i n e main ( )
{ i nt x , y ;
c i n >>x>>y ;
cout<<” El r e s u l t a d o de m u l t i p l i c a r x e y e s : ”<<m u l t i p l i c a r ( x , y ) ;
}
i nt m u l t i p l i c a r ( i nt &a , i nt b )
{ return ( ∗ a ) ∗ b ; }

Solución:

main no puede ser inline


en multiplicar esta accediendo al valor de a con *a, como si fuese un puntero, y solo es una
referencia. Deberı́a ser return a*b;
tampoco hace falta que se pase por referencia.

(b) f l o a t v ( 8 ) ;
f l o a t c a l c u l o ( f l o a t x=v , i nt y=1 , f l o a t z = 3 .5 )
{ return x+y+z ; }
bool f u n c i o n 1 ( )
{ i f ( c a l c u l o ( 3 . 2 , 7 ) ! = 1 0 ) return true ;
e l s e return f a l s e ; }

Solución:
a q u i to do c o r r e c t o

(c) i nt f u n c i o n 1 ( r e g i s t e r i nt x , f l o a t y )
{ extern i nt a ;
c i n >>a ;
return ( x−y)+a ; }

Solución:

function1 declara que devolverá un int pero devuelve un float.


es de suponer que el entero extern a estará definido en otra parte

(d) struct alumno


{ char nombre [ 4 0 ] ;
enum { Suspenso , Aprobado , Notable , S o b r e s a l i e n t e , M a t r i c u l a } no ta ; }
alumno c u r s o [ 1 5 0 ] ;
....
void v i s u a l i z a r ( alumno c u r s o [ ] )
{ char ∗ c a l i f i c a c i o n e s [ ]={ ” Suspenso ” , ” Aprobado” ,
” No ta ble ” , ” S o b r e s a l i e n t e ” , ” M a t r i c u l a ” } ;
for ( i nt i =1; i <=150; i ++)
{ cout<<”Alumno : ”<<c u r s o [ i ]<<” Nota : ”<< c a l i f i c a c i o n e s [ no ta ] ; }
}

Solución:

Página 1 de 11
Exámen de LP. Septiembre 2003

falta el ; después de la llave de la struct


el contador debe contar desde 0 hasta 149
debe mostrarse el nombre con curso[i].nombre y la nota con calificaciones[curso[i].nota]

2. (3 puntos) Completa los siguientes segmentos de programa para obtener las salidas indicadas:
(a) Con esta sentencia for se pretende calcular la siguiente suma: 1/2 + 1/3 + 1/4 + ... + 1/50
f l o a t suma ( 0 ) , j ;
i nt i =2;
for ( );
co ut <<” R e s u l t a d o : ”<<suma ;

Solución:
for ( j =2; j <=50; suma += ( 1 / j ++));

(b) El vector vector contiene las direcciones donde comienzan 10 cadenas tratadas como cadenas de caracteres:
char *vector[10]; La función ordenar recibe ese vector y ordena sus direcciones de forma que al recorrerlo
(después de ejecutarse la función) se obtiene a partir de él las cadenas ordenadas alfabéticamente. (Se puede
usar las funciones predefinidas para cadenas.)
void o r d e n a r ( )
{ char ∗temp ;
}

Solución:
#include <i o s t r e a m>
using namespace s t d ;
void o r d e n a r ( char ∗ v e c t o r [ ] , i nt s i z e ) {
char ∗ tmp ;
bool cambiado = true ;
i nt d i f f ;
while ( cambiado ) {
cambiado = f a l s e ;
for ( i nt n=0; n < s i z e −1; n++){
i f ( strcmp ( v e c t o r [ n ] , v e c t o r [ n+1] ) > 0 ) {
tmp=v e c t o r [ n ] ;
vector [ n ] = vector [ n+1];
v e c t o r [ n+1] = tmp ;
cambiado=true ;
}
}
}
}

(c) El siguiente programa usa punteros a funciones para obtener el mayor y menor de los elementos introducidos
en un array bidimensional
#include <i o s t r e a m . h>
const i nt f i l =5; const i nt c o l =5;
float buscar ( float matriz [ ] [ col ] , );
f l o a t mayor ( f l o a t x , f l o a t y);
f l o a t menor ( f l o a t x , f l o a t y);
i nt menu ( ) ;

Página 2 de 11
Exámen de LP. Septiembre 2003

void main ( )
{ f l o a t m a t r i z [ f i l ] [ c o l ]={ 0 } , ;
cout<<” I n t r o d u c e l o s e l e m e n t o s de l a m a t r i z \n” ;
for ( i nt i =0; i < f i l ; i ++)
for ( i nt j =0; j <c o l ; j ++) {
cout<<” Ma tr iz [ ”<<i <<” ] [ ”<<j <<” ] ” ; c i n >>m a t r i z [ i ] [ j ] ;
}
switch ( menu ( ) ) {
case 1 : p=mayor ; break ;
case 2 : p=menor ; break ;
}
cout<<” El elemento l o c a l i z a d o e s : ”<<b u s c a r ( ma tr iz , p)<<e n d l ;
}
i nt menu ( ) {
i nt op=0;
do {
cout<<”MENU\n 1 . Mayor\n 2 . Menor” ; c i n >>op ;
} while ( op < 1 ) | | ( op > 2 ) ) ;
return op ;
}
float buscar ( float matriz [ ] [ c o l ] , ) {
f l o a t r e s u l=m a t r i z [ 0 ] [ 0 ] ;
for ( i nt i =0; i < f i l ; i ++)
for ( i nt j =0; j <c o l ; j ++)
return r e s u l ;
}
f l o a t mayor ( f l o a t x , f l o a t y ) {
i f ( x>y )
return x ;
e l s e return y ;
}
f l o a t menor ( f l o a t x , f l o a t y ) {
i f ( x<y )
return x ;
e l s e return y ;
}

Solución:
El puntero p ha de declararse antes de su uso como:
float (∗p ) ( flo a tx , float y ) ;
Ha de agregarse también un segundo parámetro a la función buscar como:
float buscar ( float matriz [ ] [ c o l ] , float (∗p ) ( float x , float y ) ) ;
Dentro del bucle se llama a la función a la que apunte el puntero p
float r e s u l = matriz [ 0 ] [ 0 ] ;
for ( i nt i =0; i < f i l ; i ++){
for ( i nt j =0; j <c o l ; j ++){
r e s u l = p( r esul , matriz [ i ] [ j ] ) ;
}
return r e s u l ;
}

3. (2,5 puntos) Usando aritmética de punteros (no indexando los punteros ni los vectores) y sin emplear las funciones
predefinidas para cadenas (strlen, strcmp, etc), realiza un programa que lea del teclado una cadena de caracteres
cuyo tamaño es conocido en tiempo de ejecución, y que una función de dicho programa devuelva verdadero si

Página 3 de 11
Exámen de LP. Septiembre 2003

el contenido de dicha cadena es un palı́ndromo (palabra o frase que se lee igual de derecha a izquierda que en
sentido inverso) y falso en caso contrario.

Solución:

#include <i o s t r e a m>


using namespace s t d ;
bool e s p a l i n d r o m o ( char ∗ f r a s e ) {
char ∗ top ;
char ∗ s t a r t = f r a s e ;
char ∗ end = f r a s e ;
// avanzamos end h a s t a e l f i n a l de l a cadena
while ( ∗ end != ’ \0 ’ ) {
++end ;
}
// r e t r o c e d e m o s uno d e s d e e l f i n de cadena
end−−;
top = end ;
// m i e n t r a s no l l e g u e h a s t a a l p r i n c i p i o o t r a v e z
while ( end >= f r a s e ) {
// s a l t a m o s l o s e s p a c i o s h a c i a a d e l a n t e
while ( s t a r t < top && ∗ s t a r t == ’ ’ ) {
s t a r t ++;
}
// s a l t a m o s l o s e s p a c i o s h a c i a a t r a s
while ( end > f r a s e && ∗ end == ’ ’ ) {
end−−;
}
i f ( ∗ s t a r t++ != ∗ end−− ) {
return f a l s e ;
}
}
return true ;
}
main ( ) {
co ut << ” a man a pla n a c a n a l panama”<< e n d l ;
co ut << e s p a l i n d r o m o ( ”a man a pla n a c a n a l panama” ) << e n d l ;
}

4. (2,5 puntos) Se dispone de un fichero con acceso directo para almacenar la información correspondiente a las
personas nacidas en una provincia. Para ello se usa la siguiente estructura:
struct t i p o f e c h a
{ unsigned d i a ;
unsigned mes ;
unsigned anno ; } ;
struct ciuda da no
{ char n i f [ 9 ] ; //N. I . F . d e l ciu dadan o
char nombre [ 4 0 ] ; // nombre c o m p l e t o d e l ciu dadan o
tipo fecha fecha nacimiento ; // f e c h a de n a c i m i e n t o d e l ciu dadan o
unsigned v i v o : 1 ; // s i s i g u e v i v o o no d i c h o ciu dadan o
unsigned t i e n e d e s c e n d i e n t e s : 1 ; // s i d i c h o ciu dadan o t i e n e d e s c e n d i e n t e s
};

Escribe un programa que lea de dicho fichero y almacene en otro, también de acceso directo, solo el nif y la fecha
de nacimiento de todas aquellas personas que sigan vivas y que hayan nacido entre 1930 y 1936.

Página 4 de 11
Exámen de LP. Septiembre 2003

Solución:

#include <f s t r e a m>


#include <i o s t r e a m>
using namespace s t d ;
void f i l t r a r f i c h e r o ( void ) ;
const i nt TAM NOMBRE( 3 0 ) ;
const i nt TAM NIF ( 1 2 ) ;
struct t i p o f e c h a {
unsigned d i a ;
unsigned mes ;
unsigned anno ;
};
struct ciuda da no {
char n i f [ TAM NIF ] ;
char nombre [TAM NOMBRE ] ;
tipo fecha fecha nacimiento ;
unsigned v i v o : 1 ;
unsigned t i e n e d e s c e n d i e n t e s : 1 ;
};
i nt main ( void ) {
filtrarfichero ();
}
void f i l t r a r f i c h e r o ( ) {
i f s t r e a m ciudadanos ;
ofstream vivos ;
c i u d a d a n o s . open ( ” c i u d a d a n o s . dat ” , i o s : : i n | i o s : : b i n a r y ) ;
i f ( ! ciudadanos ) {
co ut << ”No puedo a b r i r e l f i c h e r o c i u d a d a n o s . dat ” ;
return ;
}
v i v o s . open ( ” v i v o s . dat ” , i o s : : out | i o s : : b i n a r y ) ;
i f ( ! vivos ) {
co ut << ”No puedo a b r i r e l f i c h e r o vivo d . dat ” ;
return ;
}

ciuda da no p ;
while ( ( c i u d a d a n o s . r ea d ( ( char ∗ ) &p , s i z e o f ( ciuda da no ) )
&& ! c i u d a d a n o s . e o f ( ) ) ) {
i f ( ( p . f e c h a n a c i m i e n t o . anno >= 1930
&& p . f e c h a n a c i m i e n t o . anno <= 1 9 3 6 )
&& ( p . v i v o == 1 ) ) {
v i v o s . w r i t e ( ( char ∗ ) &p . n i f , s i z e o f ( char ) ∗TAM NIF ) ;
v i v o s . w r i t e ( ( char ∗ ) &p . f e c h a n a c i m i e n t o , s i z e o f ( t i p o f e c h a ) ) ;
}
}
vivos . close ( ) ;
ciudadanos . c l o s e ( ) ;
}

5. (5 puntos) Implementa utilizando memoria dinámica la clase Matriz de enteros.


Escribe un constructor que reciba el número de filas y de columnas
Escribe un constructor de copias
Sobrecarga el operador = para asignar una matriz en otra

Página 5 de 11
Exámen de LP. Septiembre 2003

Sobrecarga el operador { para restar dos matrices


Sobrecarga el operador == para comprobar si dos matrices son iguales
Escribe una función que permita sumar a un entero una matriz, obteniendo la matriz donde a cada uno de
sus elementos se ha sumado el entero
Sobrecarga el operador [], para almacenar un entero e en la posición i,j
Sobrecarga el operador << para que se pueda utilizar para enviar los datos de la matriz a un fichero

Solución:

#include <i o s t r e a m>


using namespace s t d ;
c l a s s Ma tr iz ;
Ma tr iz sumarAInt ( int , const Ma tr iz &);
o str ea m & operator << ( o str ea m &, Ma tr iz &);
c l a s s Ma tr iz {
public :
Ma tr iz ( int , i nt ) ;
Ma tr iz ( const Ma tr iz &);
i nt ∗ & operator [ ] ( i nt ) ;
Ma tr iz & operator=(const Ma tr iz &);
Ma tr iz & operator −(const Ma tr iz &);
˜ Ma tr iz ( ) ;

private :
i nt ∗∗ d a t o s ;
i nt rows , c o l s ;
void r e s e r v a D a t o s ( ) ;
void l i b e r a D a t o s ( ) ;
void c o p i a D a t o s ( i nt ∗ ∗ ) ;

fri end o str ea m & operator << ( o str ea m &, Ma tr iz &);


fri end bool operator == ( const Ma tr iz &, const Ma tr iz &);
fri end Ma tr iz sumarAInt ( i nt n , const Ma tr iz & m) ;
};

Ma tr iz : : ˜ Ma tr iz ( ) {
liberaDatos ( ) ;
}

Ma tr iz : : Ma tr iz ( const Ma tr iz &m) {
rows =m. rows ;
c o l s = m. c o l s ;
reservaDatos ( ) ;
c o p i a D a t o s (m. d a t o s ) ;
}
i nt ∗ & Ma tr iz : : operator [ ] ( i nt f i l a ) {
return d a t o s [ f i l a ] ;
}
Ma tr iz : : Ma tr iz ( i nt rows , i nt c o l s ) : rows ( rows ) , c o l s ( c o l s ) {
reservaDatos ( ) ;
}
Ma tr iz & Ma tr iz : : operator=(const Ma tr iz & m) {
i f ( ( rows != m. rows ) | | ( c o l s != m. c o l s ) ) {
liberaDatos ( ) ;
rows = m. rows ;
c o l s = m. c o l s ;

Página 6 de 11
Exámen de LP. Septiembre 2003

reservaDatos ( ) ;
}
c o p i a D a t o s (m. d a t o s ) ;
return ∗ t h i s ;
}
Ma tr iz & Ma tr iz : : operator −(const Ma tr iz & m) {
i f ( ( rows != m. rows ) | | ( c o l s != m. c o l s ) ) {
co ut << ” E r r o r a l r e s t a r m a t r i c e s d i f e r e n t e s ” ;
return ∗ t h i s ;
}
for ( i nt row = 0 ; row < rows ; row++){
for ( i nt c o l = 0 ; c o l < c o l s ; c o l ++){
this −>d a t o s [ row ] [ c o l ] −= m. d a t o s [ row ] [ c o l ] ;
}
}
return ∗ t h i s ;
}
bool operator == ( const Ma tr iz &a , const Ma tr iz &b ) {
i f ( ( a . rows != b . rows ) | | ( a . c o l s != b . c o l s ) ) {
return f a l s e ;
}
for ( i nt row = 0 ; row < a . rows ; row++){
for ( i nt c o l = 0 ; c o l < a . c o l s ; c o l ++){
i f ( a . d a t o s [ row ] [ c o l ] != b . d a t o s [ row ] [ c o l ] ) {
return f a l s e ;
}
}
}
return true ;
}
void Ma tr iz : : l i b e r a D a t o s ( ) {
for ( i nt row = 0 ; row < rows ; row++){
delete [ ] d a t o s [ row ] ;
}
delete [ ] d a t o s ;
}
void Ma tr iz : : c o p i a D a t o s ( i nt ∗∗ d a t o s ) {
for ( i nt row = 0 ; row < rows ; row++){
for ( i nt c o l = 0 ; c o l < c o l s ; c o l ++){
this −>d a t o s [ row ] [ c o l ] = d a t o s [ row ] [ c o l ] ;
}
}
}
void Ma tr iz : : r e s e r v a D a t o s ( ) {
d a t o s = new i nt ∗ [ rows ] ;
for ( i nt n= 0 ; n<rows ; n++){
d a t o s [ n]= new i nt [ c o l s ] ;
for ( i nt c o l= 0 ; c o l <c o l s ; c o l ++){
datos [ n ] [ c o l ] = 0 ;
}
}
}
Ma tr iz sumarAInt ( i nt n , const Ma tr iz & m) {
Ma tr iz r e t (m) ;
for ( i nt row = 0 ; row < m. rows ; row++){
for ( i nt c o l = 0 ; c o l < m. c o l s ; c o l ++){
r e t . d a t o s [ row ] [ c o l ] +=n ;

Página 7 de 11
Exámen de LP. Septiembre 2003

}
}
return r e t ;
}
o str ea m & operator << ( o str ea m & os , Ma tr iz &m) {
for ( i nt row = 0 ; row < m. rows ; row++){
for ( i nt c o l = 0 ; c o l < m. c o l s ; c o l ++){
o s << m[ row ] [ c o l ] << ” , ” ;
}
o s << e n d l ;
}
o s << e n d l ;
return o s ;
}
i nt main ( ) {
Ma tr iz m( 2 , 2 ) ;
m[ 0 ] [ 1 ] = 1 0 ;
m[ 1 ] [ 1 ] = 2 0 ;
co ut << ”M: ”<<e n d l ;
co ut << m;
Ma tr iz z = sumarAInt ( 2 0 0 , m) ;
co ut << ”Z : ”<<e n d l ;
co ut << z<<e n d l ;
Ma tr iz x = m−z ;
co ut << ”X: ”<<e n d l ;
co ut << x<<e n d l ;
i f ( x == z ) co ut << ” e r r o r ”<<e n d l ;
z = x;
i f ( x == z ) co ut << ” son i g u a l e s ”<<e n d l ;
}

6. (3 puntos) Se pretende escribir un programa para calcular las nóminas de una empresa en la que hay dos tipos
de empleados: comerciales y mecánicos. Todos ellos cobran un salario base, que en el caso de un mecánico se
incrementa en 6 euros por hora extra trabajada y en el de un comercial se incrementa con un porcentaje del 5 %
sobre las ventas de cada mes. Si CalcularSueldo( ) calcula el salario mensual de cada empleado, para calcular la
nómina de los empleados de la empresa se puede utilizar una función SumarSueldos( ) que recibe como argumento
un vector de punteros a empleados apuntando a los diferentes comerciales y mecánicos de la empresa y el número
total de empleados, y calcula la suma total de los sueldos de los empleados.
(a) Define la clase empleado cuyo constructor reciba como argumento el sueldo base. Define a partir de ella las
clases comercial y mecánico, que reciban además el porcentaje de ventas y las horas extra respectivamente.

Solución:
#include <i o s t r e a m>
using namespace s t d ;
c l a s s Empleado {
public :
Empleado ( f l o a t s u e l d o B a s e )
: sueldoBase ( sueldoBase ){
}
virtual float c a l c u l a r S u e l d o ()=0;
protected :
float sueldoBase ;
};
c l a s s Co mer cia l : public Empleado {
public :

Página 8 de 11
Exámen de LP. Septiembre 2003

Co mer cia l ( f l o a t sueldo Ba se , f l o a t v e n t a s M e n s u a l e s )


: Empleado ( s u e l d o B a s e ) , v e n t a s M e n s u a l e s ( v e n t a s M e n s u a l e s ) {
}
float ca lcula r Sueldo (){
return s u e l d o B a s e +( v e n t a s M e n s u a l e s ∗ 5 / 1 0 0 ) ;
}
private :
float ventasMensuales ;
};
c l a s s Mecanico : public Empleado {
public :
Mecanico ( f l o a t sueldo Ba se , f l o a t h o r a s E x t r a )
: Empleado ( s u e l d o B a s e ) , h o r a s E x t r a ( h o r a s E x t r a ) {
}
float ca lcula r Sueldo (){
return s u e l d o B a s e +( h o r a s E x t r a ∗ 6 ) ;
}
private :
float horasExtra ;
};

(b) Implementa la función SumarSueldos() de tal manera que utilice ligadura dinámica.

Solución:
f l o a t suma r Sueldo s ( Empleado ∗∗ p l a n t i l l a , i nt numTrabajadores ) {
f l o a t r e t =0;
for ( i nt n = 0 ; n< numTrabajadores ; n++){
r e t += p l a n t i l l a [ n]−> c a l c u l a r S u e l d o ( ) ;
}
return r e t ;
}

(c) Escribe un programa de ejemplo.

Solución:
i nt main ( ) {
Empleado ∗ empresa [ 3 ] ;
empresa [ 0 ] = new Co mer cia l ( 1 0 0 0 , 1 0 0 0 0 ) ;
empresa [ 1 ] = new Mecanico ( 2 0 0 0 , 1 0 ) ;
empresa [ 2 ] = new Co mer cia l ( 8 0 0 , 1 0 0 0 0 0 0 ) ;
f l o a t t o t a l = suma r Sueldo s ( empresa , 3 ) ;
co ut << ” To ta l nomina : ”<< t o t a l <<e n d l ;
}

7. (2 puntos) Elige entre uno de los dos ejercicios siguientes:


(a) Escribe un programa de prueba donde se defina utilizando la STL una lista de string .
Insertar por el final 5 elementos
Recorrer la lista para comprobar su contenido
Insertar 5 elementos por el principio
Ordenar la lista
Borrar el segundo y el penúltimo elemento
Utilizar un iterador para recorrer la lista

Página 9 de 11
Exámen de LP. Septiembre 2003

Solución:
#include <i o s t r e a m>
#include < i t e r a t o r >
#include < l i s t >
#include <a l g o r i t h m>
using namespace s t d ;
i nt main ( ) {
l i s t <s t r i n g > l i s t a ;
o s t r e a m i t e r a t o r <s t r i n g > out ( cout , ” , ” ) ;
l i s t a . push ba ck ( ”UNO” ) ;
l i s t a . push ba ck ( ”DOS” ) ;
l i s t a . push ba ck ( ”TRES” ) ;
l i s t a . push ba ck ( ”CUATRO” ) ;
l i s t a . push ba ck ( ”CINCO” ) ;

copy ( l i s t a . b e g i n ( ) , l i s t a . end ( ) , out ) ;

lista . push f r o n t ( ”uno ” ) ;


lista . push f r o n t ( ” dos ” ) ;
lista . push front (” tres ” ) ;
lista . push front ( ” cuatro” ) ;
lista . push front (” cinco” ) ;

l i s ta . sort ();

l i s t <s t r i n g > : : i t e r a t o r i = l i s t a . b e g i n ( ) ;
++i ;
l i s t a . erase ( i ) ;

i = l i s t a . end ( ) ;
−−i ;
−−i ;
l i s t a . erase ( i ) ;
co ut << e n d l ;
i = l i s t a . begin ( ) ;
while ( i != l i s t a . end ( ) ) {
co ut << ∗ i << ” , ” ;
i ++;
}
}

(b) Escribe un manipulador propio de entrada para cambiar la base a hexadecimal y otro de salida para cambiar
la precisión a 10 dı́gitos y la longitud de campo a 30 caracteres. Escribir un programa de prueba.

Solución:
#include <i o s t r e a m>
#include <iomanip>
using namespace s t d ;
c l a s s MuyAncho{
};
c l a s s AHex{
};
o str ea m & operator << ( o str ea m & os , MuyAncho &t ) {
o s << s e t p r e c i s i o n ( 1 0 ) ;
o s << setw ( 3 0 ) ;

Página 10 de 11
Exámen de LP. Septiembre 2003

return o s ;
}
i s t r e a m & operator >> ( i s t r e a m & i s , AHex &t ) {
i s >> hex ;
return i s ;
}
i nt main ( ) {
AHex xx ;
MuyAncho mm;
f l o a t n=0;
c i n >> xx >> n ;
co ut << ” [ ” << mm << n << ” ] ” ;
}

Página 11 de 11

You might also like