PDA

Visualizza la versione completa : C++ struttura dati insieme con vettore booleano


pietrol83
18-03-2012, 10:48
ciao a tutti,
ho creato una struttura dai insieme con un vettore booleano e a me sembra essere fatto bene. ho notato che quando testo i metodi ottengo dei risulatati non attesi. sto cercando di capire dove sia il problema ma non ne vengo a capo. io penso sia il compilatore che mi ha voltato le spalle. potete dare voi un'occhiata e dirmi dov' il problema (qualora ce ne fosse uno)?
posto i codici:

insiemev.h


#ifndef insiemev_h
#define insiemev_h

#include "insieme.h"
#include<iostream>
#include<stdlib.h>

using namespace std;

template<class tipoelem>
class insiemev : public insieme<tipoelem>
{
public:
insiemev(int);

int card;

void creainsieme();
bool insiemevuoto();
bool appartiene(tipoelem);
void inserisci(tipoelem);
void cancella(tipoelem);
void unione(insiemev<tipoelem> &, insiemev<tipoelem> &);
void intersezione(insiemev<tipoelem> &, insiemev<tipoelem> &);
void differenza(insiemev<tipoelem> &, insiemev<tipoelem> &);

void visualizzains();
private:
bool *set;
int dimset;
};

#endif

template<class tipoelem>
void insiemev<tipoelem>::visualizzains()
{
for(int i = 0; i < dimset; i++)
{
if(this->appartiene(i))
{
cout << i << " ";
}
}
cout << "\n\n";
}

template<class tipoelem>
insiemev<tipoelem>::insiemev(int dim)
{
dimset = dim;
this->creainsieme();
}

template<class tipoelem>
void insiemev<tipoelem>::creainsieme()
{
set = new bool[dimset];
for(int i = 0; i < dimset; i++)
set[i] = false;
card = 0;
}

template<class tipoelem>
bool insiemev<tipoelem>::insiemevuoto()
{
return(card == 0);
}

template<class tipoelem>
bool insiemev<tipoelem>::appartiene(tipoelem elem)
{
return(set[elem]);
}

template<class tipoelem>
void insiemev<tipoelem>::inserisci(tipoelem elem)
{
if(!this->appartiene(elem))
{
set[elem] = true;
++card;
}
}

template<class tipoelem>
void insiemev<tipoelem>::cancella(tipoelem elem)
{
if(set[elem])
{
set[elem] = false;
card--;
}
}

template<class tipoelem>
void insiemev<tipoelem>::unione(insiemev<tipoelem> &A, insiemev<tipoelem> &B)
{
for(int i = 0; i < dimset; i++)
{
if(A.appartiene(i) || B.appartiene(i))
this->inserisci(i);
}
}

template<class tipoelem>
void insiemev<tipoelem>::intersezione(insiemev<tipoelem> &A, insiemev<tipoelem> &B)
{
for(int i = 0; i < card; i++)
{
if(A.appartiene(i) && B.appartiene(i))
this->inserisci(i);
}
}

template<class tipoelem>
void insiemev<tipoelem>::differenza(insiemev<tipoelem> &A, insiemev<tipoelem> &B)
{
for(int i = 0; i < card; i++)
{
if(A.appartiene(i) && !B.appartiene(i))
this->inserisci(i);
}
}

testinsieme.cpp


#include "insiemev.h"
#include<iostream>
#include<stdlib.h>

using namespace std;

int main()
{
cout << " ***test insieme con vettore***\n\n";
int dim = 10;
insiemev<int> ins(dim);
ins.inserisci(1);
ins.inserisci(2);
ins.visualizzains();
int dim2 = 5;
insiemev<int> ins2(dim2);
ins2.inserisci(4);
ins2.inserisci(2);
ins2.visualizzains();
int card3 = dim + dim2;
insiemev<int> ins3(card3);
ins3.unione(ins, ins2);
ins3.visualizzains();

system("pause");
return 0;
}

il problema : quando testo il metodo unione dovrei ottenere come risultato l'insieme conelementi {1, 2, 4} mentre mi viene visualizzato {1, 2, 4, 6, 8, 9, 10, 11, 12, 13, 14}

cosa ho fatto di sbagliato? vi prego aiutatemi.

oregon
18-03-2012, 10:53
E insieme.h ?

pietrol83
18-03-2012, 11:42
va bhe insieme.h contiene i metodi virtuali (che sono implementati in insiemev.h) e un metodo che non fa altro che chiamare i metodi per testarli.

oregon
18-03-2012, 11:43
Ti dispiace mostrarlo?

pietrol83
18-03-2012, 12:36
insieme.h


#ifndef insieme_h
#define insieme_h

#include<iostream>
#include<stdlib.h>

using namespace std;

template<class tipoelem>
class insieme
{
public:
virtual void creainsieme() = 0;
virtual bool insiemevuoto() = 0;
virtual bool appartiene(tipoelem) = 0;
virtual void inserisci(tipoelem) = 0;
virtual void cancella(tipoelem) = 0;
//virtual void unione(insieme<tipoelem> *, insieme<tipoelem> *) = 0;
//virtual void intersezione(insieme<tipoelem> *, insieme<tipoelem> *) = 0;
//virtual void differenza(insieme<tipoelem> *, insieme<tipoelem> *) = 0;

void test();
};

#endif

template<class tipoelem>
void insieme<tipoelem>::test()
{
cout << " ***test del metodo CREAINSIEME***\n\n";
cout << "il metodo CREAINSIEME crea un insieme privo di elementi. per provare il metodo\n";
cout << "basta utilizzare il metodo INSIEMEVUOTO.\n\n";
cout << " insiemevuoto() = " << this->insiemevuoto() << "\n\n";
system("pause");
system("cls");

cout << " ***test del metodo INSIEMEVUOTO***\n\n";
cout << "il metodo INSIEMEVUOTO testa se l'insieme e' privo o meno di elementi.\n\n";
cout << " test del metodo su insieme privo di elementi:\n";
cout << " insiemevuoto() = " << this->insiemevuoto() << "\n";
cout << " test del metodo su insieme con almeno un elemento:\n";
cout << " inserimento di un valore nell'insieme: a = ";
tipoelem a;
cin >> a;
this->inserisci(a);
cout << " insiemevuoto() = " << this->insiemevuoto() << "\n\n";
system("pause");
system("cls");

cout << " ***test del metodo APPARTIENE***\n\n";
cout << "il metodo APPARTIENE testa se il valore fornito come argomento e' presente\n";
cout << "o meno tra i valori dell'insieme.\n\n";
cout << " test con esito positivo:\n";
cout << " appartiene(a) = " << this->appartiene(a) << "\n";
cout << " test con esito negativo:\n";
cout << " b = ";
tipoelem b;
cin >> b;
cout << " appartiene(b) = " << this->appartiene(b) << "\n\n";
system("pause");
system("cls");

cout << "i metodi UNIONE, INTERSEZIONE e DIFFERENZA non vengono testati in quanto\n";
cout << "essendo questa una class virtuale, non possibile instanziare oggetti\n";
cout << "insieme, ma bisognerebbe fornire i puntatori a insieme da un main.\n\n";
system("pause");
}


questa la classe base (virtuale)

oregon
18-03-2012, 12:50
Ma in

unione

nel for

for(int i = 0; i < dimset; i++)

tu controlli degli elementi che non esistono in A e/o B ...

dimset infatti maggiore della dimensione massima dei due insiemi e quindi sfori i rispettivi vettori

ramy89
18-03-2012, 12:54
Non controlli se si esce o no dai limiti dell' array di booleani:


template<class tipoelem>
void insiemev<tipoelem>::unione(insiemev<tipoelem> &A, insiemev<tipoelem> &B)
{
int max=A.dimset;
if(max<B.dimset)
max=B.dimset;
for(int i = 0; i < max; i++)
{
if(i<A.dimset)
if(A.appartiene(i))
this->inserisci(i);
if(i<B.dimset)
if(B.appartiene(i))
this->inserisci(i);
}
}

E non ti ha dato segmentation fault per caso.Per cui se l' array di booleani di B era composto da 5 campi, ha letto anche quelli oltre.E per caso ce ne erano alcuni che sono stati letti come veri.
Ma potevi semplicemente risolvere con un:


template<class tipoelem>
bool insiemev<tipoelem>::appartiene(tipoelem elem)
{
bool result=elem<dimset;
if(result)
result=set[elem];
return result;
}


Per c' da dire che al posto del metodo unione avresti potuto implementare l' operatore | , e che avendo realizzato questa classe con i template, ti da errore se tipoelem=string, visto che un valore come "ciao" non un indice valido dell' array set.

oregon
18-03-2012, 13:00
Aggiungo che, al di l del problema specifico, mi accorgo che non fai quasi mai un po' di degugging ...

Se solo avessi eseguito il codice linea per linea, avresti scoperto subito il problema (a parte che avresti dovuto evitarlo in sede di progettazione).

Insomma, quello che devi imparare a fare un po' di debugging delle tue applicazioni.
Perch scrivere del codice (sbagliato) semplice ... correggerlo molto pi difficile (e non bisogna sempre e comunque affidarsi ad un forum ...)

pietrol83
18-03-2012, 13:24
[QUOTE]Originariamente inviato da ramy89


int max=A.dimset;
if(max<B.dimset)
max=B.dimset;

se faccio in questo modo comunque sforo uno dei due array in quanto di dimensione minore rispetto all'altro.
inoltre ho provato a fare come dici tu ma il risultato non quello atteso.
ho fatto una modifica ed ho ottenuto il risultato atteso. in pratica ho fatto due cicli, uno per A e uno per B:

max = A.dimset;
for(int i = 0; i < max; i++)
{
if(A.appartiene(i))
this->inserisci(i);
}

e allo stesso modo per B

pietrol83
18-03-2012, 13:26
Originariamente inviato da oregon
Aggiungo che, al di l del problema specifico, mi accorgo che non fai quasi mai un po' di degugging ...

Se solo avessi eseguito il codice linea per linea, avresti scoperto subito il problema (a parte che avresti dovuto evitarlo in sede di progettazione).

Insomma, quello che devi imparare a fare un po' di debugging delle tue applicazioni.
Perch scrivere del codice (sbagliato) semplice ... correggerlo molto pi difficile (e non bisogna sempre e comunque affidarsi ad un forum ...)

oregon hai perfettamente ragione, io non che non faccio quasi mai il debugging; non lo faccio proprio, perch avendo fatto tutto da solo senza seguire un corso o avendo qualcuno che mi insegnasse le cose, non ho nemmeno preso in considerazione il fatto del debugging.

Loading