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