|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9434
|
[C++]confrontare 2 stringhe
Ciao a tutti ragazzi mi date una mano per favore a capire questo programma?
Ci sono alcune cose che non ho capito e spero nel vostro aiuto e spiegazione per allontanarmi da ciò che c'è scritto sul libro che non riesco a mettere in pratica. Questo è un programma che deve confrontare 2 stringhe Considerando quel main potete dirmi perchè ci sono 3 costruttori? quello a 0 argomenti, quello con argomenti e quello di copia Codice:
#ifndef _STRINGA_H_
#define _STRINGA_H_
#include <iostream>
#include <stdlib.h>
using namespace std;
class Stringa{
private:
char* str;
int l;//lunghezza stringa
public:
Stringa():str(0){};
Stringa(const char*);
Stringa(const Stringa &);
~Stringa() {delete [] str;}
int Lunghezza() const {return l;}
void Stampa() const {cout<<str;}
const Stringa& operator=(const Stringa&);
bool operator==(const Stringa&);
friend ostream& operator<<(ostream& out,const Stringa &s) { s.Stampa(); return out;}
};
commento a lato per evidenziare cosa ho capito Codice:
#include "string.h"
Stringa::Stringa(const char* sr){
const char* app = sr; //inizializzo puntatore a carattere con sr
l=0; //lunghezza stringa nulla
while(*app++) l++; //mentre il puntatore avanza, aumenta la lunghezza
app = sr; //questa non l'ho capita
str = new char[l+1];// per il temrinatore ???ma che vuol dire?
char* app2 = str;
while (*app2++=*app++);
}
Stringa::Stringa(const Stringa & s){
const char* app = s.str;
l=s.l;
str = new char [l+1];
char* app2 = str;
while (*app2++ = *app++);
}
const Stringa& Stringa::operator=(const Stringa& s){
if(this == &s); //self-assignment(a=a);
else{
delete [] str;
const char* app = s.str;
l=s.l;
str = new char [l+1];
char* app2 = str;
while (*app2++ = *app++);
}
return *this;
}
bool Stringa::operator==(const Stringa& s){
if(l != s.l) return false;
else{
char* app = str;
char* app2 = s.str;
for(;*app == *app2 && *app != '\0';*app++,*app2++);
if( *app == '\0' && *app2=='\0') return true;
else return false;
}
}
mi potreste spiegare la loro implementazione cosa fa di preciso? Codice:
#include "string.h"
int main(){
Stringa s1("ciao");
Stringa s2("gatto ");
cout<<s1<<endl;
cout<<s2<<endl;
if( s1 == s2) cout<<"\nuguali"; else cout<<"\ndiversi";
system("pause");
return 0;
}
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. |
|
|
|
|
|
#2 | ||
|
Senior Member
Iscritto dal: Jul 2005
Città: Vicenza
Messaggi: 1570
|
Allora, andiamo per passi:
Quote:
Quello senza argomenti ovviamente inizializza la stringa ad una stringa nulla (in quanto azzera il puntatore a char "str". Il secondo infine inizializza la stringa fornendogli una stringa in stile c. Riguardo al codice: Codice:
app = sr; Codice:
str = new char[l+1]; Codice:
char* app2 = str;
while (*app2++=*app++);
Quote:
|
||
|
|
|
|
|
#3 | ||
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9434
|
Veramente grazie
Quote:
Quote:
Cerco di spiegarmi prima l'implementazione dell'operatore di assegnamento. Questo viene implementata come metodo di una classe e quindi ha al primo operando un oggetto della classe stessa, oppure la definivo come funzione esterna (eventualmente dichiarandola friend della classe se accede ai membri privati della classe). Codice:
const Stringa& Stringa::operator=(const Stringa& s){
if(this == &s); //self-assignment(a=a); //se il puntatore all'oggetto stringa ha lo stesso indirizzo della stringa s. Non fa nulla
else{
delete [] str; //oppure cancella l'estensione dinamica di str
const char* app = s.str; //assegna ad app la stringa str (come l'operazione che mi hai spiegato prima)
l=s.l; //questa non l'ho capita
str = new char [l+1];
//queste operazioni sono quelle che mi hai detto prima
char* app2 = str;
while (*app2++ = *app++);
}
return *this; //ritorna l'oggetto stesso, poichè il risultato dell'operazione è l'oggetto stesso
}
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. |
||
|
|
|
|
|
#4 | ||
|
Senior Member
Iscritto dal: Jul 2005
Città: Vicenza
Messaggi: 1570
|
Quote:
Per questo serve un costruttore per copia, perchè se non specificato dall'utente viene generato un costruttore per copia di default. Questo non fa altro che eseguire una copia membro per membro. Puoi immaginare come questa operazione sia errata nel caso di un campo puntatore, in quanto si andrebbe a copiare solo il puntatore stesso, cioè l'indirizzo del primo carattere della stringa memorizzata. Questo porterebbe le due istanze a puntare alla stessa stringa in memoria, e quindi le operazioni sulla prima avrebbero ripercussioni anche sulla seconda. Per questo si va a specificare un costruttore per copia, così da cambiare questo comportamento e far si che venga generata una stringa completamente nuova (per l'appunto una copia). Quote:
Codice:
l=s.l; //questa non l'ho capita
str = new char [l+1];
|
||
|
|
|
|
|
#5 | ||
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9434
|
Quote:
questo è stato un ottimo caso per specificare il problema che hai posto. Quote:
Anche per questo vale ciò che ho scritto prima "Questo viene implementata come metodo di una classe e quindi ha al primo operando un oggetto della classe stessa, oppure la definivo come funzione esterna (eventualmente dichiarandola friend della classe se accede ai membri privati della classe)." ma perchè viene definita in questo modo in bool e non con Stringa & Codice:
bool Stringa::operator==(const Stringa& s){
if(l != s.l) return false; //se le due lunghezze son diverse return false
else{
char* app = str; //copia le due stringhe in app e app2
char* app2 = s.str;
for(;*app == *app2 && *app != '\0';*app++,*app2++);
//il primo ; non l'ho capito, per le due strighe che sono uguali e per il puntatore app che non ha ancora raggiunto l'ultimo carattere, incrementa i due puntatori
if( *app == '\0' && *app2=='\0') return true;
//se i due puntatori puntano al carattere terminazione ,quindi stringhe vuote return true
else return false;
}
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. |
||
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Attenzione - Si tratta di un programma di esempio, a puro scopo didattico.
Il codice, infatti, non e' sicuro e potrebbe portare a problemi (i.e. crash) se usato in un software "vero".
__________________
In God we trust; all others bring data |
|
|
|
|
|
#7 | ||
|
Senior Member
Iscritto dal: Jul 2005
Città: Vicenza
Messaggi: 1570
|
Quote:
Quote:
Un riferimento all'istanza stessa lo restituisci nel caso di operatori come quello di uguaglianza, di somma, moltiplicazione, ecc... Questo tra l'altro non è NECESSARIO (potresti restituire anche un void), ma viene utilizzato come tecnica per permettere la concatenazione dell'operazione (es° a * b * c, oppure a = b = c) |
||
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9434
|
Grazie Kendall
molto chiaro grazie ti posso chiedere una spiegazione sul ciclo for dell'overload dell'operatore di confronto? Poi metto tutto insieme e spero che tutto fili grzie ancora
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. |
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Jul 2005
Città: Vicenza
Messaggi: 1570
|
Quote:
Codice:
for(;*app == *app2 && *app != '\0';*app++,*app2++); app e app2 sono puntatori a char che all'inizio del ciclo for puntano al carattere iniziale delle rispettive stringhe. il primo ";" preceduto dal nulla significa banalmente che non viene inizializzato alcun indice o altra variabile (tipo il classico "int i = 0", quindi la condizione di uscita non necessita di variabili aggiuntive). La condizione " *app == *app2 && *app != '\0' "controlla che il carattere puntato attualmente da app e app2 corrisponda, nonchè che sia diverso dal carattere nullo. Infine vengono fatti avanzare entrambi i puntatori per passare al carattere successivo. In questa maniera il ciclo termine o se viene trovata una differenza nei caratteri, o se viene raggiunta la fine della stringa cioè il carattere nullo (nel primo caso le stringhe son diverse, nel secondo sono uguali). |
|
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9434
|
ciao kendall
ora mi è venuto un dubbio in un altro post , ed in un'altra classe avevo ad esempio Codice:
char * marca
che quindi nel costruttore avevo
Moto::Moto(const char *mar)
{
Marca=new char[strlen(mar)+1]
strcpy(Marca,mar)
}
ritornando al problema poichè nella classe abbiamo Codice:
char * str perchè poi ho anche Codice:
str=new char[l+1] perchè? perchè in questo problema si devono solo confrontare le stringhe che lo si fa tramite i puntatori. PErò poi perchè si sceglie una strada o un altra?
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. |
|
|
|
|
|
#11 | |
|
Senior Member
Iscritto dal: Jul 2005
Città: Vicenza
Messaggi: 1570
|
Quote:
Se ti guardi anche solo la lista di funzioni per la manipolazione di stringhe contenuto nell'header cstring (o string.h se lavori sotto c) vedrai come contenga tutto e molto di più del contenuto della classe che hai analizzato in questo thread. si parla ovviamente di manipolazioni a basso livello, per un utilizzo più generico delle stringhe ricorda di utilizzare sempre la classe String del c++. |
|
|
|
|
|
|
#12 | |
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9434
|
te l'ho chiesto poichè in quell'occasione il costruttore di copia non è stato usato. E questo mi fa pensare
Mi posso per esempio regolare così?se scelgo di implementare con i puntatori allora vado a considerare il costruttore di copia se no , uso quell'altra forma. Avevo sotto mano un altro esercizio dove appunto c'è il costruttore di copia, però poi l'implementazione non è svolta con i puntatori. Perciò capisco ciò che mi hai spiegato così chiaramente rispetto al libro Quote:
Il discriminante dei puntatori vengono meno perchè in quest'esercizio che sto visionando adesso non ce ne son. A meno che non li si utilizzi quando ho estensione dinamica.
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. |
|
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Jul 2005
Città: Vicenza
Messaggi: 1570
|
Il costruttore per copia, così come l'operatore di assegnamento, lo devi utilizzare quando questo si discosta rispetto al comportamento di default (cioè nel caso nel quale tu non specifichi nulla).
Per default, sia il costruttore per copia che l'operatore di assegnazione fanno una copia membro a membro (con il comportamento che ti ho spiegato prima). Se questo non è ciò che desideri allora devi specificarli da te. |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 16:36.



















