PDA

Visualizza versione completa : [C++]funzionamento costruttori di copia


leuconoe
24-08-2009, 02.11.06
Salve a tutti.
Sono nuova sia su questo forum che nel campo della programmazione :)
Volevo riportare qui di seguito una parte del progetto che sto compilando per l'università e chiedere qualche chiarimento che non è mai arrivato da parte del docente.


#include<iostream>
#include<cstdlib>
#include<cstring>
using namespace std;

class indirizzo {

char via[30];
char numcivico[10];
int cap;
char citta[30];

public:

indirizzo();
~indirizzo();

void put_via(char *s) {strcpy(via,s);}
void get_via() {cout<<via<<'\n';}
void put_numcivico (char *p) {strcpy(numcivico,p);}
void get_numcivico() {cout<<numcivico<<'\n';}
void put_cap(int n) {cap=n;}
void get_cap() {cout<<cap<<'\n';}
void put_citta(char *q) {strcpy(citta,q);}
void get_citta() {cout<<citta<<'\n';}
};

class CasaEditrice:public indirizzo {

char *nome;
char *numtel;
char *numfax;
char *piva;
char *id;


public:
friend ostream &operator<<(ostream &stream, CasaEditrice &CasaEdi);
friend istream &operator>>(istream &stream, CasaEditrice &CasaEdi);

CasaEditrice(int p);
CasaEditrice::CasaEditrice(const CasaEditrice &casaed);
~CasaEditrice();

void put_nome(char *n) {nome=new char[strlen(n)+1]; strcpy(nome,n);}
void get_nome() {cout<<nome<<'\n';}
void put_numtel(char *n1) {numtel= new char[strlen(n1) +1]; strcpy(numtel,n1);}
void get_numtel() {cout<<numtel<<'\n';}
void put_numfax (char *n2) { numfax= new char[strlen(n2)+1];strcpy(numfax,n2);}
void get_numfax() {cout<<numfax<<'\n';}
void put_piva(char *n3) {piva= new char[strlen(n3) +1];strcpy(piva,n3);}
void get_piva() {cout<<piva<<'\n';}
void put_id(char *n4) {id= new char[strlen(n4) +1];strcpy(piva,n4);}
void get_iva() {cout<<piva<<'\n';}
};



indirizzo::indirizzo()
{
via[30]='\0';
numcivico[10]='\0';
cap=0;
citta[30]='\0';


}

indirizzo::~indirizzo()
{ if(via) delete[] via;
if(numcivico) delete [] numcivico;

if(citta) delete[] citta;
}


CasaEditrice::CasaEditrice(int p)
{
nome=new char[p];
numtel= new char[p];
numfax= new char[p];
piva= new char[p];
id= new char[p];
if((!nome)&&(!numtel)&&(!numfax)&&(!piva)&&(!id))
{
cout<<"impossibile allocare";
exit(1);
}

*numtel=p;
*numfax=p;
*piva=p;
*id=p;
}

CasaEditrice::CasaEditrice(const CasaEditrice &casaed)
{ nome=new char;
numtel= new char;
numfax= new char;
piva= new char;
id= new char;
if((!nome)&&(!numtel)&&(!numfax)&&(!piva)&&(!id))
{
cout<<"impossibile allocare";
exit(1);
}
*nome=*casaed.nome;
*numtel=*casaed.numtel;
*numfax=*casaed.numfax;
*piva=*casaed.piva;
*id=*casaed.id;
}



CasaEditrice::~CasaEditrice()
{
if(nome) delete[] nome;
if(numtel) delete[] numtel;
if(numfax) delete[] numfax;
if(piva) delete[] piva;
if (id) delete[] id;
}



ostream &operator<<(ostream &stream, CasaEditrice &CasaEdi )
{
stream << CasaEdi.nome << ". ";
stream << CasaEdi.numtel << ". ";
stream << CasaEdi.numfax << ". ";
stream << CasaEdi.piva << ". ";
stream << CasaEdi.id << "\n";
return stream;
}


istream &operator>>(istream &stream, CasaEditrice &CasaEdi )
{
cout << "Inserire il nome: "; stream >> CasaEdi.nome;
cout << "Inserire num. di tel: "; stream >> CasaEdi.numtel;
cout << "Inserire num. di fax: "; stream >> CasaEdi.numfax;
cout << "Inserire p.iva: "; stream >> CasaEdi.piva;
cout << "Inserire id: "; stream >> CasaEdi.id;
return stream;
}

int main()
{

CasaEditrice bitti(45) ;
cin>>bitti;
cout<<Array;


bitti.put_via("via alfieri 18");
bitti.get_via();


system ("PAUSE");
return 0 ;

}



il programma funziona, ma non capisco se ho implementato correttamente il costruttore e il costruttore di copia.
poi, dal manuale, ho appreso che la deallocazione di un array statico non ha bisogno di istruzioni, quindi mi chiedevo se fosse corretto eliminare il distruttore per la classe indirizzo che utilizza l'istruzione delete[] per array di dimensione predefinita.
Vi sarei molto grati se mi chiarisse qualcosa soprattutto sui costruttori per array dinamici.
Scusate per la poca chiarezza del codice, ma, come ho già detto, la programmazione è cosa nuovissima per me.
Grazie a tutti :)

LoryOne
24-08-2009, 19.32.41
Sei sicura che il costruttore di copia non faccia riferimento attraverso l'utilizzo di puntatore ad un array statico che viene riallocato con l'operatore new per aumentarne dinamicamente le dimensioni in base all'input dell'utente ?

Se è così, è più che giusto a parer mio l'utilizzo di delete [] nel destructor per lberare la memoria allocata nel constructor dalla classe che eredita indirizzo

ps: interessante l'utilizzo degli streams per effettuare gli input (Y)

ArrigoC
24-08-2009, 20.05.11
Si, anche io ho dei problemi sullo stesso ( l'ho preso dal prof dell'uni ) però sono molto più indietro di te

Qualcuno potrebbe darmi una mano? Mi imbroglio di brutto

LoryOne
24-08-2009, 23.04.19
T'imbrogli perchè non hai le idee chiare o perchè il prof è un confusionario: Magari butta giu codice in maniera meccanica ... Eleganza ed efficenza di C++ sono fondamentali.
Impara gradualmente, scrivi codice semplice e compilalo.
Impara le regole del linguaggio ed attieniti ad esse scrupolosamente ... i virtuosismi lasciali ai boriosi; certe finezze le imparerai col tempo.

ArrigoC
25-08-2009, 11.41.07
Va bene, grazie mille :)
Se per te va bene dare un'occhiata ogni tanto, butto giù il codice di volta in volta e lo incollo nel forum va bene?

LoryOne
25-08-2009, 13.00.32
Per me va benissimo, ho pure 4 occhi :D
Scherzi a parte, qui troverai tanti utenti con grande esperienza dai quali potrai attingere informazioni e risposte ai tuoi quesiti. :)

leuconoe
25-08-2009, 13.22.39
Grazie mille per la disponibilità LaryOne! :)
ora mi sono accorta che nel main passando un argomento alla funzione bitti.put_indirizzo definendo un puntatore e non passando direttamente la stringa, si blocca l'esecuzione del programma anche se il compilatore compila il codice.
Mah scopro sempre più errori.
Questa è la mmodifica apportata:
int main()
{
CasaEditrice bitti(30);
cin>>bitti;
cout<<bitti;
char *s;
cout<<"inserire via";
gets(s);
bitti.put_via(s);
bitti.get_via();
system ("PAUSE");
return 0 ;
}

LoryOne
25-08-2009, 23.34.18
Un po di ripasso
Codice semplice per i semplici concetti fondamentali...


class MyClass {
/* val e copynumber sono due variabili private all'interno della classe.
Infatti precedono publlc:
Per accedere ai valori dall'esterno è necessario dichiarare una funzione
pubblica che ritorni il valore della variabile
*/
int val;
int copynumber;
public:
/* Costruttore definito direttamente all'interno della classe.
E' possibile anche la seguente forma:
MyClass::MyClass(int i){
...
...
}
Deve essere definita all'esterno della classe, poichè :: indica
appartenenza a.
Il costruttore di MyClass appartiene alla classe MyClass, ma lo stesso
dicasi per le eventuali funzioni i cui soli prototipi sono all'interno
della classe, così come per il distruttore
*/
MyClass(int i) {
val = i;
copynumber = 0;
cout << "Siamo all'interno del normale costruttore\n";
}

/* Costruttore di copia
Viene definito &o come indirizzo della copia della classe MyClass.
Tutte le variabili private del costruttore originario sono accesibili
alla copia. val è pari ad i, e copynumber è incrementato di 1
*/
MyClass(const MyClass &o) {
val = o.val;
copynumber = o.copynumber + 1;
cout << "Siamo all'interno del costruttore di copia.\n";
cout << "val e' pari a " << o.val << "\n";
}

/* Distruttore della classe originaria o del costruttore di copia
Due sono le classi: L'originale e la sua copia, quindi 2 volte sarà
eseguito il distruttore, ma solo la prima volta copynumber sarà = 0
*/
~MyClass() {
if(copynumber == 0)
cout << "Distruttore della classe principale.\n";
else
cout << "Distruttore del costruttore di copia\n";
}

// funzione pubblica che ritorna il valore della variabile privata val
int getval() { return val; }
};

/* Funzione al di fuori della classe che necessita come parametro la classe
stessa, in modo da accedere alla funzione pubblica della classe che mostra
il valore della variabile privata val
*/
void display(MyClass ob) {
cout << "Ormai in display val e' pari a " << ob.getval() << '\n';
}

int main() {
MyClass a(10);
display(a);
return 0;
}


Funzioni friend (amiche della classe)


class MyClass {
// a e b sono due varibili private all'interno della classe
int a, b;
public:
MyClass(int i, int j) { a=i; b=j; }
friend int comDenom(MyClass x); // La funzione friend
};

/* comDenom() non fa parte di nessun membro della classe, ma il suo
prototipo è stato creato all'interno della classe per identificare un
legame con essa.
*/
int comDenom(MyClass x) {
/* Poichè comDenom() è una funzione friend di MyClass, può accedere
direttamente alle variabili private all'interno della classe.
Se x.a è < di x.b, allora max = x.a, altrimenti max = x.b
*/
int max = x.a < x.b ? x.a : x.b;

for(int i=2; i <= max; i++)
if((x.a%i)==0 && (x.b%i)==0) return i;

return 0;
}

int main() {
MyClass n(18, 111);

if(comDenom(n))
cout << "Il comune denominatore e' " <<
comDenom(n) << "\n";
else
cout << "Nessun comune denominatore.\n";

return 0;
}


Prossimo passo: Classi che ereditano membri di altre classi e possibile violazione di accesso ...
Io ora vado a letto perchè ho una certa età neh :D e domani si va a lavurà

LoryOne
27-08-2009, 13.52.57
Classi che ereditano membri di altre classi e possibile violazione di accesso ...



class B {
// protected:
int i, j; // i e j sono due variabili private all'interno di B
public:
void set(int a, int b) { i = a; j = b; }
void show() { cout << i << " " << j << "\n"; }
};

class D : public B { // La classe D eredita le funzioni pubbliche da B
int k;
public:
D(int x) { k = x; }
void showk() { cout << k << "\n"; }
/* Violazione di accesso !!!
i è stata dichiarata privata all'interno di B.
Per ovviare al problema, si dichiara i protected
*/
// i = 10;
};

int main() {
D ob(3);

ob.set(1, 2);
ob.show();

ob.showk();

return 0;
}

LoryOne
27-08-2009, 21.53.34
Operatore new e memoria dinamica


main(void){
/* stringa è un array di 6 caratteri.
Il sesto carattere è il temrinatore di sequenza, altrimenti noto
come terminatore nullo.
*/
char stringa[]={'1','2','3','4','5','\0'};
/* *p è un puntatore a char e ch è un array statico di 6 elementi.
Di ch si conoscono in via preventiva tipologia e dimensione immutabili.
*p è un puntatore e di lui si conosce solo la tipologia del dato al
quale esso fa riferimento. La locazione in memoria è invece dinamica.
*/
char *p, ch[6];

// Si copia in ch la sequenza di caratteri di cui si compone stringa
strcpy(ch,stringa);
cout << ch << "\n"; // Il risultato è la stampa da 1 a 5 escluso '\0' non stampabile

/* Attraverso l'operatore new, al puntatore p si assegna la locazione in memoria
dinamica di una sequenza di caratteri pari ad 8.
*/
p = new char[8]; // il primo carattere ha posizione pari a 0 nell'array, l'ultimo 7.
/* Alla locazione in memoria ora definita da p si copia la sequenza ottenuta da ch.
ch riempie la memoria dinamica fino al sesto carattere, ma gli ulteriori 2
restano disponibili perchè comunque allocati.
*/
strcpy(p,ch);
for(int i=0;i<8;i++) cout << "posizione " << i
<< " carattere " << p[i] << "\n";
cout << "\n";

/* A questo punto posso decidere quale valore assegnare ai caratteri dell'array
al quale punta *p a cominciare dall'ultimo carattere copiato da strcpy.
*/
p[5]='*';
p[6]='*';
p[7]='*';

for(int i=0;i<8;i++) cout << "posizione " << i
<< " carattere " << p[i] << "\n";

// Libera la memoria dinamica allocata dal puntatore *p ad array di char
delete [] p;
}

ArrigoC
28-08-2009, 13.56.52
Ciao, scusate se non ho risposto ma non sono molto ferrato e stavo facendo delle prove.
Ora mi trovo nei guai a causa di un intero... mi spiego meglio:


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std;

typedef struct VolumeConQuantitaEDisposizione
{
string nomevol;
int quantitadisponibile;
string collocazione;
};

int main()
{
VolumeConQuantitaEDisposizione a[5];
string title;
string coll;
int *quant;
for (int i = 0; i < 5; i++)
{
a[i].nomevol='\0';
a[i].quantitadisponibile='\0';
a[i].collocazione='\0';
cout << i+1 <<": " << a[i].nomevol << " << >> " << a[i].quantitadisponibile << " << >> " << a[i].collocazione<<endl;
}

for (int i = 0; i < 5; i++)
{
cout << i+1 <<"° titolo: ";
getline(cin,title);
a[i].nomevol = title;
cout << "Collocazioine: ";
getline(cin,coll);
a[i].collocazione = coll;
cout << "Quantita': ";
cin >> *quant;
a[i].quantitadisponibile = *quant;
}


system("PAUSE");
return 0;
}



Ho provato la struct volumeccecc facendo un array di dimensione 5, inizializzando il tutto e poi inserendoci dei dati.
L'inizializzazione funziona, ma quando inserisco i dati, dopo l'intero il getline lo salta... come mai?? pensavo di risolvere mettendoci un getline fasullo... che ne dite?

Semi.genius
28-08-2009, 14.18.11
Ciao, scusate se non ho risposto ma non sono molto ferrato e stavo facendo delle prove.
Ora mi trovo nei guai a causa di un intero... mi spiego meglio:


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std;

typedef struct VolumeConQuantitaEDisposizione
{
string nomevol;
int quantitadisponibile;
string collocazione;
};

int main()
{
VolumeConQuantitaEDisposizione a[5];
string title;
string coll;
int *quant;
for (int i = 0; i < 5; i++)
{
a[i].nomevol='\0';
a[i].quantitadisponibile='\0';
a[i].collocazione='\0';
cout << i+1 <<": " << a[i].nomevol << " << >> " << a[i].quantitadisponibile << " << >> " << a[i].collocazione<<endl;
}

for (int i = 0; i < 5; i++)
{
cout << i+1 <<"° titolo: ";
getline(cin,title);
a[i].nomevol = title;
cout << "Collocazioine: ";
getline(cin,coll);
a[i].collocazione = coll;
cout << "Quantita': ";
cin >> *quant;
a[i].quantitadisponibile = *quant;
}


system("PAUSE");
return 0;
}



Ho provato la struct volumeccecc facendo un array di dimensione 5, inizializzando il tutto e poi inserendoci dei dati.
L'inizializzazione funziona, ma quando inserisco i dati, dopo l'intero il getline lo salta... come mai?? pensavo di risolvere mettendoci un getline fasullo... che ne dite?

Ti rispondo io...

1. Dovresti evitare di fare così a[i].quantitadisponibile='\0'; anche se è numericamente corretto (e funziona), non è altrettanto semanticamente siccome '\0' è da interpretarsi come un carattere non un intero. perciò è meglio (anche per chi legge il codice fare) a[i].quantitadisponibile=0
2. Per il problema della getline è semplice. Dipende dal sistema operativo su cui lo stai facendo girare. Per inviare i dati premi Invio, no? In Linux, invio è interpretato '\n', Mac OS X usa '\r' e Windows usa "\r\n". Questo cosa significa? Una volta fatta la prima getline, la funzione esce perchè ha incontrato '\r', ma nel buffer rimane l'altro terminatore che è '\n'. Perciò devi svuotarlo. O fai la getline a vuoto o più elegantemente, usa fflush(stdin) appena dopo ogni getline che svuota il buffer.

ArrigoC
28-08-2009, 18.13.11
Grazie mille ^_^ , allora metto '\0' per le stringhe ed 0 per gli interi. Ora invece fa una cosa alquanto strana ( tanto per cambiare diciamo ).

void Biblioteca::Aggiungi_volume(int quant,string titolo,string coll,int Q)
{
int i;
int j;
bool t=false;

i=TrovaVolumeDaNome(titolo,Q);

if ( i = -1 )
{
for (j=0;j<Q && !t;j++)
{
if ( a[j].nomevol == '\0') // l'errore lo da qui
{
a[j].nomevol = titolo;
a[j].quantitadisponibile=quant;
a[j].collocazione = coll;
t=true;
}
}

if (j==Q)
cout<<"biblioteca piena.\n";

}
else
a[i].quantitadisponibile=(a[i].quantitadisponibile)+quant;
}


la funzione serve per cercare attraverso trovanomedatitolo il titolo all'interno della libreria, se esiste già semplicemente aggiorna la quantità, altrimenti inserisce il nuovo libro.
L'errore che mi dà è il seguente:
no match for 'operator==' in '(((Biblioteca*)this)->Biblioteca::a + (+(((unsigned int)j) * 12u)))->VolumeConQuantitaEDisposizione::nomevol == '\000''.

E lo trovo strano perchè il simbolo == l'ho usato in un'altra funzione e non mi dà problemi ... ecco il codice della funzione:


int Biblioteca::TrovaVolumeDaNome (string titolo,int Q)
{
for (int i=0;i<Q;i++)
if (a[i].nomevol == titolo)
return i;
else
return -1;

}



grazie mille a tutti per la disponibilità

P8257 WebMaster
28-08-2009, 18.41.00
L'operatore '==' è di tipo binario, è sbagliato utilizzarlo con le stringhe per i confronti, può essere molto pericoloso e crearti anche comportamenti inattesi utilizza

string::compare(...)

Nel secondo caso ti funziona perché viene calcolata la risultante binaria tra le due espressioni (ma non è comunque consigliabile usarlo), nell'altro caso non funziona perché '\0' è un carattere e per giunta un carattere speciale.

Semi.genius
28-08-2009, 18.58.20
prima di tutto dal codice sembra che a[i] l'hai dichiarato globalmente. Prima regola per i buon programmi: non dichiarare mai globalmente qualcosa che non siano costanti o variabili "di servizio". Non farlo, rende difficile la ricerca della variabile nel codice e il suo debug, redendo imprevedibili i programmi. Piuttosto passala come argomento.
Secondo, le stringhe non vanno mai comparate con == ! Questo perché le stringhe le puoi considerare un vettore e nella variabile fittizia string viene salvato l'indirizzo della prima cella. Confrontando con if due variabili string si confronta in realtà il loro indirizzo in memoria, che sarà (sennò colliderebbero) sempre diverso.
Il modo giusto per confrontare due stringhe è usare la funzione compare fornita dall'include <string> perciò (ammentendo di seguire c++)

if( titolo.compare(a[i].nomevol)==0 )

Terzo, if ( i = -1 ) così fai un assegnamento. Se il tuo obiettivo è confrontare devi fare if (i == -1)

Quarto, a[j].nomevol == '\0' così stai confrontando una stringa con un carattere. Se vuoi sapere se la stringa è vuota (credo sia questo il tuo obiettivo) devi verificare il carattere. per me invece di assegnarli '\0' verrebbe più comodo se li inizializzazi le stringhe come "". in questo modo ti basterebbe fare if(a[i].nomevol.empty()) e controlli se la stringa è vuota.

Semi.genius
28-08-2009, 19.02.18
L'operatore '==' è di tipo binario, è sbagliato utilizzarlo con le stringhe per i confronti, può essere molto pericoloso e crearti anche comportamenti inattesi utilizza

string::compare(...)

Nel secondo caso ti funziona perché viene calcolata la risultante binaria tra le due espressioni (ma non è comunque consigliabile usarlo), nell'altro caso non funziona perché '\0' è un carattere e per giunta un carattere speciale.

mi hai preceduto :D

ArrigoC
28-08-2009, 19.25.44
Capito, ho fatto come tu mi hai consigliato, inizializzando le stringhe con "" e usando la funzione empty, ma ora mi da "errore di segmentazione"
Il codice modificato e':


void Biblioteca::Aggiungi_volume(int quant,string titolo,string coll,int Q)
{

int x;
int j;
bool t=false;

x = TrovaVolumeDaNome(titolo,Q);

if ( x == -1 )
{
for (j=0; j<Q && !t;j++)
{
if ( a[j].nomevol.empty() )
{
a[j].nomevol = titolo;
a[j].quantitadisponibile=quant;
a[j].collocazione = coll;
t=true;
}
}

if (j==Q)
cout<<"biblioteca piena.\n";

}
else
a[x].quantitadisponibile=(a[x].quantitadisponibile)+quant;
}


Stavo pensando al fatto che hai detto, ossia che a[j] l'ho dichiarata come variabile globale. Io non l'ho fatto, perchè l'ho dichiarato come membro di una classe ( membro privato ) e sò che le funzioni membro della classe possono accedere ai membri privati della stessa classe

Semi.genius
28-08-2009, 19.35.26
Capito, ho fatto come tu mi hai consigliato, inizializzando le stringhe con "" e usando la funzione empty, ma ora mi da "errore di segmentazione"
Il codice modificato e':


void Biblioteca::Aggiungi_volume(int quant,string titolo,string coll,int Q)
{

int x;
int j;
bool t=false;

x = TrovaVolumeDaNome(titolo,Q);

if ( x == -1 )
{
for (j=0; j<Q && !t;j++)
{
if ( a[j].nomevol.empty() )
{
a[j].nomevol = titolo;
a[j].quantitadisponibile=quant;
a[j].collocazione = coll;
t=true;
}
}

if (j==Q)
cout<<"biblioteca piena.\n";

}
else
a[x].quantitadisponibile=(a[x].quantitadisponibile)+quant;
}


Stavo pensando al fatto che hai detto, ossia che a[j] l'ho dichiarata come variabile globale. Io non l'ho fatto, perchè l'ho dichiarato come membro di una classe ( membro privato ) e sò che le funzioni membro della classe possono accedere ai membri privati della stessa classe

ah ok, allora va bene, non vedendo gli attributi della classe pensavo che l'avevi dichiarata al di fuori

L'errore di segmentazione lo avrai probabilmente perché l'indice j del for supera la dimensione dell'array a e perciò va a controllare campi al di fuori "del tuo dominio" finché supera il segmento che il sistema operativo ti ha offerto. controlla bene il funzionamento del programma

ArrigoC
28-08-2009, 19.45.02
Controllato e ricontrollato, anche con il debugger, e mi dà errore alla comparazione delle stringhe. ho scritto:


int Biblioteca::TrovaVolumeDaNome (string titolo,int Q)
{
for (int i=0;i<Q;i++)
if (titolo.compare(a[i].nomevol)==0) // qui dà errore
return i;
else
return -1;

}

e se dà errore lì penso dia errore anche alla funzione successiva


void Biblioteca::Aggiungi_volume(int quant,string titolo,string coll,int Q)
{

int x;
int j;
bool t=false;

x = TrovaVolumeDaNome(titolo,Q);

if ( x == -1 )
{
for (j=0; j<Q && !t;j++)
{
if ( a[j].nomevol.empty() )
{
a[j].nomevol = titolo;
a[j].quantitadisponibile=quant;
a[j].collocazione = coll;
t=true;
}
}

if (j==Q)
cout<<"biblioteca piena.\n";

}
else
a[x].quantitadisponibile=(a[x].quantitadisponibile)+quant;
}

Semi.genius
28-08-2009, 19.49.51
Controllato e ricontrollato, anche con il debugger, e mi dà errore alla comparazione delle stringhe. ho scritto:


int Biblioteca::TrovaVolumeDaNome (string titolo,int Q)
{
for (int i=0;i<Q;i++)
if (titolo.compare(a[i].nomevol)==0) // qui dà errore
return i;
else
return -1;

}

e se dà errore lì penso dia errore anche alla funzione successiva


void Biblioteca::Aggiungi_volume(int quant,string titolo,string coll,int Q)
{

int x;
int j;
bool t=false;

x = TrovaVolumeDaNome(titolo,Q);

if ( x == -1 )
{
for (j=0; j<Q && !t;j++)
{
if ( a[j].nomevol.empty() )
{
a[j].nomevol = titolo;
a[j].quantitadisponibile=quant;
a[j].collocazione = coll;
t=true;
}
}

if (j==Q)
cout<<"biblioteca piena.\n";

}
else
a[x].quantitadisponibile=(a[x].quantitadisponibile)+quant;
}


1. controlla se titolo è una stringa
2. controlla se l'indice i non va fuori la grandezza dell'array

ps. leggi pm e se puoi allega lintero programma