====== Examen Parcial - 75.41. Algoritmos y Programación II ======
**Cátedra:** Mandrafina\\
**Fecha:** Primera Oportunidad - Segundo Cuatrimestre 2004\\
**Día:** 08/10/2004
Esta página está incompleta; podés ayudar completando el material.
===== Enunciado =====
==== Punto I ====
Dado el siguiente programa se requiere indicar lo que se mostraría por pantalla:
#include
using namespace std;
int main(){
int *A, *C;
int **B;
char *D, *E, *F;
char G;
int H;
H = 15;
G = 'B';
A = new int();
*A = 64;
cout << H << G << *A << endl;
B = &A;
cout << **B << endl;
D = (char*) A;
C = (int*) D;
cout << *D << *C << endl;
delete A;
if ( *D == '?' ) {
cout << G << H << endl;
}
}
==== Punto II ====
¿Qué es programación por contrato? Explique los conceptos de precondición, postcondición y axioma, dentro de la teoría de Tipos de Datos Abstractos.
==== Punto III ====
Construtir un TDA ConsultaCompetidor que permita acceder a la información del siguiente archivo:
^ Campo ^ Tipo ^
| NumeroCompetidor | int |
| NombreCompetidor | char[30] |
| TiempoVuelta | “mmss” (char[4]) |
| Pais | char[35] |
| Edad | unsigned int |
Las primitivas que debe ofrecer son (agregue las que considere necesarias):
* obtenerTiempoPromedio( ConsultaCompetidor cc )
* obtenerCompetidorMejorTiempo(ConsultaCompetidor cc )
* obtenerCompetidorPeorTiempo(ConsultaCompetidor cc )
* obtenerCompetidor(ConsultaCompetidor cc, int nroCompetidor )
La implementación del TDA puede hacer con la estructura de datos que se considere conveniente, pero deben especificarse e implementarse todas las primitivas.
==== Punto IV ====
Resolución de problema de aplicación (1hr 20 min)
Dado los archivos descriptos más abajo, totalmente desordenados, construir un programa para emitir un listado de ciudades, ordenado por código de país y cantidad de habitantes, para el continente con CodigoContinente = 1:
^ PAIS ^ CIUDAD ^ CANTIDAD DE HABITANTES ^
| ar | Buenos Aires | 3500000 |
| br | San Pablo | 4000000 |
Los archivos tienen la siguiente estructura:
^Campo ^ Tipo ^
| CodigoPais | char[2] |
| CodigoContinente | int |
| NombrePais | char[30] |
^Campo ^ Tipo ^
| CodigoCiudad | int |
| CodigoPais | char[2] |
| NombreCiudad | char[40] |
| CantidadHabitantes | int |
Nota:
- Explicar la estrategia de solución adoptada con claridad (usar esquemas)
- Los archivos se procesarán secuencialmente, una sola vez, luego en forma directa
- Los archivos no deben almacenarse en memoria bajo ninguna circunstancia
- Completar todo lo necesario para la resolución del problema, tipos, variables, procedimientos, etc.
===== Resolución =====
==== Punto III ====
/************************************************************************************
El ordenamiento de la lista se hace de la siguiente manera:
ResultadoComparacion compararDato(Dato dato1, Dato dato2) {
if (getTiempoVuelta(dato1.competidor) == getTiempoVuelta(dato2.competidor)) {
if (getNombre(dato1.competidor) == getNombre(dato2.competidor))
return igual;
else {
if (getNombre(dato1.competidor) > getNombre(dato2.competidor))
return mayor;
else
return menor;
}
}
else
if (getTiempoVuelta(dato1.competidor) > getTiempoVuelta(dato2.competidor))
return mayor;
else
return menor;
}
*******************************************************************************************/
/*
Pre: Ninguna
Post: La consulta queda creada y lista para ser usada
*/
void crear(cCompetidor &miConsulta) {
crearLista(miConsulta.competidores);
}
/*
Pre: La consulta debe haber sido creada
Post: La consulta queda destruída e inutilizable
*/
void destruir(cCompetidor &miConsulta) {
PtrNodoLista ptrCompetidor;
Dato datoCompetidor;
ptrCompetidor = primero(miConsulta.competidores);
while (ptrCompetidor != fin()) {
obtenerDato(miConsulta.competidores,datoCompetidor,ptrCompetidor);
destruir(datoCompetidor.competidor);
colocarDato(miConsulta.competidores,datoCompetidor,ptrCompetidor);
ptrCompetidor = siguiente(miConsulta.competidores,ptrCompetidor);
}
eliminarLista(miConsulta.competidores);
}
/*
Pre: La consulta debe haber sido creada, así como el competidor a agregar
Post: El competidor queda agregado a la consulta
*/
void agregarCompetidor(cCompetidor &miConsulta, Competidor* miCompetidor) {
Dato datoCompetidor;
datoCompetidor.competidor = miCompetidor;
insertarDato(miConsulta.competidores,datoCompetidor);
}
/*
Pre: La consulta debe haber sido creada, y miCompetidor debe referenciar a un competidor
Post: Se elimina al competidor de la consulta (no se destruye el competidor)
*/
void quitarCompetidor(cCompetidor &miConsulta, Competidor* miCompetidor){
PtrNodoLista ptrCompetidor;
Dato datoCompetidor;
bool encontrado = false;
ptrCompetidor = primero(miConsulta.competidores);
while ((ptrCompetidor != fin()) && (!encontrado)){
obtenerDato(miConsulta.competidores,datoCompetidor,ptrCompetidor);
if (datoCompetidor.competidor == miCompetidor){
encontrado = true;
}
else {
ptrCompetidor = siguiente(miConsulta.competidores,ptrCompetidor);
}
}
if (encontrado){
eliminarNodo(miConsulta.competidores,ptrCompetidor);
}
}
/*
Pre: La consulta debe haber sido creada y "pathCompetidores" debe ser la ruta a un archivo con formato correcto
Post: Se agregan todos los competidores del archivo a la consulta
*/
void cargarCompetidores(cCompetidor &miConsulta, string pathCompetidores) {
ArchivoRegistros fCompetidores;
regCompetidor registro;
Competidor* nvoCompetidor;
unsigned int tiempo;
crear(fCompetidores,pathCompetidores,sizeof(regCompetidor));
while (!fin(fCompetidores)) {
leer(fCompetidores,static_cast(®istro));
crear(nvoCompetidor,registro.numero,registro.nombre);
setEdad(nvoCompetidor,registro.edad);
tiempo = convertirTiempo(registro.tiempo);
setTiempoVuelta(nvoCompetidor,tiempo);
setPais(nvoCompetidor,registro.pais);
agregarCompetidor(miConsulta,nvoCompetidor);
}
destruir(fCompetidores);
}
/*
Pre: La consulta debe haber sido creada
Post: Se devuelve el tiempo promedio de los competidores de la consulta. En caso de haber un error se retorna "0"
*/
float obtenerTiempoPromedio(cCompetidor &miConsulta) {
float promedio = 0;
int cantidadCompetidores = 0;
int sumatoria = 0;
PtrNodoLista ptrCompetidor;
Dato datoCompetidor;
ptrCompetidor = primero(miConsulta.competidores);
while (ptrCompetidor != fin()) {
cantidadCompetidores++;
obtenerDato(miConsulta.competidores,datoCompetidor,ptrCompetidor);
sumatoria += getTiempoVuelta(datoCompetidor.competidor);
ptrCompetidor = siguiente(miConsulta.competidores,ptrCompetidor);
}
if (cantidadCompetidores != 0) {
promedio = (float)sumatoria/cantidadCompetidores;
}
return promedio;
}
/*
Pre: La consulta debe haber sido creada
Post: Se retorna una referencia el competidor de mejor tiempo. En caso que no hay competidores, se retorna "0"
*/
Competidor* obtenerCompetidorMejorTiempo(cCompetidor &miConsulta) {
Competidor* competidor = 0;
PtrNodoLista ptrCompetidor;
Dato datoCompetidor;
ptrCompetidor = primero(miConsulta.competidores);
if (ptrCompetidor != fin()) {
obtenerDato(miConsulta.competidores,datoCompetidor,ptrCompetidor);
competidor = datoCompetidor.competidor;
}
return competidor;
}
/*
Pre: La consulta debe haber sido creada
Post: Se retorna una referencia el competidor de peor tiempo. En caso que no hay competidores, se retorna "0"
*/
Competidor* obtenerCompetidorPeorTiempo(cCompetidor &miConsulta) {
Competidor* competidor = 0;
PtrNodoLista ptrCompetidor;
Dato datoCompetidor;
ptrCompetidor = ultimo(miConsulta.competidores);
if (ptrCompetidor != fin()) {
obtenerDato(miConsulta.competidores,datoCompetidor,ptrCompetidor);
competidor = datoCompetidor.competidor;
}
return competidor;
}
/*
Pre: La consulta debe haber sido creada
Post: Se retorna una referencia al competidor cuyo número es nroCompetidor. En caso de no existir en la consulta, se retorna 0
*/
Competidor* obtenerCompetidor(cCompetidor &miConsulta, int nroCompetidor) {
PtrNodoLista ptrCompetidor;
Dato datoCompetidor;
bool encontrado = false;
Competidor* competidor = 0;
ptrCompetidor = primero(miConsulta.competidores);
while ((ptrCompetidor != fin()) && (!encontrado)) {
obtenerDato(miConsulta.competidores,datoCompetidor,ptrCompetidor);
if (getNumero(datoCompetidor.competidor) == nroCompetidor) {
encontrado = true;
competidor = datoCompetidor.competidor;
}
else
ptrCompetidor = siguiente(miConsulta.competidores,ptrCompetidor);
}
return competidor;
}
Para que todo esto ande, obviamente hace falta el **TDA Competidor**:
using namespace std;
const string NOPAIS = "Orígen Indefinido";
typedef struct Competidor{
int numero;
string nombre;
unsigned int edad;
string pais;
unsigned int tiempoVuelta;
};
/*
Pre: Ninguna
Post: Crea el dato y lo deja listo para su uso
*/
void crear(Competidor* &miCompetidor, int numero, string nombre){
miCompetidor = new Competidor;
miCompetidor->numero = numero;
miCompetidor->nombre = nombre;
miCompetidor->edad = 0;
miCompetidor->pais = NOPAIS;
miCompetidor->tiempoVuelta = 0;
}
/*
Pre: El dato debe haber sido creado
Post: Destruye el dato, y lo deja inutilizable
*/
void destruir(Competidor* &miCompetidor){
miCompetidor->numero = 0;
delete miCompetidor;
miCompetidor = NULL;
}
/*
Pre: El dato debe haber sido creado
Post: Establece el nombre del competidor
*/
void setNombre(Competidor* miCompetidor, string nombre){
miCompetidor->nombre = nombre;
}
/*
Pre: El dato debe haber sido creado
Post: Establece la edad del competidor
*/
void setEdad(Competidor* miCompetidor, unsigned int edad){
miCompetidor->edad = edad;
}
/*
Pre: El dato debe haber sido creado
Post: Establece el país del competidor
*/
void setPais(Competidor* miCompetidor, string pais){
miCompetidor->pais = pais;
}
/*
Pre: El dato debe haber sido creado y tiempoVuelta debe ser un entero, representado en segundos
Post: Establece el tiempo de vuelta del competidor
*/
void setTiempoVuelta(Competidor* miCompetidor, unsigned int tiempoVuelta){
miCompetidor->tiempoVuelta = tiempoVuelta;
}
/*
Pre: El dato debe haber sido creado
Post: Establece el tiempo de vuelta del competidor (en segundos)
*/
int getNumero(Competidor* miCompetidor){
return miCompetidor->numero;
}
/*
Pre: El dato debe haber sido creado
Post: Retorna el nombre del competidor
*/
string getNombre(Competidor* miCompetidor){
return miCompetidor->nombre;
}
/*
Pre: El dato debe haber sido creado
Post: Retorna la edad del competidor
*/
unsigned int getEdad(Competidor* miCompetidor){
return miCompetidor->edad;
}
/*
Pre: El dato debe haber sido creado
Post: Retorna el país del competidor
*/
string getPais(Competidor* miCompetidor){
return miCompetidor->pais;
}
/*
Pre: El dato debe haber sido creado
Post: Retorna el tiempo de vuelta del competidor (en segundos)
*/
unsigned int getTiempoVuelta(Competidor* miCompetidor){
return miCompetidor->tiempoVuelta;
}
==== Punto IV ====
==Estrategia==
Se cargan todos los paises en el continente 1, ordenándolos por código ascendente.
Luego se lee el archivo de ciudades insertándolas en la lista de ciudades del pais correspondiente, si existiera ( se inserta en forma ascendente por habitantes )
{{:materias:75:41:diagrama.png|:materias:75:41:diagrama.png}}
==Implementación==
struct tPais{
PtrNodoLista corriente;
char codigo[3];
Lista ciudades;
};
struct tCiudad{
int habitantes;
long prr;
};
struct RegPais{
char codigo[2];
int continente;
char nombre[30];
};
struct RegCiudad{
int codigo;
char cod_pais[2];
char nombre[40];
int habitantes;
};
const int IGUAL = 0;
const int MAYOR = 1;
const int MENOR = -1;
int compararPais( tPais& p1, tPais& p2 )
{
string cod1 = getCodigo( p1 );
string cod2 = getCodigo( p2 );
if( cod1 == cod2 ) return IGUAL;
if( cod1 < cod2 ) return MENOR;
if( cod1 > cod2 ) return MAYOR;
}
int main()
{
Lista paises;
crearLista( paises );
cargarPaises( paises );
cargarCiudades( paises );
mostrarListado( paises );
liberarListaPais( paises );
eliminarLista( paises );
return 0;
}
void cargarPaises( Lista paises )
{
ArchivoRegistro arch;
RegPais aux;
tPais pais;
crearArchivoReg( arch, “paises.dat”, sizeof( RegPais ) );
while( !fin(arch) ){
leer(arch, &aux);
if( aux.continente == 1 ){
crearPais(pais, aux.codigo );
insertarDato( paises, pais );
destruirPais( pais );
}
}
destruirArchivo( arch );
}
void cargarCiudades( Lista paises )
{
PtrNodoLista pOrigen; // puntero al nodo del pais encontrado
tPais pais; // patron de busqueda
ArchivoRegistro arch;
RegCiudad aux;
tCiudad ciudad;
crearArchivoReg(arch, “ciudades.dat”, sizeof(RegCiudad));
while(!fin(arch)){
leer(arch,aux);
crearPais( pais, aux.cod_pais);
pOrigen = localizarDato( paises, pais );
destruirPais( pais );
if( pOrigen != fin( paises ) ){
obtenerDato( paises, pais, pOrigen );
crearCiudad( ciudad, aux.habitantes, posicion(arch) );
agregarCiudad( pais, ciudad );
colocarDato( paises, pais, pOrigen );
destruirCiudad( ciudad );
}
}
destruirArchivo(arch);
}
void liberarListaPais( Lista paises )
{
tPais pais;
PtrNodoLista pNodo;
pNodo = primero( paises );
while( pNodo != fin( paises) ){
obtenerDato(paises, pais, pNodo );
destruirPais(pais);
colocarDato( paises, pais, pNodo);
pNodo = siguiente( paises, pNodo );
}
}
void mostrarListado( Lista paises )
{
long prr:
tPais pais;
tCiudad ciudad;
RegCiudad aux;
PtrNodoLista pNodo;
ArchivoRegistro arch;
crearArchivoReg( arch, “ciudades.dat”, sizeof(RegCiudad)),
cout << “PAIS\tCIUDAD\t\tHABITANTES\n”;
pNodo = primero( paises );
while( pNodo != fin(paises)){
obtenerDato(paises, pais, pNodo);
primerCiudad( pais );
while( obtenerCiudad( pais, ciudad) ){
prr = getPrr( ciudad );
posicionarse( arch, prr);
leer( arch, aux);
cout << getCodigo(pais) << “\t” << aux.nombre << “\t\t”;
cout << getHabitantes(ciudad) << endl;
}
pNodo = siguiente(paises, pNodo );
}
destruirArchivo( arch );
}
// TDAs utilizados ( structs declarados arriba )
// tPais
void crearPais( tPais& pais, char cod[] )
{
pais.codigo[2] = '\0'; // fin de cadena
pais.codigo[0] = cod[0];
pais.codigo[1] = cod[1];
crearLista( pais.ciudades );
}
void destruirPais( tPais& pais )
{
tCiudad ciudad;
PtrNodoLista pNodo;
pNodo = primero( pais.ciudades);
while( pNodo != fin(pais.ciudades) ){
obtenerDato( pais.ciudades, ciudad, pNodo);
destruirCiudad( ciudad );
colocarDato( pais.ciudades, ciudad, pNodo);
pNodo = siguiente( pais.ciudades, pNodo );
}
eliminarLista( pais.ciudades );
}
//mueve el puntero corriente a la primer ciudad, sin obtenerla
void primerCiudad( tPais& pais )
{
pais.corriente = primero( pais.ciudades );
}
//obtiene la ciudad actual, mueve el puntero al siguiente, devuelve true si la ciudad
// obtenida es válida
bool obtenerCiudad( tPais& pais, tCiudad& ciudad )
{
if( pais.corriente == fin( pais.ciudades ) )
return false;
obtenerDato( pais.ciudades, ciudad, pais.corriente );
pais.corriente = siguiente( pais.ciudades, pais.corriente );
return true;
}
//obtiene el codigo
string getCodigo( tPais& pais )
{
return string( pais.codigo );
}
//TDA Ciudad
// tCiudad
void crearCiudad( tCiudad& ciudad, int habitantes, long prr )
{
ciudad.habitantes = habitantes;
ciudad.prr = prr;
}
void destruirCiudad( tCiudad& ciudad )
{
}
long getPrr( tCiudad& ciudad )
{
return ciudad.prr;
}
int getHabitantes( tCiudad& ciudad )
{
return ciudad.habitantes;
}
Hasta acá llevo 1 hora 16 minutos. Más tarde, cuando pasaba la resolución, me di cuenta que faltaba la primitiva agregarCiudad. La listo a continuación:
void agregarCiudad( tPais& pais, const tCiudad& ciudad )
{
insertarDato( pais.ciudades, ciudad );
}
===== Discusión =====
Si ves algo que te parece incorrecto en la resolución y no te animás a cambiarlo, dejá tu comentario acá