Escuela Politécnica Superior Ingeniería Industrial EXAMEN TEÓRICO DE INFORMÁTICA APLICADA 11 de Junio de 2005 1. Explique en qué consiste el paso por valor, paso por dirección y paso por referencia. Ponga un ejemplo de cada uno de ellos. ¿Cuáles se admiten en C y cuales en C++? (1 pto) Paso por Valor (C y C++): Se pasa una copia temporal (no puede modificarse el original). int VisualizarNota(int nota) { nota=5; // modificamos la copia temporal cout << “Nota: “ << nota; } Llamada: VisualizarNota(notaJuan); // notaJuan no se modifica Paso por Dirección (C y C++): Se pasa la dirección en memoria de la variable original (puede modificarse): int PonerNota(int *pnota) { *pnota=5; // modificamos la variable original cout << “Nota: “ << *pnota; } Llamada: PonerNota( &notaJuan);//permite que se modifique notaJuan Paso por Referencia (específico de C++): Se pasa una referencia (nombre alternativo) de la variable original (puede modificarse). int PonerNota(int &nota) { nota=5; // modificamos la variable original cout << “Nota: “ << nota; } Llamada: PonerNota(notaJuan);//permite que se modifique notaJuan 2. ¿Qué tipos de accesibilidad se pueden utilizar dentro de una clase de C++? Explique las caraterísticas de cada uno de ellos. (1 pto) Duración del examen: 2:00 horas Escuela Politécnica Superior Ingeniería Industrial Una clase está formada por miembros (datos y funciones) que pueden ser: Privados (declarados como private:): Son miembros de una clase (datos o funciones) que sólo pueden ser accedidos por funciones de la clase. Se deben declarar privados las variables y métodos de la clase que no queremos que sean utilizados o accedidos por otras clases o funciones globales. Públicos (public:): Son miembros que pueden ser utilizados fuera de la clase (ej. dentro de una función global, o dentro de la función main() ). Protegidos (protected:): son miembros privados que pueden ser utilizados por otra clase derivada (Herencia). Es práctica general declarar los datos de la clase como privados, mientras que los métodos que operan sobre esos datos se suelen declarar públicos. Si se necesita que una clase derivada acceda a los datos de la clase base, entonces utilizaremos el modificador de acceso protected. 3. Indique los errores que aparecerían al compilar el siguiente programa C. Comente qué tipo de error se ha cometido. Vuelva a escribir el código de manera que no exista ningún error de compilación. (1 pto) Duración del examen: 2:00 horas Escuela Politécnica Superior Ingeniería Industrial #include <stdio.h> #define MAX 50 struct alumno { char nombre[MAX]; float notas[3]; }; typedef struct alumno alumno; void LeerVector(float *v, int n); void IntroducirAlumno(alumno *alu); void main(void) { int n=5; int v[MAX]; alumno pepe; printf(“Encuentre los errores...\n“); for(i = 0; i < n; i++) printf("%d", i); LeerVector(v, 30); IntroducirAlumno(&pepe); } void LeerVector(float *v, int n) { int i; for(i=0, i < n, i++) { printf("Introduzca el elemento %d: ", i); scanf("%d", &v[i]); } } void IntroducirAlumno(alumno *alu) { printf("Introduzca el nombre del alumno:\n"); scanf("%s", alu->nombre); printf("Introduzca las notas del alumno:\n"); scanf("%f", &alu->notas[0]); scanf("%f", &alu->notas[1]); scanf("%f", &alu->notas[2]); } 4. El fragmento de código que aparece a continuación se ha compilado sin ningún problema. Sin embargo, al ejecutarlo, el sistema operativo produce un error y termina el programa. Indique los errores y vuelva a escribir el código de forma correcta. (1.5 ptos) Duración del examen: 2:00 horas Escuela Politécnica Superior Ingeniería Industrial #include <stdio.h> struct impresion{ char usuario[30]; int pc; char fichero[30]; }; typedef struct impresion impresion; //No es imprescindible declarar el prototipo, aunque sí muy aconsejable int IntroducirImpresion(impresion *imp); void main(void) { impresion doc; FILE* fichero; IntroducirImpresion(&doc); //No basta con declarar un puntero. fichero = fopen("fichero.txt", "w"); if(fichero==NULL){ //fichero=NULL siempre es cierto, //además se machaca el resultado de fopen printf(“Error abriendo fichero”); // fclose(fichero); // Si no se ha abierto el fichero produce un //error } else{ //Si no ha habido ningún problema, escribimos en el fichero fprintf(fichero, "Datos de impresion\n"); fprintf(fichero, "Usuario %s", doc->usuario); fprintf(fichero, "PC %d", doc->pc); fprintf(fichero, "Fichero %s", doc->fichero); fclose(fichero); } } int IntroducirImpresion(impresion *imp) { printf("Introduzca el nombre del usuario:\n"); scanf("%s", imp->usuario); printf("Introduzca el ordenador:\n"); scanf("%d", imp->pc); printf("Introduzca el nombre del fichero:\n"); scanf("%s", imp->fichero); } 5. Defina: Lista, cola y pila. Defina una estructura de datos en C que le permita implementar las anteriores. (1.5 ptos) (Tema de estructuras) 6. Definir brevemente los siguientes conceptos de C++: clase, objeto, método, (2 ptos) constructor, destructor y función amiga (friend). (Tema 7 clases en C++) Duración del examen: 2:00 horas Escuela Politécnica Superior Ingeniería Industrial 7. Lea atentamente el código de C++ que se muestra a continuación y conteste a las siguientes preguntas: a) Describa la jerarquía de clases. CCadena: Clase base. CDCadena: Clase derivada de CCadena. Deriva de forma pública. b) Describa el funcionamiento del operator +. CDCadena CDCadena::operator + (CDCadena &orig) { char *cadena; //puntero para una cadena // Se libera memoria para la nueva cadena // La longitud de la nueva cadena es la suma de longitudes // de las cadenas: pCadena y orig.pCadena cadena = new char[tam + orig.tam]; //Se copia pCadena en cadena (datos del objeto que realizó la //llamada) strcpy(cadena, pCadena); // Se copia orig.pCadena (datos del objeto argumento) strcat(cadena, orig.pCadena); //Se crea un nuevo objeto con el constructor con //parámetro y datos CDCadena temp(tam + orig.tam, cadena); //El resultado es un objeto CDCadena. La nueva cadena es el //resultado de concatenar las cadenas del objeto que relizó la llamada //(this) y del objeto orig. return (temp); } c) ¿Indique en qué momento se llama a los constructores y a los destructores? En el caso de los constructores, se llama primero al de la clase base, y a continuación el de la clase derivada. En los destructores, el funcionamiento es al contrario. Primero se llama al destructor de la clase derivada, y , a continuación, el de la clase base. Indicamos el momento en que se llama a todos los contructores: 1) CDCadena c1(4, cad1); // constructor con parámetros, se llama al constructor de la clase base 2) CDCadena c2(4, cad2); //constructor con parámetros, se llama al constructor de la clase base 3) CDCadena c3; //constructor con parámetros por defecto, se llama al constructor de la clase base 4) c3 = (c1 + c2); // En esta línea se crean dos objetos temporales: a. En el operator +: CDCadena temp(tam + orig.tam, cadena); // Se llama al constructor de la clase base y derivada. b. Se llama al destructor al finalizar el operator +. c. return (temp); // Se llama al constructor copia de la clase base y derivada d. se llama al constructor y al destructor en la llamada al operador = 5) Al finalizar la función main se llama al destructor para los objetos c1, c2 y c3. d) ¿Cuál es la salida por pantalla del programa? (2 ptos) Salida por pantalla: Duración del examen: 2:00 horas Escuela Politécnica Superior Ingeniería Industrial MainCadena.cpp #include <iostream.h> #include "..\inc\CDCadena.h" int main(void) { char cad1[]="abc"; char cad2[]="def"; CDCadena c1(4, cad1); CDCadena c2(4, cad2); CDCadena c3; c3 = (c1 + c2); c1.Visualizar(); c2.Visualizar(); c3.Visualizar(); return 0; } CCadena.h Duración del examen: 2:00 horas Escuela Politécnica Superior Ingeniería Industrial class CCadena { protected: int tam; char *pCadena; public: CCadena(int t=20); CCadena(int t, char *cad); CCadena(CCadena &orig); ~CCadena(void); void Visualizar(void); }; CDCadena.h #include "../inc/CCadena.h" class CDCadena : public CCadena{ public: CDCadena(int t=20); CDCadena(int t, char *cad); CDCadena(CDCadena &orig); ~CDCadena(void); // destructor CDCadena& operator = (CDCadena &orig); CDCadena operator + (CDCadena &orig); }; CCadena.cpp Duración del examen: 2:00 horas Escuela Politécnica Superior Ingeniería Industrial #include <iostream.h> #include "..\inc\CCadena.h" CCadena::CCadena(int t) { tam = t; pCadena = new char[tam]; cout << endl << "Constructor clase base"; } CCadena::CCadena(int t, char *cad) { tam = t; pCadena = new char[tam+1]; for(int i=0; i<tam; i++) pCadena[i]=cad[i]; } CCadena::CCadena(CCadena &orig) { tam = orig.tam; pCadena = new char[tam+1]; for(int i=0; i<tam; i++) pCadena[i]=orig.pCadena[i]; } CCadena::~CCadena() { cout << endl << "Llamando al destructor de la clase base"; delete [] pCadena; } void CCadena::Visualizar() { cout << endl << "Cadena: " << pCadena << endl; } CDCadena.cpp Duración del examen: 2:00 horas Escuela Politécnica Superior Ingeniería Industrial #include <iostream.h> #include <string.h> #include "..\inc\CDCadena.h" CDCadena::CDCadena(int t) : CCadena(t) { cout << endl<< "Llamando al constructor de la clase derivada"; } CDCadena::CDCadena(int t, char *cad) : CCadena(t, cad) { } CDCadena::CDCadena(CDCadena &orig) : CCadena(orig) { } CDCadena::~CDCadena() { cout << endl<< "Llamando al destructor de la clase derivada"; } CDCadena& CDCadena::operator = (CDCadena &orig) { delete []pCadena; pCadena = new char[orig.tam]; strcpy(pCadena, orig.pCadena); return (*this); } CDCadena CDCadena::operator + (CDCadena &orig) { char *cadena; cadena = new char[tam + orig.tam]; strcpy(cadena, pCadena); strcat(cadena, orig.pCadena); CDCadena temp(tam + orig.tam, cadena); return (temp); } Duración del examen: 2:00 horas