Tema 8 - Facultad de Informática

Anuncio
Fundamentos de la programación
8
GradoenIngenieríaInformática
GradoenIngenieríadelSoftware
GradoenIngenieríadeComputadores
LuisHernándezYáñez
Luis Hernández Yáñez
FacultaddeInformática
UniversidadComplutense
Programas multiarchivo y compilación separada Interfaz frente a implementación
Uso de módulos de biblioteca
Ejemplo: Gestión de una lista ordenada I
Compilación de programas multiarchivo
El preprocesador
Cada cosa en su módulo
Ejemplo: Gestión de una lista ordenada II
El problema de las inclusiones múltiples
Compilación condicional
Protección frente a inclusiones múltiples
Ejemplo: Gestión de una lista ordenada III
Implementaciones alternativas
Espacios de nombres
Implementaciones alternativas
Calidad y reutilización del software
Fundamentos de la programación: Programación modular
757
762
768
770
778
780
782
784
789
794
795
796
804
808
817
827
Luis Hernández Yáñez
Fundamentos de la programación: Programación modular
Página 757
Programasmultiarchivo
Códigofuenterepartidoentrevariosarchivos(módulos)
Cadamóduloconsusdeclaracionesysussubprogramas
 Módulo:Unidadfuncional(estructuradedatos,utilidades,...)
Principal
Lista
const int N = 10;
typedef double tArray[N];
typedef struct {
tArray elem;
int cont;
} tArray;
void init(tArray &lista);
void insert(tArray &lista, double elem, bool &ok);
void remove(tArray &lista, int pos, bool &ok);
...
Cálculos
int main() {
tArray lista;
bool ok;
init(lista);
cargar(lista, "bd.txt");
sort(lista);
double dato;
cout << "Dato: ";
cin >> dato;
insert(lista, dato, ok);
cout << min(lista) << endl; cout << max(lista) << endl;
cout << sum(lista) << endl;
guardar(lista, "bd.txt");
double mean(tArray lista);
Archivos
bool cargar(tArray &lista, string nombre);
double min(tArray lists);
double max(tArray lista);
double desv(tArray lista);
bool guardar(tArray lista, string nombre);
bool mezclar(string arch1, string arch2);
int minIndex(tArray lista);
int size(string nombre);
int maxIndex(tArray lista);
bool exportar(string nombre);
double sum(tArray lista);
return 0;
Luis Hernández Yáñez
}
Ejecutable
Fundamentos de la programación: Programación modular
Página 758
Compilaciónseparada
Cadamódulosecompilaacódigoobjetodeformaindependiente
Lista
lista.obj
const int N = 10;
typedef double tArray[N];
typedef struct {
tArray elem;
int cont;
} tArray;
void init(tArray &lista);
void insert(tArray &lista, double elem, bool &ok);
void remove(tArray &lista, int pos, bool &ok);
...
Cálculos
00101110101011001010010010101
00101010010101011111010101000
10100101010101010010101010101
01100101010101010101010101001
01010101010100000101010101101
01001010101010101000010101011
11001010101010111100110010101
01101010101010010010101001111
00101010101001010100101010010
10100101010100101000010011110
10010101011001010101001010100
10101010101010010101001010101
01000010101011100101010010100
01110101011101001101010100101
01011111110101011001101010111
00001001010100101010101010110
calculos.obj
Archivos
archivos.obj
bool cargar(tArray &lista, string nombre);
bool guardar(tArray lista, string nombre);
bool mezclar(string arch1, string arch2);
int size(string nombre);
bool exportar(string nombre);
double mean(tArray lista);
double min(tArray lists);
Luis Hernández Yáñez
double max(tArray lista);
double desv(tArray lista);
int minIndex(tArray lista);
int maxIndex(tArray lista);
double sum(tArray lista);
01011001010010010101001010100
10101011111010101000101001010
10101010010101010101011001010
10101010101010101001010101010
10100000101010101101010010101
01010101000010101011110010101
01010111100110010101011010101
01010010010101001111001010101
01001010100101010010101001010
10100101000010011110100101010
11001010101001010100101010101
01010010101001010101010000101
01011100101010010100011101010
11101001101010100101010111111
10101011001101010111000010010
10100101010101010110001111010
Fundamentos de la programación: Programación modular
11101010110010100100101010010
10100101010111110101010001010
01010101010100101010101010110
01010101010101010101010010101
01010101000001010101011010100
10101010101010000101010111100
10101010101111001100101010110
10101010100100101010011110010
10101010010101001010100101010
01010101001010000100111101001
01010110010101010010101001010
10101010100101010010101010100
00101010111001010100101000111
01010111010011010101001010101
11111101010110011010101110000
10010101001010101010101101111
Página 759
Compilaciónseparada
Alcompilarelprogramaprincipal,seadjuntanlosmóduloscompilados
Principal
Módulosdelprograma
int main() {
tArray lista;
bool ok;
init(lista);
cargar(lista, "bd.txt");
sort(lista);
double dato;
cout << "Dato: ";
cin >> dato;
insert(lista, dato, ok);
cout << min(lista) << endl; cout << max(lista) << endl;
cout << sum(lista) << endl;
guardar(lista, "bd.txt");
lista.obj
calculos.obj
Luis Hernández Yáñez
archivos.obj
...
return 0;
}
Bibliotecasdelsistema
iostream.obj
fstream.obj
math.obj
Ejecutable
Fundamentos de la programación: Programación modular
Página 760
...
Compilaciónseparada
¡Sólolosarchivosfuentemodificadosnecesitanserrecompilados!
Principal
lista.cpp
main.cpp
COMPILACIÓN
lista.obj

archivos.obj 
...
iostream.obj
fstream.obj
main.obj
math.obj
...
ENLACE
Ejecutable
Fundamentos de la programación: Programación modular
Página 761
Fundamentos de la programación: Programación modular
Página 762
Luis Hernández Yáñez
Luis Hernández Yáñez
calculos.obj
Luis Hernández Yáñez
Creacióndemódulosdebiblioteca
Códigodeunprogramadeunúnicoarchivo:
 Definicionesdeconstantes
 Declaracionesdetiposdedatos
 Prototiposdelossubprogramas
 Implementacióndelossubprogramas
 Implementacióndelafunciónmain()
Constantes,tiposyprototiposindicancómoseusa:Interfaz
 Estructuradedatosconlossubprogramasquelagestionan
 Conjuntodeutilidades(subprogramas)deusogeneral
 Etcétera
+Implementación delossubprogramas(cómosehace)
Fundamentos de la programación: Programación modular
Página 763
Luis Hernández Yáñez
Creacióndemódulosdebiblioteca
Interfaz:Definiciones/declaracionesdedatosyprototipos
¡Todoloqueelusuariodelaunidadfuncionalnecesitasaber!
Implementación:Códigodelossubprogramasquehaceneltrabajo
Nohayqueconocerloparausarlo:¡Seguroqueescorrecto!
Interfazeimplementaciónendosarchivosseparados:
 Cabecera:Definiciones/declaracionesdedatosyprototipos
 Implementación:Implementacióndelossubprogramas.
Archivodecabecera:extensión.h
Mismonombre
Archivodeimplementación:extensión.cpp
Repartimoselcódigoentreambosarchivos(lista.h/lista.cpp)
Fundamentos de la programación: Programación modular
Página 764
Creacióndemódulosdebiblioteca
Interfaz frenteaimplementación
lista.h
const int N = 10;
typedef double tArray[N];
typedef struct {
tArray elem;
int cont;
} tArray;
void init(tArray &lista);
void insert(tArray &lista, double elem, bool &ok);
Luis Hernández Yáñez
void remove(tArray &lista, int pos, bool &ok);
...
lista.cpp
Módulo
Unidad
Biblioteca
#include "lista.h"
void init(tArray &lista) {
lista.cont = 0;
}
void insert(tArray &lista, double elem, bool &ok) {
if (lista.cont == N) {
ok false;
}
else {
...
Siotromóduloquiereusaralgodeesabiblioteca:
Debeincluirelarchivodecabecera
main.cpp
#include "lista.h"
...
Losnombresdearchivosdecabecera
propios(nodelsistema)seencierran
entredoblescomillas,noentreángulos
Fundamentos de la programación: Programación modular
Página 765
Creacióndemódulosdebiblioteca
lista.h
const int N = 10;
typedef double tArray[N];
typedef struct {
tArray elem;
int cont;
} tArray;
Interfaz
Archivodecabecera(.h):todoloquenecesita
conocerotromódulo(oprogramaprincipal)
quequierautilizarsusservicios(subprogramas)
Ladirectiva#include añadelasdeclaracionesdelarchivo
decabeceraenelcódigodelmódulo(preprocesamiento):
void init(tArray &lista);
void insert(tArray &lista, double elem, bool &ok);
void remove(tArray &lista, int pos, bool &ok);
...
main.cpp
Luis Hernández Yáñez
#include "lista.h"
...
Preprocesador
Todoloquesenecesitasaberpara
comprobarsielcódigodemain.cpp
haceunusocorrectodelalista
(declaracionesyllamadas)
Fundamentos de la programación: Programación modular
main.cpp
const int N = 10;
typedef double tArray[N];
typedef struct {
tArray elem;
int cont;
} tArray;
void init(tArray &lista);
void insert(tArray &lista, double elem, bool &ok);
void remove(tArray &lista, int pos, bool &ok);
...
Página 766
Creacióndemódulosdebiblioteca
lista.cpp
Implementación
Compilarelmódulosignificacompilar
suarchivodeimplementación(.cpp)
Tambiénnecesitaconocersuspropiasdeclaraciones:
#include "lista.h"
void init(tArray &lista) {
lista.cont = 0;
}
void insert(tArray &lista, double elem, bool &ok) {
if (lista.cont == N) {
ok false;
}
else {
...
lista.cpp
lista.obj
00101110101011001010010010101
00101010010101011111010101000
10100101010101010010101010101
01100101010101010101010101001
01010101010100000101010101101
01001010101010101000010101011
11001010101010111100110010101
01101010101010010010101001111
00101010101001010100101010010
10100101010100101000010011110
10010101011001010101001010100
10101010101010010101001010101
01000010101011100101010010100
01110101011101001101010100101
01011111110101011001101010111
00001001010100101010101010110
Alcompilarelmódulosegeneraelcódigoobjeto
Sinosemodificanohaynecesidadderecompilar
Códigoqueusaelmódulo:
 Necesitasóloelarchivodecabeceraparacompilar
 Seadjuntaelcódigoobjetodelmóduloduranteelenlace
Fundamentos de la programación: Programación modular
Página 767
Fundamentos de la programación: Programación modular
Página 768
Luis Hernández Yáñez
Luis Hernández Yáñez
#include "lista.h"
...
Luis Hernández Yáñez
Usodemódulosdebiblioteca
Ejemplo:Gestióndeunalistaordenada(Tema7)
Todoloquetengaqueverconlalistaestaráensupropiomódulo
Ahoraelcódigoestarárepartidoentresarchivos:
 lista.h:archivodecabeceradelmódulodelista
 lista.cpp:implementacióndelmódulodelista
 bd.cpp:programaprincipalqueusalalista
Tantolista.cpp comobd.cpp debenincluiralprincipiolista.h
Módulopropio:doblescomillasenladirectiva#include
#include "lista.h"
Archivosdecabeceradebibliotecasdelsistema:entreángulos
Ynotienennecesariamentequellevarextensión.h
Fundamentos de la programación: Programación modular
Página 769
Archivo de cabecera
lista.h
Módulo:GestióndeunalistaordenadaI
Luis Hernández Yáñez
#include <string>
using namespace std;
const int N = 100;
typedef struct {
int codigo;
string nombre;
double sueldo;
} tRegistro;
typedef tRegistro tArray[N];
typedef struct {
tArray registros;
int cont;
} tLista;
const string BD = "bd.txt";
...
¡Documentabienelcódigo!
Fundamentos de la programación: Programación modular
Página 770
void mostrar(int pos, tRegistro registro);
void mostrar(const tLista &lista);
bool operator>(tRegistro opIzq, tRegistro opDer);
bool operator<(tRegistro opIzq, tRegistro opDer);
tRegistro nuevo();
void insertar(tLista &lista, tRegistro registro, bool &ok);
void eliminar(tLista &lista, int pos, bool &ok); // pos = 1..N
int buscar(tLista lista, string nombre);
void cargar(tLista &lista, bool &ok);
Luis Hernández Yáñez
void guardar(tLista lista);
Cadaprototipo,conuncomentarioqueexpliquesuutilidad/uso
(Aquíseomitenporcuestióndeespacio)
Fundamentos de la programación: Programación modular
Página 771
Implementación
lista.cpp
Módulo:GestióndeunalistaordenadaI
Luis Hernández Yáñez
#include <iostream>
#include <string>
using namespace std;
#include <fstream>
#include <iomanip>
#include "lista.h"
tRegistro nuevo() {
tRegistro registro;
cout << "Introduce el código: ";
cin >> registro.codigo;
cout << "Introduce el nombre: ";
cin >> registro.nombre;
cout << "Introduce el sueldo: ";
cin >> registro.sueldo;
return registro;
} ...
Fundamentos de la programación: Programación modular
Página 772
Luis Hernández Yáñez
void insertar(tLista &lista, tRegistro registro, bool &ok) {
ok = true;
if (lista.cont == N) {
ok = false; // Lista llena
}
else {
int i = 0;
while ((i < lista.cont) && (lista.registros[i] < registro)) {
i++;
}
// Insertamos en la posición i
for (int j = lista.cont; j > i; j‐‐) {
// Desplazamos a la derecha
lista.registros[j] = lista.registros[j ‐ 1];
}
lista.registros[i] = registro;
lista.cont++;
}
} ...
Fundamentos de la programación: Programación modular
Página 773
Luis Hernández Yáñez
void eliminar(tLista &lista, int pos, bool &ok) { // pos = 1..
ok = true;
if ((pos < 1) || (pos > lista.cont)) {
ok = false; // Posición inexistente
}
else {
pos‐‐; // Pasamos a índice del array
for (int i = pos + 1; i < lista.cont; i++) {
// Desplazamos a la izquierda
lista.registros[i ‐ 1] = lista.registros[i];
}
lista.cont‐‐;
}
}
...
Fundamentos de la programación: Programación modular
Página 774
Programa principal
bd.cpp
Módulo:GestióndeunalistaordenadaI
#include <iostream>
using namespace std;
#include "lista.h"
Luis Hernández Yáñez
int menu();
int main() {
tLista lista;
bool ok;
int op, pos;
cargar(lista, ok);
if (!ok) {
cout << "No se ha podido abrir el archivo!" << endl;
}
else {
do {
mostrar(lista);
op = menu(); ...
Luis Hernández Yáñez
Fundamentos de la programación: Programación modular
Página 775
if (op == 1) {
tRegistro registro = nuevo();
insertar(lista, registro, ok);
if (!ok) {
cout << "Error: Lista llena!" << endl;
}
}
else if (op == 2) {
cout << "Posición: ";
cin >> pos;
eliminar(lista, pos, ok);
if (!ok) {
cout << "Error: Posicion inexistente!" << endl;
}
}
else if (op == 3) {
string nombre;
cin.sync();
cout << "Nombre: ";
cin >> nombre;
int pos = buscar(lista, nombre);
...
Fundamentos de la programación: Programación modular
Página 776
if (pos == ‐1) {
cout << "No se ha encontrado!" << endl;
}
else {
cout << "Encontrado en la posición " << pos << endl;
}
}
} while (op != 0);
guardar(lista);
}
return 0;
int menu() {
cout << endl;
cout << "1 ‐ Insertar" << endl;
cout << "2 ‐ Eliminar" << endl;
cout << "3 ‐ Buscar" << endl;
cout << "0 ‐ Salir" << endl;
int op;
do {
...
Fundamentos de la programación: Programación modular
Página 777
Fundamentos de la programación: Programación modular
Página 778
Luis Hernández Yáñez
Luis Hernández Yáñez
}
G++
Archivosdecabeceraeimplementaciónenlamismacarpeta
Listamostodoslos.cpp enlaordeng++:
D:\FP\Tema08>g++ ‐o bd.exe lista.cpp bd.cpp
Recuerdaquesólosecompilanlos.cpp
VisualC++/Studio
Alosarchivosdecabecera
losllamadeencabezado
ConDepurar ‐> Generar solución
secompilantodoslos.cpp
Fundamentos de la programación: Programación modular
Página 779
Fundamentos de la programación: Programación modular
Página 780
Luis Hernández Yáñez
Luis Hernández Yáñez
Archivosdecabeceraeimplementaciónengruposdistintos:
Directivas:#...
Antesdecompilarseponeenmarchaelpreprocesador
Interpretalasdirectivasygeneraunúnicoarchivotemporalcon
todoelcódigodelmódulooprograma
Comoenlainclusión(directiva#include):
#include <string>
using namespace std;
int menu();
#include <string>
using namespace std;
...
const int N = 100;
typedef struct {
int codigo;
string nombre;
double sueldo;
} tRegistro;
typedef struct {
int codigo;
string nombre;
double sueldo;
} tRegistro;
typedef tRegistro
tArray[N];
typedef tRegistro
tArray[N];
typedef struct {
tArray registros;
int cont;
} tLista;
...
typedef struct {
tArray registros;
int cont;
} tLista;
...
int menu();
...
Fundamentos de la programación: Programación modular
Página 781
Fundamentos de la programación: Programación modular
Página 782
Luis Hernández Yáñez
Luis Hernández Yáñez
const int N = 100;
#include "lista.h"
Distribuirlafuncionalidaddelprogramaenmódulos
Luis Hernández Yáñez
Encapsulacióndeunconjuntodesubprogramasrelacionados:
 Porlaestructuradedatossobrelaquetrabajan
 Subprogramasdeutilidad
Amenudolasestructurasdedatoscontienenotrasestructuras:
const int N = 100;
typedef struct {
int codigo;
string nombre;
double sueldo;
} tRegistro;
typedef tRegistro tArray[N];
typedef struct {
tArray registros;
int cont;
} tLista;
Listaderegistros:
 EstructuratRegistro
 EstructuratLista
(contienetRegistro)
Cadaestructura,ensumódulo
Fundamentos de la programación: Programación modular
Página 783
Cabecera
registro.h
GestióndeunalistaordenadaII
#include <string>
using namespace std;
Luis Hernández Yáñez
typedef struct {
int codigo;
string nombre;
double sueldo;
} tRegistro;
tRegistro nuevo();
bool operator>(tRegistro opIzq, tRegistro opDer);
bool operator<(tRegistro opIzq, tRegistro opDer);
void mostrar(int pos, tRegistro registro);
Fundamentos de la programación: Programación modular
Página 784
Implementación
registro.cpp
GestióndeunalistaordenadaII
Luis Hernández Yáñez
#include <iostream>
#include <string>
using namespace std;
#include <iomanip>
#include "registro.h"
tRegistro nuevo() {
tRegistro registro;
cout << "Introduce el código: ";
cin >> registro.codigo;
cout << "Introduce el nombre: ";
cin >> registro.nombre;
cout << "Introduce el sueldo: ";
cin >> registro.sueldo;
return registro;
}
bool operator>(tRegistro opIzq, tRegistro opDer) {
return opIzq.nombre > opDer.nombre;
} ...
Fundamentos de la programación: Programación modular
Página 785
Cabecera
lista2.h
GestióndeunalistaordenadaII
#include <string>
using namespace std;
#include "registro.h"
Luis Hernández Yáñez
const int N = 100;
typedef tRegistro tArray[N];
typedef struct {
tArray registros;
int cont;
} tLista;
const string BD = "bd.txt";
void insertar(tLista &lista, tRegistro registro, bool &ok);
void eliminar(tLista &lista, int pos, bool &ok); // pos = 1..N
int buscar(tLista lista, string nombre);
void mostrar(const tLista &lista);
void cargar(tLista &lista, bool &ok);
void guardar(tLista lista);
Fundamentos de la programación: Programación modular
Página 786
Implementación
lista2.cpp
GestióndeunalistaordenadaII
Luis Hernández Yáñez
#include <iostream>
using namespace std;
#include <fstream>
#include "lista2.h"
void insertar(tLista &lista, tRegistro registro, bool &ok) {
ok = true;
if (lista.cont == N) {
ok = false; // Lista llena
}
else {
int i = 0;
while ((i < lista.cont) && (lista.registros[i] < registro)) {
i++;
}
// Insertamos en la posición i
for (int j = lista.cont; j > i; j‐‐) {// Desplazar a la derecha
lista.registros[j] = lista.registros[j ‐ 1];
}
...
Fundamentos de la programación: Programación modular
Página 787
bd2.cpp
GestióndeunalistaordenadaII
#include <iostream>
using namespace std;
#include "registro.h"
#include "lista2.h"
int menu();
Luis Hernández Yáñez
int main() {
tLista lista;
bool ok;
int op, pos;
¡Nointentescompilaresteejemplo!
Tieneerrores
cargar(lista, ok);
if (!ok) {
cout << "No se pudo abrir el archivo!" << endl;
}
else {
do {
mostrar(lista);
op = menu();
...
Fundamentos de la programación: Programación modular
Página 788
Luis Hernández Yáñez
Fundamentos de la programación: Programación modular
Página 789
GestióndeunalistaordenadaII
2módulosyelprogramaprincipal:
bd2.cpp
...
#include "registro.h"
#include "lista2.h"
...
registro.h
#include <string>
...
registro.cpp
...
#include "registro.h"
...
lista2.h
Luis Hernández Yáñez
...
#include "registro.h"
...
lista2.cpp
Incluye...
...
#include "lista2.h"
...
Fundamentos de la programación: Programación modular
Página 790
GestióndeunalistaordenadaII
Preprocesamientode#include:
#include <iostream>
using namespace std;
#include <string>
using namespace std;
typedef struct {
...
} tRegistro;
...
#include "registro.h"
#include "lista2.h"
int menu();
#include <string>
using namespace std;
#include "registro.h"
...
Luis Hernández Yáñez
const int N = 100;
typedef tRegistro tArray[N];
typedef struct {
tArray registros;
int cont;
} tLista;
...
#include <string>
using namespace std;
typedef struct {
...
} tRegistro;
...
Fundamentos de la programación: Programación modular
Página 791
GestióndeunalistaordenadaII
Preprocesamientode#include:
#include <iostream>
using namespace std;
#include <string>
using namespace std;
typedef struct {
...
} tRegistro;
...
Sustituido
#include <string>
using namespace std;
#include <string>
using namespace std;
typedef struct {
...
} tRegistro;
...
#include "lista2.h"
Luis Hernández Yáñez
int menu();
...
const int N = 100;
typedef tRegistro tArray[N];
typedef struct {
tArray registros;
int cont;
} tLista;
...
Fundamentos de la programación: Programación modular
Página 792
GestióndeunalistaordenadaII
#include <iostream>
using namespace std;
const int N = 100;
typedef tRegistro tArray[N];
typedef struct {
tArray registros;
int cont;
} tLista;
...
#include <string>
using namespace std;
typedef struct {
...
} tRegistro;
...
int menu();
...
Luis Hernández Yáñez
#include <string>
using namespace std;
#include <string>
using namespace std;
¡Identificadorduplicado!
typedef struct {
...
} tRegistro;
...
Fundamentos de la programación: Programación modular
Página 793
Compilacióncondicional
Directivas#ifdef,#ifndef,#else y#endif
Seusanenconjunciónconladirectiva#define
Luis Hernández Yáñez
#define X
#ifdef X
... // Código if
[#else
... // Código else
]
#endif
#define X
#ifndef X
... // Código if
[#else
... // Código else
]
#endif
Ladirectiva#define defineunsímbolo(identificador)
Izquierda:secompilaráel“Códigoif”ynoel“Códigoelse”
Derecha:alrevés,onadasinohayelse
Lascláusulaselsesonopcionales
Fundamentos de la programación: Programación modular
Página 794
Protecciónfrenteainclusionesmúltiples
lista2.cpp ybd2.cpp incluyenregistro.h
 ¡Identificadoresduplicados!
Cadamódulodebeincluirseunaysólounavez
Protecciónfrenteainclusionesmúltiples:
Luis Hernández Yáñez
#ifndef X
#define X
... // Módulo
#endif
ElsímboloXdebeserúnico
paracadamódulodelaaplicación
LaprimeraveznoestádefinidoelsímboloX:seincluyeydefine
LassiguientesveceselsímboloX yaestádefinido:noseincluye
SímboloX:nombredelarchivocon_enlugarde.
registro_h,lista2_h,...
Fundamentos de la programación: Programación modular
Página 795
Cabecera
registrofin.h
Gestióndeunalistaordenada III
#ifndef registrofin_h
#define registrofin_h
#include <string>
using namespace std;
Luis Hernández Yáñez
typedef struct {
int codigo;
string nombre;
double sueldo;
} tRegistro;
tRegistro nuevo();
bool operator>(tRegistro opIzq, tRegistro opDer);
bool operator<(tRegistro opIzq, tRegistro opDer);
void mostrar(int pos, tRegistro registro);
#endif
Fundamentos de la programación: Programación modular
Página 796
Implementación
registrofin.cpp
GestióndeunalistaordenadaIII
Luis Hernández Yáñez
#include <iostream>
#include <string>
using namespace std;
#include <iomanip>
#include "registrofin.h"
tRegistro nuevo() {
tRegistro registro;
cout << "Introduce el código: ";
cin >> registro.codigo;
cout << "Introduce el nombre: ";
cin >> registro.nombre;
cout << "Introduce el sueldo: ";
cin >> registro.sueldo;
return registro;
}
bool operator>(tRegistro opIzq, tRegistro opDer) {
return opIzq.nombre > opDer.nombre;
} ...
Fundamentos de la programación: Programación modular
Página 797
Cabecera
listafin.h
GestióndeunalistaordenadaIII
Luis Hernández Yáñez
#ifndef listafin_h
#define listafin_h
#include <string>
using namespace std;
#include "registrofin.h"
const int N = 100;
typedef tRegistro tArray[N];
typedef struct {
tArray registros;
int cont;
} tLista;
const string BD = "bd.txt";
void mostrar(const tLista &lista);
void insertar(tLista &lista, tRegistro registro, bool &ok);
void eliminar(tLista &lista, int pos, bool &ok); // pos = 1..N
int buscar(tLista lista, string nombre);
void cargar(tLista &lista, bool &ok);
void guardar(tLista lista);
#endif
Fundamentos de la programación: Programación modular
Página 798
Implementación
listafin.cpp
GestióndeunalistaordenadaIII
Luis Hernández Yáñez
#include <iostream>
using namespace std;
#include <fstream>
#include "listafin.h"
void insertar(tLista &lista, tRegistro registro, bool &ok) {
ok = true;
if (lista.cont == N) {
ok = false; // lista llena
}
else {
int i = 0;
while ((i < lista.cont) && (lista.registros[i] < registro)) {
i++;
}
// Insertamos en la posición i
for (int j = lista.cont; j > i; j‐‐) {
// Desplazamos a la derecha
lista.registros[j] = lista.registros[j ‐ 1];
}
...
Fundamentos de la programación: Programación modular
Página 799
bdfin.cpp
GestióndeunalistaordenadaIII
#include <iostream>
using namespace std;
#include "registrofin.h"
#include "listafin.h"
int menu();
Luis Hernández Yáñez
int main() {
tLista lista;
bool ok;
int op, pos;
¡Ahorayapuedescompilarlo!
cargar(lista, ok);
if (!ok) {
cout << "No se pudo abrir el archivo!" << endl;
}
else {
do {
mostrar(lista);
op = menu();
...
Fundamentos de la programación: Programación modular
Página 800
GestióndeunalistaordenadaIII
Preprocesamientode#include enbdfin.cpp:
#include <iostream>
using namespace std;
#ifndef registrofin_h
#define registrofin_h
#include <string>
using namespace std;
#include "registrofin.h"
#include "listafin.h"
typedef struct {
...
} tRegistro;
...
int menu();
...
Luis Hernández Yáñez
registrofin_h nosehadefinidotodavía
Fundamentos de la programación: Programación modular
Página 801
GestióndeunalistaordenadaIII
Preprocesamientode#include enbdfin.cpp:
#include <iostream>
using namespace std;
#define registrofin_h
#include <string>
using namespace std;
Luis Hernández Yáñez
typedef struct {
...
} tRegistro;
...
#include "listafin.h"
#ifndef listafin_h
#define listafin_h
#include <string>
using namespace std;
#include "registrofin.h"
const int N = 100;
typedef tRegistro tArray[N];
typedef struct {
tArray registros;
int cont;
} tLista;
...
int menu();
...
listafin_h nosehadefinidotodavía
Fundamentos de la programación: Programación modular
Página 802
GestióndeunalistaordenadaIII
Preprocesamientode#include enbdfin.cpp:
typedef struct {
...
} tRegistro;
...
#ifndef registrofin_h
#define registrofin_h
#include <string>
using namespace std;
#define listafin_h
#include <string>
using namespace std;
#include "registrofin.h"
typedef struct {
...
} tRegistro;
...
...
int menu();
¡registrofin_h yaestádefinido!
...
Fundamentos de la programación: Programación modular
Página 803
Fundamentos de la programación: Programación modular
Página 804
Luis Hernández Yáñez
Luis Hernández Yáñez
#include <iostream>
using namespace std;
#define registrofin_h
#include <string>
using namespace std;
Mismainterfaz,implementaciónalternativa
lista.h
#include <string>
using namespace std;
#include "registrofin.h"
Lista
ordenada
const int N = 100;
typedef tRegistro tArray[N];
typedef struct {
tArray registros;
int cont;
} tLista;
Lista
noordenada
Luis Hernández Yáñez
void insertar(tLista &lista, tRegistro registro, bool &ok);
void insertar(tLista &lista, tRegistro registro, bool &ok) {
ok = true;
void insertar(tLista &lista, tRegistro registro, bool &ok) {
if (lista.cont == N) {
ok = true;
ok = false; // Lista llena
if (lista.cont == N) {
}
ok = false; // Lista llena
else {
}
int i = 0;
else {
while ((i < lista.cont) && (lista.registros[i] < registro)) {
i++;
lista.registros[lista.cont] = registro;
}
lista.cont++;
// Insertamos en la posición i
}
for (int j = lista.cont; j > i; j‐‐) { }
// Desplazamos a la derecha
lista.registros[j] = lista.registros[j ‐ 1];
...
Fundamentos de la programación: Programación modular
Página 805
Mismainterfaz,implementaciónalternativa
listaDES.cpp:Listanoordenada
...
#include "lista.h"
void insertar(tLista &lista, tRegistro registro, bool &ok) {
ok = true;
if (lista.cont == N) {
ok = false; // Lista llena
...
}
#include "lista.h"
else {
lista.registros[lista.cont] = registro;
void insertar(tLista &lista, tRegistro registro, bool &ok) {
lista.cont++;
ok = true;
}
if (lista.cont == N) {
}
ok = false; // Lista llena
...
}
else {
int i = 0;
while ((i < lista.cont) && (lista.registros[i] < registro)) {
i++;
}
// Insertamos en la posición i
for (int j = lista.cont; j > i; j‐‐) {
// Desplazamos a la derecha
lista.registros[j] = lista.registros[j ‐ 1];
}
lista.registros[i] = registro;
...
Luis Hernández Yáñez
listaORD.cpp:Listaordenada
Fundamentos de la programación: Programación modular
Página 806
Mismainterfaz,implementaciónalternativa
Alcompilar,incluimosunarchivodeimplementaciónuotro:
¿Programaconlistaordenadaoconlistadesordenada?
g++ ‐o programa.exe registrofin.cpp listaORD.cpp ...
Incluyelaimplementacióndelalistaconordenación
g++ ‐o programa.exe registrofin.cpp listaDES.cpp ...
Luis Hernández Yáñez
Incluyelaimplementacióndelalistasinordenación
Página 807
Fundamentos de la programación: Programación modular
Página 808
Luis Hernández Yáñez
Fundamentos de la programación: Programación modular
Agrupacioneslógicasdedeclaraciones
Espaciodenombres:agrupacióndedeclaraciones
(tipos,datos,subprogramas)bajounnombredistintivo
Formadeunespaciodenombres:
namespace nombre {
// Declaraciones
}
Luis Hernández Yáñez
Porejemplo:
namespace miEspacio {
int i;
double d;
}
Variablesi yd declaradasenelespaciodenombresmiEspacio
Fundamentos de la programación: Programación modular
Página 809
Accesoamiembrosdeunespaciodenombres
Operadorderesolucióndeámbito (::)
AccesoalasvariablesdelespaciodenombresmiEspacio:
Nombredelespacioyoperadorderesolucióndeámbito
miEspacio::i
miEspacio::d
Luis Hernández Yáñez
Puedehaberentidadesconelmismoidentificadorendistintos
módulosoenámbitosdistintosdeunmismomódulo
Cadadeclaraciónenunespaciodenombresdistinto:
namespace primero {
int x = 5;
}
namespace segundo {
double x = 3.1416;
}
Ahorasedistingueentreprimero::x ysegundo::x
Fundamentos de la programación: Programación modular
Página 810
using
Luis Hernández Yáñez
Introduce unnombrede un espaciodenombresen elámbitoactual:
#include <iostream> using namespace std; namespace primero { int x = 5; int y = 10; 5
} namespace segundo { 2.7183
double x = 3.1416; 10
double y = 2.7183; } 3.1416
int main() { using primero::x; using segundo::y; cout << x << endl; // x es primero::x
cout << y << endl; // y es segundo::y
cout << primero::y << endl; // espacio explícito
cout << segundo::x << endl; // espacio explícito
return 0; }
Fundamentos de la programación: Programación modular
Página 811
using namespace
Luis Hernández Yáñez
Introduce todoslosnombresde un espacioen elámbitoactual:
#include <iostream> using namespace std; namespace primero { int x = 5; 5
int y = 10; using [namespace]
10
} sólotieneefecto
namespace segundo { 3.1416
double x = 3.1416; en el bloque
2.7183
double y = 2.7183; enque seencuentra
} int main() { using namespace primero; cout << x << endl; // x es primero::x
cout << y << endl; // y es primero::y
cout << segundo::x << endl; // espacio explícito
cout << segundo::y << endl; // espacio explícito
return 0; }
Fundamentos de la programación: Programación modular
Página 812
Luis Hernández Yáñez
#ifndef listaEN_h
#define listaEN_h
#include "registrofin.h"
namespace ord { // Lista ordenada
const int N = 100;
typedef tRegistro tArray[N];
typedef struct {
tArray registros;
int cont;
} tLista;
const string BD = "bd.txt";
void mostrar(const tLista &lista);
void insertar(tLista &lista, tRegistro registro, bool &ok);
void eliminar(tLista &lista, int pos, bool &ok); // 1..N
int buscar(tLista lista, string nombre);
void cargar(tLista &lista, bool &ok);
void guardar(tLista lista);
} // namespace
#endif
Fundamentos de la programación: Programación modular
Página 813
Implementación
#include <iostream>
#include <fstream>
using namespace std;
#include "listaEN.h"
void ord::insertar(tLista &lista, tRegistro registro, bool &ok) {
// ...
}
Luis Hernández Yáñez
void ord::eliminar(tLista &lista, int pos, bool &ok) {
// ...
}
int ord::buscar(tLista lista, string nombre) {
// ...
}
...
Fundamentos de la programación: Programación modular
Página 814
Usodelespaciodenombres
QuienutilicelistaEN.h debeponerelnombredelespacio:
#include <iostream>
using namespace std;
#include "registrofin.h"
#include "listaEN.h"
Luis Hernández Yáñez
int menu();
int main() {
ord::tLista lista;
bool ok;
ord::cargar(lista, ok);
if (!ok) {
cout << "No se pudo abrir el archivo!" << endl;
}
else {
ord::mostrar(lista);
...
Ousarunainstrucciónusing namespace ord;
Fundamentos de la programación: Programación modular
Página 815
Usodelespaciodenombres
#include <iostream>
using namespace std;
#include "registrofin.h"
#include "listaEN.h"
using namespace ord;
Luis Hernández Yáñez
int menu();
int main() {
tLista lista;
bool ok;
cargar(lista, ok);
if (!ok) {
cout << "No se pudo abrir el archivo!" << endl;
}
else {
mostrar(lista);
...
Fundamentos de la programación: Programación modular
Página 816
Implementacionesalternativas
Distintosespaciosdenombresparadistintasimplementaciones
¿Listaordenadaolistadesordenada?
Luis Hernández Yáñez
namespace ord { // Lista ordenada
const int N = 100;
typedef tRegistro tArray[N];
...
void mostrar(const tLista &lista);
void insertar(tLista &lista, tRegistro registro, bool &ok);
...
} // namespace
namespace des { // Lista desordenada
const int N = 100;
typedef tRegistro tArray[N];
...
void mostrar(const tLista &lista);
void insertar(tLista &lista, tRegistro registro, bool &ok);
...
} // namespace
Fundamentos de la programación: Programación modular
Página 817
Cabecera
listaEN.h
Implementacionesalternativas
Todolocomúnpuedeestarfueradelaestructuranamespace:
#ifndef listaEN_H
#define listaEN_H
#include "registrofin.h"
const int N = 100;
Luis Hernández Yáñez
typedef tRegistro tArray[N];
typedef struct {
tArray registros;
int cont;
} tLista;
void mostrar(const tLista &lista);
void eliminar(tLista &lista, int pos, bool &ok); // pos = 1..N
...
Fundamentos de la programación: Programación modular
Página 818
Luis Hernández Yáñez
namespace ord { // Lista ordenada
const string BD = "bd.txt";
void insertar(tLista &lista, tRegistro registro, bool &ok);
int buscar(tLista lista, string nombre);
void cargar(tLista &lista, bool &ok);
void guardar(tLista lista);
} // namespace
namespace des { // Lista desordenada
const string BD = "bddes.txt";
void insertar(tLista &lista, tRegistro registro, bool &ok);
int buscar(tLista lista, string nombre);
void cargar(tLista &lista, bool &ok);
void guardar(tLista lista);
} // namespace
#endif
cargar() yguardar() sedistinguenporqueusan
supropiaBD,peroseimplementanexactamenteigual
Fundamentos de la programación: Programación modular
Página 819
listaEN.cpp
#include <iostream>
using namespace std;
#include <fstream>
#include "listaEN.h"
// IMPLEMENTACIÓN DE LOS SUBPROGRAMAS COMUNES
void eliminar(tLista &lista, int pos, bool &ok) { // ...
}
Luis Hernández Yáñez
void mostrar(const tLista &lista) { // ...
}
// IMPLEMENTACIÓN DE LOS SUBPROGRAMAS DEL ESPACIO DE NOMBRES ord
void ord::insertar(tLista &lista, tRegistro registro, bool &ok) {
ok = true;
if (lista.cont == N) {
ok = false; // Lista llena
}
else {
int i = 0;
while ((i < lista.cont) && (lista.registros[i] < registro)) {
i++;
} ...
Fundamentos de la programación: Programación modular
Página 820
for (int j = lista.cont; j > i; j‐‐) {
lista.registros[j] = lista.registros[j ‐ 1];
}
lista.registros[i] = registro;
lista.cont++;
}
Luis Hernández Yáñez
}
int ord::buscar(tLista lista, string nombre) {
int ini = 0, fin = lista.cont ‐ 1, mitad;
bool encontrado = false;
while ((ini <= fin) && !encontrado) {
mitad = (ini + fin) / 2;
if (nombre == lista.registros[mitad].nombre) {
encontrado = true;
}
else if (nombre < lista.registros[mitad].nombre) {
fin = mitad ‐ 1;
}
else {
ini = mitad + 1;
}
} ...
Fundamentos de la programación: Programación modular
Página 821
if (encontrado) {
mitad++;
}
else {
mitad = ‐1;
}
return mitad;
}
void ord::cargar(tLista &lista, bool &ok) { // ...
}
Luis Hernández Yáñez
void ord::guardar(tLista lista) { // ...
}
...
Fundamentos de la programación: Programación modular
Página 822
// IMPLEMENTACIÓN DE LOS SUBPROGRAMAS DEL ESPACIO DE NOMBRES des
Luis Hernández Yáñez
void des::insertar(tLista &lista, tRegistro registro, bool &ok) {
ok = true;
if (lista.cont == N) {
ok = false; // Lista llena
}
else {
lista.registros[lista.cont] = registro;
lista.cont++;
}
}
int des::buscar(tLista lista, string nombre) {
int pos = 0;
bool encontrado = false;
while ((pos < lista.cont) && !encontrado) {
if (nombre == lista.registros[pos].nombre) {
encontrado = true;
}
else {
pos++;
}
} ...
Fundamentos de la programación: Programación modular
Página 823
if (encontrado) {
pos++;
}
else {
pos = ‐1;
}
return pos;
}
void des::cargar(tLista &lista, bool &ok) { // ...
}
Luis Hernández Yáñez
void des::guardar(tLista lista) { // ...
}
Fundamentos de la programación: Programación modular
Página 824
bdEN.cpp
Programaprincipal
#include <iostream>
using namespace std;
#include "registrofin.h"
#include "listaEN.h"
using namespace ord;
Luis Hernández Yáñez
int menu();
int main() {
tLista lista;
bool ok;
...
tRegistro registro = nuevo();
insertar(lista, registro, ok);
if (!ok) {
...
Fundamentos de la programación: Programación modular
Página 825
bdEN.cpp
Programaprincipal
#include <iostream>
using namespace std;
#include "registrofin.h"
#include "listaEN.h"
using namespace des;
Luis Hernández Yáñez
int menu();
int main() {
tLista lista;
bool ok;
...
tRegistro registro = nuevo();
insertar(lista, registro, ok);
if (!ok) {
...
Fundamentos de la programación: Programación modular
Página 826
Luis Hernández Yáñez
Fundamentos de la programación: Programación modular
Página 827
Softwaredecalidad
Luis Hernández Yáñez
Elsoftwaredebeserdesarrolladoconbuenasprácticasde
ingenieríadelsoftwarequeasegurenunbuenniveldecalidad
Losdistintosmódulosdelaaplicacióndebenserprobados
exhaustivamente,tantodeformaindependientecomoensu
relaciónconlosdemásmódulos
Lapruebaydepuraciónesmuyimportanteytodoslosequipos
deberánseguirbuenaspautasparaasegurarlacalidad
Losmódulosdebenserigualmentebiendocumentados,de
formaqueotrosdesarrolladorespuedanaprovecharlos
Fundamentos de la programación: Programación modular
Página 828
Luis Hernández Yáñez
Pruebaexhaustiva
Elsoftwaredebeserprobadoexhaustivamente
Debemosintentardescubrirtodosloserroresposible
Loserroresdebenserdepurados,corrigiendoelcódigo
Pruebassobrelistas:
 Listainicialmentevacía
 Listainicialmentellena
 Listaconunnúmerointermediodeelementos
 Archivonoexistente
Etcétera...
Sehandeprobartodaslasopciones/situacionesdelprograma
Enlasclasesprácticasveremoscómosedepuraelsoftware
Fundamentos de la programación: Programación modular
Página 829
Noreinventemoslarueda
Desarrollarelsoftwarepensandoensuposiblereutilización
Unsoftwaredecalidaddebepoderserfácilmentereutilizado
Nuestrosmódulosdebenserfácilmenteusadosymodificados
Luis Hernández Yáñez
Porejemplo:Nuevaaplicaciónquegestioneunalistadelongitud
variablederegistrosconNIF,nombre,apellidosyedad
Partiremosdelosmódulosregistro ylista existentes
Lasmodificacionesbásicamenteafectaránalmóduloregistro
Fundamentos de la programación: Programación modular
Página 830
LicenciaCC(Creative Commons)
Estetipodelicenciasofrecenalgunosderechosaterceraspersonas
bajociertascondiciones.
Estedocumentotieneestablecidaslassiguientes:
Reconocimiento(Attribution):
Encualquierexplotacióndelaobraautorizadaporlalicencia
haráfaltareconocerlaautoría.
Luis Hernández Yáñez
Nocomercial(Noncommercial):
Laexplotacióndelaobraquedalimitadaausosnocomerciales.
Compartirigual(Sharealike):
Laexplotaciónautorizadaincluyelacreacióndeobrasderivadas
siemprequemantenganlamismalicenciaalserdivulgadas.
Pulsaenlaimagendearribaaladerechaparasabermás.
Fundamentos de la programación: Programación modular
Página 831
Descargar