Tema 2 - Programación Modular
Tema 2 - Programación Modular
Alberto Verdejo
Facultad de Informática (UCM)
Fundamentos de la programación II
Programación modular
Hoy, al llegar a la estación y ver que de nuevo tendrás que esperar, has decidido hacer una
aplicación que te permita saber en cualquier momento a qué hora pasará el próximo tren.
Para empezar, en el tiempo que has estado esperando ya has conseguido el horario de los
trenes de las estaciones que utilizas a menudo. Ahora, ya será muy fácil calcular cuándo
pasará el próximo tren.
Requisitos de implementación
Problema: ¿A qué hora pasa el próximo tren?
Tipo de datos Hora horas.h
#include <iostream>
struct Hora {
int hh;
int mm;
int ss;
};
#include <iomanip>
using namespace std;
#include "horas.h"
// operador de comparación
bool operator<(Hora const& a, Hora const& b) {
if (a.hh < b.hh) return true;
else if (a.hh > b.hh) return false;
else if (a.mm < b.mm) return true;
else if (a.mm > b.mm) return false;
else return a.ss < b.ss;
}
Tipo de datos Hora horas.cpp
// operador de entrada
istream & operator>>(istream & entrada, Hora &/*sal*/ hora) {
char aux;
entrada >> hora.hh >> aux >> hora.mm >> aux >> hora.ss;
return entrada;
}
// operador de salida
ostream & operator<<(ostream & salida, Hora const& hora) {
salida << setfill('0') << setw(2) << hora.hh << ':'
<< setfill('0') << setw(2) << hora.mm << ':'
<< setfill('0') << setw(2) << hora.ss;
return salida;
}
Tipo de datos HorarioTrenes horario.h
#include "horas.h"
struct HorarioTrenes {
Hora horario[MAX_TRENES];
int num_trenes;
};
Tipo de datos HorarioTrenes horario.cpp
#include "horario.h"
Programa principal main.cpp
#include "horas.h"
#include "horario.h"
using namespace std;
int main() {
int nTrenes, nConsultas; cin >> nTrenes >> nConsultas;
HorarioTrenes trenes;
trenes.num_trenes = nTrenes;
for (int i = 0; i < nTrenes; ++i) {
cin >> trenes.horario[i];
}
// consulta las horas
for (int i = 0; i < nConsultas; ++i) {
Hora h; cin >> h;
Hora sig;
if (busca(trenes, h, sig)) cout << sig << '\n';
else cout << "NO\n"; // ya no hay trenes posteriores
}
return 0;
}
¿Mejoras?
horario.h
#include <vector>
main.cpp
¡Falta de cohesión!
¿Mejoras?
main.cpp
¡Demasiado acoplamiento!
Objetivos deseables en la programación modular
#include <iostream>
#include <iomanip>
using namespace std;
#include "horas.h"
// operador de comparación
bool operator<(Hora const& a, Hora const& b) {
if (a.hh < b.hh) return true;
else if (a.hh > b.hh) return false;
else if (a.mm < b.mm) return true;
else if (a.mm > b.mm) return false;
else return a.ss < b.ss;
}
Tipo de datos Hora horas.cpp
// operador de entrada
istream & operator>>(istream & entrada, Hora &/*sal*/ hora) {
char aux;
entrada >> hora.hh >> aux >> hora.mm >> aux >> hora.ss;
return entrada;
}
// operador de salida
ostream & operator<<(ostream & salida, Hora const& hora) {
salida << setfill('0') << setw(2) << hora.hh << ':'
<< setfill('0') << setw(2) << hora.mm << ':'
<< setfill('0') << setw(2) << hora.ss;
return salida;
}
Tipo de datos HorarioTrenes horario.h
#include "horas.h"
#include "horario.h"
‣ Las clases tienen una interfaz (la parte a la que acceden directamente los
usuarios de la clase) y una implementación (a la que se accede solo
indirectamente a través de la interfaz).
class MiClase { // nombre de la clase
public:
// miembros públicos: la interfaz accesible por los usuarios
interfaz // - funciones
// - tipos
private:
// miembros privados: detalles de la implementación
// (solamente utilizables desde los miembros de la clase)
implementación // - funciones
// - tipos
// - atributos (variables)
};
Tipo de datos Hora horas.h
#include <iostream>
class Hora {
public:
Hora(int h = 0, int m = 0, int s = 0) : hh(h), mm(m), ss(s) {}
int hora() const { return hh; }
int minuto() const { return mm; }
int segundo() const { return ss; }
bool operator<(Hora const& otro) const;
void read(std::istream & input = std::cin);
void print(std::ostream & output = std::cout) const;
private:
int hh, mm, ss;
};
#include <iomanip>
#include "horas.h"
using namespace std;
// operador de comparación
bool Hora::operator<(Hora const& otro) const {
if (hh < otro.hh) return true;
else if (hh > otro.hh) return false;
else if (mm < otro.mm) return true;
else if (mm > otro.mm) return false;
else return ss < otro.ss;
}
Tipo de datos Hora horas.cpp
#include "horas.h"
#include <vector>
class HorarioTrenes {
public:
HorarioTrenes() {}
void inserta_tren(Hora const& hora);
bool siguiente_tren(Hora const& hora, Hora &/*sal*/ sig) const;
private:
std::vector<Hora> trenes;
};
Tipo de datos HorarioTrenes horario.cpp
#include "horario.h"
HorarioTrenes trenes;
for (int i = 0; i < nTrenes; ++i) {
Hora h; cin >> h;
trenes.inserta_tren(h);
}
main.cpp
i >> hh >> aux >> mm >> aux >> ss;
} 0101001010100101010100101000
HorarioTrenes trenes;
0100111101001010101100101010
1001010100101010101010100101
for (int i = 0; i < nTrenes; ++i) {
Hora h; cin >> h; 0100101010101000010101011100
trenes.inserta_tren(h);
} 1010100100101010111111101010
// consulta las horas 1100110101011100001001010100
for (int i = 0; i < nConsultas; ++i) {
Hora h; cin >> h; 0101100101010101010101010101
Hora sig;
bool existe = trenes.siguiente_tren(h, 0010101010101010000010101010
horario.cpp
sig);
if (!existe) cout << "NO\n"; // ya no 1101010010101010101010000101
horario.obj
hay trenes posteriores
else cout << sig << '\n'; 0101111001010101010111100110
}
return 0; 0101010110101010101001001010
}
101010101010110101010010100
#include "horario.h"
001011101010110010101
void HorarioTrenes::inserta_tren(Hora const&
001010100101010111110
hora) {
trenes.push_back(hora);
0101001010101010100101010101
} 1001111001010101010010101001
bool HorarioTrenes::siguiente_tren(Hora
0101001010100101010100101000
const& hora, Hora &/*sal*/ sig) const { 0100111101001010101100101010
bool encontrado = false;
for (int i = 0; i < trenes.size() && 1001010100101010101010100101
!encontrado; ++i) {
if (!(trenes[i] < hora)) { 0100101010101000010101011100
encontrado = true;
sig = trenes[i]; 1010100100101010111111101010
}
} 1100110101011100001001010100
return encontrado;
} 0101100101010101010101010101
0010101010101010000010101010
1101010010101010101010000101
0101111001010101010111100110
0101010110101010101001001010
101010101010110101010010100
Compilación separada
‣ Y después se unen para formar el ejecutable.
bool HorarioTrenes::siguiente_tren
main.cpp
#include <iostream>
using namespace std;
#include "horas.h"
#include "horario.h"
int main() {
int nTrenes, nConsultas;
cin >> nTrenes >> nConsultas;
Preprocesamiento de #include
horas.h
#ifndef HORAS
#define HORAS
horario.h
#ifndef HORARIO
#define HORARIO
horario.cpp
#endif
#endif
main.cpp
#include "horas.h"
#include "horario.h"
Preprocesamiento de #include: #pragma once
horas.h
#pragma once
¡No es estándar! horario.h
#pragma once
horario.cpp
main.cpp
#include "horas.h"
#include "horario.h"
Espacios de nombres