Professional Documents
Culture Documents
Desarrollo de proyectos de
programación
Desarrollo de un módulo
de biblioteca C++ para trabajar con
multiconjuntos de números primos
1
1. Representación del tipo Multiconjunto
• Debe definirse la representación de los datos de tipo Multiconjunto
que representan un multiconjunto al que pueden pertenecer
exclusivamente de los primeros NUM_PRIMOS números primos (2, 3, 5,
7, 9, 11, 13, 17, 19, 23, 29, etc.) :
– Se definirá la constante entera NUM_PRIMOS. Por ejemplo:
struct Multiconjunto {
. . .
};
/*
* Se van a definir multiconjuntos a los que pueden pertenecer
* exclusivamente los NUM_PRIMOS primeros números primos
*/
const int NUM_PRIMOS = 25;
/*
* Representa un multiconjunto al que pueden pertenecer,
* exclusivamente, los NUM_PRIMOS primeros números primos:
* multiplicidad[0]: su valor es la multiplicidad del 2 (primo núm. 1)
* multiplicidad[1]: su valor es la multiplicidad del 3 (primo núm. 2)
* multiplicidad[2]: su valor es la multiplicidad del 5 (primo núm. 3)
* multiplicidad[3]: su valor es la multiplicidad del 7 (primo núm. 4)
* multiplicidad[4]: su valor es la multiplicidad del 11 (primo núm. 5)
* . ..
*/
struct Multiconjunto {
int multiplicidad[NUM_PRIMOS];
};
3
/*
* Fichero multiconjunto.cc de implementación del módulo
* multiconjunto
*/
#include <iostream>
#include <iomanip>
#include <fstream>
#include "multiconjunto.h"
/* Almacena los NUM_PRIMOS primeros números primos */
const int PRIMOS[] = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
73, 79, 83, 89, 97
};
4
2. Diseño de las funciones del módulo
En primer lugar deben especificarse cada una de las catorce
funciones del módulo multiconjunto, que se detallan a
continuación, junto con una frase orientativa sobre su
comportamiento esperado. Se recuerda que cada especificación
exige una precondición y una postcondición.
Después de haber sido especificada cada función, debe escribirse
el código C++ del fichero de implementación del módulo
multiconjunto que incluirá el código de las catorce funciones.
Sugerencia: Definir en el fichero de implementación un vector
constante que almacene los NUM_PRIMOS primeros números
primos.
5
Presentación informal de las funciones que permiten crear y
modificar un multiconjunto de números primos:
// para crear un multiconjunto sin ningún elemento
Multiconjunto vacio ();
// para incorporar un número primo m‐veces a un multiconjunto
void incluir (Multiconjunto& A, const int p, const int m);
// para incorporar un número primo una vez a un multiconjunto
void incluir (Multiconjunto& A, const int p);
// para retirar m‐items de un número primo de un multiconjunto
void retirar (Multiconjunto& A, const int p, const int m);
// para retirar todos los items de un número primo de un
// multiconjunto
void eliminar (Multiconjunto& A, const int p);
. . .
6
Presentación informal de las funciones para consultar la
información de un multiconjunto de números primos:
. . .
// para saber la multiplicidad de un número primo en un
// multiconjunto
int multiplicidad (const Multiconjunto A, const int p);
// para saber el número total de elementos de un multiconjunto
int cardinalidad (const Multiconjunto A);
// para saber el número total de elementos diferentes de un
// multiconjunto
int numDiferentes (const Multiconjunto A);
// para presentar por pantalla el contenido de un multiconjunto
int mostrar (const Multiconjunto A);
. . .
7
Presentación informal de las funciones para operar con
multiconjuntos de números primos:
. . .
// para calcular la unión de dos multiconjuntos
Multiconjunto opUnion (const Multiconjunto A,
const Multiconjunto B);
// para calcular la intersección de dos multiconjuntos
Multiconjunto opInterseccion (const Multiconjunto A,
const Multiconjunto B);
// para calcular la diferencia de dos multiconjuntos
Multiconjunto opDiferencia (const Multiconjunto A,
const Multiconjunto B);
. . .
8
Presentación informal de las funciones para almacenar
multiconjuntos de números primos en un fichero binario y
recuperar de él la secuencia de multiconjuntos de números
primos almacenada en él previamente:
. . .
// para almacenar la información de una colección de
// multiconjuntos en un fichero binario
void guardar (const char nombreFichero[],
const Multiconjunto T[], const int n);
// para recuperar la información de una colección de
// multiconjuntos almacenada en un fichero binario
bool recuperar (const char nombreFichero[],
Multiconjunto T[], int& n);
9
La función vacio():
// para crear un multiconjunto sin ningún elemento
Multiconjunto vacio ();
/*
* Pre: … su precondición …
* Post: … su postcondición …
*/
Multiconjunto vacio () { … su código … }
10
La función vacio():
// para crear un multiconjunto sin ningún elemento
Multiconjunto vacio ();
/*
* Pre: ‐‐‐
* Post: Devuelve un multiconjunto vacío de los primeros
* NUM_PRIMOS números primos
*/
Multiconjunto vacio ();
11
Código de la función vacio():
/*
* Pre: ‐‐‐
* Post: Devuelve un multiconjunto vacío de los primeros
* NUM_PRIMOS números primos
*/
Multiconjunto vacio () {
Multiconjunto mc;
for (int i = 0; i < NUM_PRIMOS; ++i) {
mc.multiplicidad[i] = 0;
}
return mc;
}
12
La función incluir(A,p,m):
// para incorporar un número primo m‐veces a un
// multiconjunto
void incluir (Multiconjunto& A, const int p, const int m);
/*
* Pre: … su precondición …
* Post: … su postcondición …
*/
void incluir (Multiconjunto& A, const int p, const int m) {
… su código …
} 13
La función incluir(A,p,m):
// para incorporar un número primo m‐veces a un
// multiconjunto
void incluir (Multiconjunto& A, const int p, const int m);
/*
* Pre: p es uno de los NUM_PRIMOS primeros números
* primos y m>=1
* Post: Mantiene los elementos iniciales de A e
* incorpora m‐items del número primo p
*/
void incluir (Multiconjunto& A, const int p,
const int m);
14
Código de la función incluir(A,p,m):
/*
* Pre: p es uno de los NUM_PRIMOS primeros números
* primos y m>=1
* Post: Mantiene los elementos iniciales de A e
* incorpora m‐items del número primo p
*/
void incluir (Multiconjunto& A, const int p,
const int m) {
int i = buscar(p);
A.multiplicidad[i] = A.multiplicidad[i] + m;
}
15
Un primer diseño de la función auxiliar buscar(p):
/*
* Pre: p es uno de los NUM_PRIMOS primeros números primos
* Post: Devuelve el número de orden de p en la relación de
* números primos 2, 3, 5, 7, 11, 13, etc. contando a
* partir de 0 (el número de orden del 2 es el 0, el
* del 3 es el 1, el del 5 es el 2, el del 7 es el 3
* y así sucesivamente)
*/
int buscar (const int p) {
int i = 0;
while (PRIMOS[i]!=p && i < NUM_PRIMOS) { i = i + 1; }
return i;
}
16
Diseño más eficiente de la función auxiliar buscar(p):
/*
* Pre: p es uno de los NUM_PRIMOS primeros números primos
* Post: Devuelve el número de orden de p en la relación de números
* primos 2, 3, 5, 7, 11, 13, etc. contando a partir de 0
* (el número de orden del 2 es el 0, el del 3 es el 1, el
* del 5 es el 2, el del 7 es el 3 y así sucesivamente)
*/
int buscar (const int p) {
int inf = 0, sup = NUM_PRIMOS ‐ 1;
while (inf!=sup) {
int medio = (inf + sup) / 2;
if (PRIMOS[medio]<p) { inf = medio + 1; }
else { sup = medio; }
}
return inf;
}
17
La función incluir(A,p):
// para incorporar un número primo una vez a un
// multiconjunto
void incluir (Multiconjunto& A, const int p);
/*
* Pre: … su precondición …
* Post: … su postcondición …
*/
void incluir (Multiconjunto& A, const int p) {
… su código …
}
18
La función incluir(A,p):
// para incorporar un número primo una vez a un
// multiconjunto
void incluir (Multiconjunto& A, const int p);
/*
* Pre: p es uno de los NUM_PRIMOS primeros números primos
* Post: Mantiene los elementos iniciales de A e incorpora
* un item del número primo p
*/
void incluir (Multiconjunto& A, const int p);
19
Código de la función incluir(A,p):
/*
* Pre: p es uno de los NUM_PRIMOS primeros números primos
* Post: Mantiene los elementos iniciales de A e incorpora
* un item del número primo p
*/
void incluir (Multiconjunto& A, const int p) {
incluir(A,p,1);
}
20
La función retirar(A,p,m):
// para retirar m‐items de un número primo de un
// multiconjunto
void retirar (Multiconjunto& A, const int p,
const int m);
/*
* Pre: … su precondición …
* Post: … su postcondición …
*/
void retirar (Multiconjunto& A, const int p,
const int m) { … su código … } 21
La función retirar(A,p,m):
// para retirar m‐items de un número primo de un
// multiconjunto
void retirar (Multiconjunto& A, const int p,
const int m);
/*
* Pre: p es uno de los NUM_PRIMOS primeros números primos
* y m > 0
* Post: Retira de A m items del número primo p y mantiene
* los restantes elementos iniciales de A
*/
void retirar (Multiconjunto& A, const int p,
const int m); 22
Código de la función retirar(A,p,m):
/*
* Pre: p es uno de los NUM_PRIMOS primeros números primos
* y m > 0
* Post: Retira de A m items del número primo p y mantiene
* los restantes elementos iniciales de A
*/
void retirar (Multiconjunto& A, const int p,
const int m) {
int i = buscar(p);
if (A.multiplicidad[i] >= m) {
A.multiplicidad[i] = A.multiplicidad[i] ‐ m;
}
else { A.multiplicidad[i] = 0; }
}
23
La función eliminar(A,p):
// para retirar todos los items de un número primo de un
// multiconjunto
void eliminar (Multiconjunto& A, const int p);
/*
* Pre: … su precondición …
* Post: … su postcondición …
*/
void eliminar (Multiconjunto& A, const int p) {
… su código …
}
24
La función eliminar(A,p):
// para retirar todos los items de un número primo de un
// multiconjunto
void eliminar (Multiconjunto& A, const int p);
/*
* Pre: p es uno de los NUM_PRIMOS primeros números
* primos
* Post: Retira de A todos los items del número
* primo p y mantiene los restantes elementos
* iniciales de A
*/
void eliminar (Multiconjunto& A, const int p);
25
Código de la función eliminar(A,p):
/*
* Pre: p es uno de los NUM_PRIMOS primeros números
* primos
* Post: Retira de A todos los items del número
* primo p y mantiene los restantes elementos
* iniciales de A
*/
void eliminar (Multiconjunto& A, const int p) {
A.multiplicidad[buscar(p)] = 0;
}
26
La función multiplicidad(A,p):
// para saber la multiplicidad de un número primo en un
// multiconjunto
int multiplicidad (const Multiconjunto A, const int p);
/*
* Pre: … su precondición …
* Post: … su postcondición …
*/
int multiplicidad (const Multiconjunto A, const int p) {
… su código …
}
27
La función multiplicidad(A,p):
// para saber la multiplicidad de un número primo en un
// multiconjunto
int multiplicidad (const Multiconjunto A, const int p);
/*
* Pre: p es uno de los NUM_PRIMOS primeros números
* primos
* Post: Devuelve la multiplicidad de p en el multicon‐
* junto A
*/
int multiplicidad (const Multiconjunto A, const int p);
28
Código de la función multiplicidad(A,p):
/*
* Pre: p es uno de los NUM_PRIMOS primeros números
* primos
* Post: Devuelve la multiplicidad de p en el multicon‐
* junto A
*/
int multiplicidad (const Multiconjunto A, const int p) {
return A.multiplicidad[buscar(p)];
}
29
La función cardinalidad(A):
// para saber el número total de elementos de un
// multiconjunto
int cardinalidad (const Multiconjunto A);
/*
* Pre: … su precondición …
* Post: … su postcondición …
*/
int cardinalidad (const Multiconjunto A) { … su código … }
30
La función cardinalidad(A):
// para saber el número total de elementos de un
// multiconjunto
int cardinalidad (const Multiconjunto A);
/*
* Pre: ‐‐‐
* Post: Devuelve el número total de elementos del
* multiconjunto A, es decir, la suma de las
* multiplicidades de todos sus elementos
*/
int cardinalidad (const Multiconjunto A);
31
Código de la función cardinalidad(A):
/*
* Pre: ‐‐‐
* Post: Devuelve el número total de elementos del
* multiconjunto A, es decir, la suma de las
* multiplicidades de todos sus elementos
*/
int cardinalidad (const Multiconjunto A) {
int total = 0;
for (int i = 0; i < NUM_PRIMOS; ++i) {
total = total + A.multiplicidad[i];
}
return total;
}
32
La función numDiferentes(A):
// para saber el número total de elementos diferentes
// de un multiconjunto
int numDiferentes (const Multiconjunto A);
/*
* Pre: … su precondición …
* Post: … su postcondición …
*/
int numDiferentes (const Multiconjunto A) { … su código … }
33
La función numDiferentes(A):
// para saber el número total de elementos diferentes
// de un multiconjunto
int numDiferentes (const Multiconjunto A);
/*
* Pre: ‐‐‐
* Post: Devuelve el número de elementos diferentes de
* multiconjunto A
*/
int numDiferentes (const Multiconjunto A);
34
Código de la función numDiferentes(A):
/*
* Pre: ‐‐‐
* Post: Devuelve el número de elementos diferentes de
* multiconjunto A
*/
int numDiferentes (const Multiconjunto A) {
int total = 0;
for (int i = 0; i < NUM_PRIMOS; ++i) {
if (A.multiplicidad[i]>0) { total = total + 1; }
}
return total;
}
35
La función mostrar(A):
// para presentar por pantalla el contenido de un
// multiconjunto
int mostrar (const Multiconjunto A);
/*
* Pre: … su precondición …
* Post: … su postcondición …
*/
int mostrar (const Multiconjunto A) { … su código … }
36
La función mostrar(A):
// para presentar por pantalla el contenido de un
// multiconjunto
int mostrar (const Multiconjunto A);
/*
* Pre: ‐‐
* Post: Presenta por pantalla, en una línea, los
* elementos de A
*/
void mostrar (const Multiconjunto A)
37
Código de la función mostrar(A):
/*
* Pre: ‐‐
* Post: Presenta por pantalla, en una línea, los elementos de A
*/
void mostrar (const Multiconjunto A) {
int cuenta = 0;
for (int i = 0; i < NUM_PRIMOS; ++i) {
if (A.multiplicidad[i]>0) {
cuenta = cuenta + 1;
if (cuenta==1) {
if (A.multiplicidad[i]==1) { cout << "{ " << PRIMOS[i]; }
else { cout << "{ " << PRIMOS[i] << "(" << A.multiplicidad[i] << ")"; }
}
else {
if (A.multiplicidad[i]==1) { cout << ", " << PRIMOS[i]; }
else { cout << ", " << PRIMOS[i] << "(" << A.multiplicidad[i] << ")"; }
}
}
}
if (cuenta==0) { cout << "{}" << endl; }
else { cout << " }" << endl; }
}
38
La función opUnion(A,B):
// para calcular la unión de dos multiconjuntos
Multiconjunto opUnion (const Multiconjunto A,
const Multiconjunto B);
/*
* Pre: … su precondición …
* Post: … su postcondición …
*/
Multiconjunto opUnion (const Multiconjunto A,
const Multiconjunto B) { … su código … }
39
La función opUnion(A,B):
// para calcular la unión de dos multiconjuntos
Multiconjunto opUnion (const Multiconjunto A,
const Multiconjunto B);
/*
* Pre: ‐‐‐
* Post: Devuelve la unión de los multiconjuntos A y B
*/
Multiconjunto opUnion (const Multiconjunto A,
const Multiconjunto B);
40
Código de la función opUnion(A,B):
/*
* Pre: ‐‐‐
* Post: Devuelve la unión de los multiconjuntos A y B
*/
Multiconjunto opUnion (const Multiconjunto A,
const Multiconjunto B) {
Multiconjunto mc;
for (int i = 0; i < NUM_PRIMOS; ++i) {
mc.multiplicidad[i] = A.multiplicidad[i]
+ B.multiplicidad[i];
}
return mc;
}
41
La función opInterseccion(A,B):
// para calcular la intersección de dos multiconjuntos
Multiconjunto opInterseccion (const Multiconjunto A,
const Multiconjunto B);
/*
* Pre: … su precondición …
* Post: … su postcondición …
*/
Multiconjunto opInterseccion (const Multiconjunto A,
const Multiconjunto B) { … su código … }
42
La función opInterseccion(A,B):
// para crear una cola sin ningún ciudadano
ColaC nuevaColaC();
/*
* Pre: ‐‐‐
* Post: Devuelve la intersección de los multiconjun‐
* tos A y B
*/
Multiconjunto opInterseccion (const Multiconjunto A,
const Multiconjunto B);
43
Código de la función opInterseccion(A,B):
/*
* Pre: ‐‐‐
* Post: Devuelve la intersección de los multiconjuntos A y B
*/
Multiconjunto opInterseccion (const Multiconjunto A,
const Multiconjunto B) {
Multiconjunto mc;
for (int i = 0; i < NUM_PRIMOS; ++i) {
if (A.multiplicidad[i]<=B.multiplicidad[i]) {
mc.multiplicidad[i] = A.multiplicidad[i];
}
else { mc.multiplicidad[i] = B.multiplicidad[i]; }
}
return mc;
}
44
La función opDiferencia(A,B):
// para calcular la diferencia de dos multiconjuntos
Multiconjunto opDiferencia (const Multiconjunto A,
const Multiconjunto B);
/*
* Pre: … su precondición …
* Post: … su postcondición …
*/
Multiconjunto opDiferencia (const Multiconjunto A,
const Multiconjunto B) { … su código … }
45
La función opDiferencia(A,B):
// para calcular la diferencia de dos multiconjuntos
Multiconjunto opDiferencia (const Multiconjunto A,
const Multiconjunto B);
Especificación de la opDiferencia(A,B):
/*
* Pre: ‐‐‐
* Post: Devuelve la diferencia de los multiconjuntos A y B
*/
Multiconjunto opDiferencia (const Multiconjunto A,
const Multiconjunto B);
46
Código de la función opDiferencia(A,B):
/*
* Pre: ‐‐‐
* Post: Devuelve la diferencia de los multiconjuntos A y B
*/
Multiconjunto opDiferencia (const Multiconjunto A,
const Multiconjunto B) {
Multiconjunto mc;
for (int i = 0; i < NUM_PRIMOS; ++i) {
if (A.multiplicidad[i]>B.multiplicidad[i]) {
mc.multiplicidad[i] = A.multiplicidad[i]
‐ B.multiplicidad[i];
}
else { mc.multiplicidad[i] = 0; }
}
return mc;
} 47
La función guardar(nombreFichero,T,n):
// para almacenar la información de una colección de
// multiconjuntos en un fichero binario
void guardar (const char nombreFichero[],
const Multiconjunto T[], const int n);
/*
* Pre: … su precondición …
* Post: … su postcondición …
*/
void guardar (const char nombreFichero[],
const Multiconjunto T[], const int n) { … su código … }
48
La función guardar(nombreFichero,T,n):
// para almacenar la información de una colección de
// multiconjuntos en un fichero binario
void guardar (const char nombreFichero[],
const Multiconjunto T[], const int n);
/*
* Pre:
* Post: Crea un fichero de nombre nombreFichero y escribe
* en él la secuencia de datos binarios de tipo Multi‐
* conjunto almacenada en T[0,n‐1]
*/
void guardar (const char nombreFichero[],
const Multiconjunto T[], const int n);
49
Código de la función guardar(nombreFichero,T,n):
/*
* Pre:
* Post: Crea un fichero de nombre nombreFichero y escribe en él la
* secuencia de datos binarios de tipo Multiconjunto almacenada
* en T[0,n‐1]
*/
void guardar (const char nombreFichero[], const Multiconjunto T[],
const int n) {
ofstream f;
f.open(nombreFichero, ios::binary);
for (int i = 0; i < n; ++i) {
/* Escribe el multiconjunto T[i] en el fichero */
f.write(reinterpret_cast<char *>(&T[i]), sizeof(Multiconjunto));
}
f.close(); // Libera el fichero y lo disocia del flujo
}
50
La función recuperar(nombreFichero,T,n):
// para recuperar la información de una colección de
// multiconjuntos almacenada en un fichero binario
bool recuperar (const char nombreFichero[],
Multiconjunto T[], int& n);
/*
* Pre: … su precondición …
* Post: … su postcondición …
*/
bool recuperar (const char nombreFichero[],
Multiconjunto T[], int& n) { … su código … }
51
Especificación de recuperar(nombreFichero,T,n):
/*
* Pre: nombreFichero es el nombre de un fichero que almacena
* una secuencia de datos binarios de tipo Multiconjunto
* Post: Devuelve false si no es posible leer la información
* del fichero nombreFichero. Si es posible, asigna a n
* el número de conjuntos que almacena el fichero,
* asigna a los elementos T[0,n‐1] los n de datos de
* tipo Multiconjunto almacenados en el fichero y
* devuelve true.
*/
bool recuperar (char nombreFichero[],
Multiconjunto T[], int& n);
52
Código de la función recuperar(nombreFichero,T,n):
/*
* Pre: nombreFichero es el nombre de un fichero que almacena …
* Post: Devuelve false si no es posible leer la información …
*/
bool recuperar (const char nombreFichero[],
Multiconjunto T[], int& n) {
ifstream f;
n = 0;
f.open(nombreFichero, ios::binary);
if (f.is_open()) {
while (!f.eof()) {
f.read(reinterpret_cast<char *>(&T[n]), sizeof(Multiconjunto));
if (!f.eof()) { n = n + 1 ; }
}
f.close(); return true;
}
else { return false; }
}
53
54