Classe Stringhetta

#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdlib>

using namespace std;

class Stringhetta
{
	//funzione friend che servono per gli operatori << e >>
	friend ostream &operator<<(ostream &uscita, const Stringhetta &s);
	friend istream &operator>>(istream &ingresso, Stringhetta &s);
	
public:
	Stringhetta(const char *s = "");// costruttore di defoult, assegna per defoult una Stringhetta vuota
	Stringhetta(const Stringhetta &s);// costruttore di copia

	~Stringhetta();//distruttore

	// riassegnazione di operatori
	const Stringhetta &operator=(const Stringhetta &s);//operatore di assegnamento
	const Stringhetta &operator+=(const Stringhetta &s);//operatore di concatenamento
    const Stringhetta &operator+=(const char s);//operatore di concatenamento
	const Stringhetta &operator+(const Stringhetta &s);//operatore di concatenamento in Stringhetta nuova
    bool operator!() const;// risponde alla domanda !s -> "la Stringhetta this è vuota?" Questa è una ridefinizione non in linea con il significato dell'operatore !
	bool operator==(const Stringhetta &s) const;// verifica se this == s
	bool operator<(const Stringhetta &s) const;// verifica se this < s
	char &operator[](int n);//operatore di indicizzazione lvalue per modifica
	char operator[](int n) const;//operatore di indicizzazione rvalue
	Stringhetta operator()(int n, int l = 0);//estrae una sottostringa dalla posizione n, lunga l, l per default può valere 0 lo considererò "finoi alla fine"

	
	int getLunghezza() const;//restituisce la lunghezza della Stringhetta
	// riassegnazione di operatori in line
		bool operator!=(const Stringhetta &s) const {
		return !(*this == s);//!(==) 
	}// verifica se this != s e permette la chiamata in line della funzione serve la classe proxi
	
	bool operator>(const Stringhetta &s) const {// verifica se this > s
		return (s < *this); // this > s -> s < this
	}// verifica se this > s e permette la chiamata in line della funzione serve la classe proxi
	
	bool operator<=(const Stringhetta &s) const {// verifica se this <= s
		return !(s < *this); // this <= s -> s >= this -> !(s < this) 
	}// verifica se this <= s e permette la chiamata in line della funzione serve la classe proxi

	bool operator>=(const Stringhetta &s) const {// verifica se this >= s
		return !(*this < s); //this >= s -> !(this < s)
	}// verifica se this >= s e permette la chiamata in line della funzione serve la classe proxi


//funzione simile a Stringhetta operator()(int n, int l = 0); ma che nonn usa strcpy
    Stringhetta SottoStringhettina(int da,int quanto)
    {
    
    	int k=0;
    	if(quanto>lunghezza)
    	quanto =lunghezza+1;
        else if(quanto <=0)
        quanto =0;
        else
        {
        	
		}
		char *ptrTmpStringa = new char[quanto-da + 1];
    	Stringhetta temp(ptrTmpStringa);
    	for(int i=da;i<da+quanto;i++)
    	{
    		temp.ptrStringa[k++]=ptrStringa[i];
		}
		temp.ptrStringa [k]='\0';
		return temp;
	}



private:
	//membri dato
	int lunghezza;//lunghezza della Stringhetta senza il carattere terminatore
	char *ptrStringa;//puntatore al primo carattere della Stringhetta
	//funzioni varie
	void setStringa(const char *s);//funzione che imposta la Stringhetta
};



Stringhetta::Stringhetta(const char *s)
	:lunghezza(s != "" ? strlen(s) : 0)// lunghezza o 0 oppure lunghezza di s
{
	//cout << "costruttore di default e di conversione: " << s << endl;
	setStringa(s);// utilizzata per creare l'istanza dell'oggetto
}






Stringhetta::Stringhetta(const Stringhetta & s)//costruttore di copia
: lunghezza(s.lunghezza)
{
	//cout << "costruttore di copia: " << s.ptrStringa << endl;
	setStringa(s.ptrStringa);// utilizzata ancora per creare l'istanza dell'oggetto
}// la corretta costruzione dell'oggetto è sempre gestita dalla funzione setStringa(s)

Stringhetta::~Stringhetta()
{
	//cout << "distruttore: " << ptrStringa << endl;
	delete [] ptrStringa;
}
 


const Stringhetta & Stringhetta::operator=(const Stringhetta & s)
{
	
	// evitiamo l'autoassegnamento
	if (&s != this) {
	
		delete[] ptrStringa;//cancello la vecchia Stringhetta
		lunghezza = s.lunghezza;
		setStringa(s.ptrStringa);// utilizzata ancora per creare l'istanza dell'oggetto
	}
	else {
	// se cerco di copiare su me stesso, avviso
		
	}// in entrambi i casi ritorno this
	return *this;
}

const Stringhetta & Stringhetta::operator+=(const Stringhetta & s)
{
	int newLunghezza = this->lunghezza + s.lunghezza;
	char *ptrTmp = new char[newLunghezza + 1];//mi creo il nuovo contenuto dell'oggetto
	strcpy(ptrTmp, ptrStringa);//copio nella nuova Stringhetta la prima parte, quella dell'oggetto "chiamante"
	strcpy(ptrTmp + lunghezza, s.ptrStringa);//(ptrTmp + lunghezza) è il puntatore alla posizione dove inserire la Stringhetta successiva da concatenare
	delete [] ptrStringa;// cancello lo spazio di memoria occupato precedentemente
	ptrStringa = ptrTmp; // associo il nuovo puntatore al puntatore dell'oggetto
	lunghezza = newLunghezza;// il valore della nuova lunghezza

	return *this;
}
//serve per formare una stringa aggiungendo caratteri
const Stringhetta & Stringhetta::operator+=(const char s)
{
	int newLunghezza = this->lunghezza + 1;
	char *ptrTmp = new char[newLunghezza + 1];//mi creo il nuovo contenuto dell'oggetto
	strcpy(ptrTmp, ptrStringa);//copio nella nuova Stringhetta la prima parte, quella dell'oggetto "chiamante"
    ptrTmp[lunghezza]=s;
    ptrTmp[lunghezza+1]='\0';
	delete [] ptrStringa;// cancello lo spazio di memoria occupato precedentemente
	ptrStringa = ptrTmp; // associo il nuovo puntatore al puntatore dell'oggetto
	lunghezza = newLunghezza;// il valore della nuova lunghezza

	return *this;
}



const Stringhetta & Stringhetta::operator+(const Stringhetta & s)
{
	Stringhetta *ptrTmpStringa = new Stringhetta("");//allochiamno la memoria per la Stringhetta temporanea
	ptrTmpStringa->lunghezza = this->lunghezza + s.lunghezza; //assegno la lunghezza della nuova Stringhetta
	strcpy(ptrTmpStringa->ptrStringa, this->ptrStringa);//copio nella nuova Stringhetta la prima parte, quella dell'oggetto "chiamante"
	strcpy(ptrTmpStringa->ptrStringa + lunghezza, s.ptrStringa);//(ptrTmp + lunghezza) è il puntatore alla posizione dove inserire la Stringhetta successiva da concatenare
	return *ptrTmpStringa;
}

bool Stringhetta::operator!() const
{
	return (lunghezza == 0);// le lunghezza è uguale a 0
}

bool Stringhetta::operator==(const Stringhetta & s) const
{
	return (strcmp(ptrStringa, s.ptrStringa) == 0);//strcmp ritorna 0 se le due stringhe sono uguali
}

bool Stringhetta::operator<(const Stringhetta & s) const
{
	return (strcmp(ptrStringa, s.ptrStringa) < 0);//strcmp ritorna un numero negativo se la prima Stringhetta è minore della seconda
}
//serve per quando andiamo a modificare un carattere della stringa
char & Stringhetta::operator[](int n)
{
	
	if ((n < 0) || (n >= lunghezza)) {//controllo che l'indice richiesto appartenga al range ammesso
		//cerr << "Errore: indice = " << n << " out of range (" << lunghezza << ")" << endl;
		return ptrStringa[lunghezza];		
		//exit(1);//fine del programma per errore lo maschero
	}
	return ptrStringa[n];//se tutto OK ritorno il carattere richiesto modificabile
}
//serve per quando andiamo a vedere un carattere della stringa
char Stringhetta::operator[](int n) const
{
	if ((n < 0) || (n >= lunghezza)) {//controllo che l'indice richiesto appartenga al range ammesso
		//cerr << "Errore: indice = " << n << " out of range (" << lunghezza << ")" << endl;
		return '\0';
		//exit(1);//fine del programma per errore
	}
	return ptrStringa[n];//se tutto OK ritorno il carattere richiesto costante
}

int Stringhetta::getLunghezza() const
{
	return lunghezza;
}

void Stringhetta::setStringa(const char * s)
{
// funzione alla base dell'inizializzazione della classe
	ptrStringa = new char[lunghezza + 1];//allochiamno la memoria necessaria (lunghezza + 1) per il carattere di terminazione
	if (s != 0) {
	//se s punta ad una Stringhetta la copio
	
		strcpy(ptrStringa, s);//lunghezza + 1 è richiesto da strcpy_s per evitare errori di overflow buffer
	}
	else {
	//altrimenti copio una Stringhetta vuota
		ptrStringa[0] = '\0';
	}
}

ostream & operator<<(ostream & uscita, const Stringhetta & s)
{
	uscita << s.ptrStringa;
	return uscita;
}

istream & operator>>(istream & ingresso, Stringhetta & s)
{
	char temp[100]; //mi creo un buffer per memorizzare l'ingresso -> 99 caratteri c'è anche il terminatore 
	ingresso >> setw(100) >> temp;//memorizzo l'input nel buffer temporaneo
	s = temp; // utilizzo la ridefinizione dell'operatore =   "const Stringhetta & Stringhetta::operator=(const Stringhetta & s)"
	return ingresso;
}







Stringhetta Stringhetta::operator()(int n, int l)
{

//estrae una sottostringa dalla posizione n, lunga l
	if ((n < 0) || (n >= lunghezza) || (l < 0)) {//controllo la correttezza dell'indice n e controllo che l sia maggiore di 0
		return "";// viene restituita una Stringhetta vuota, viene automaticamente convertita nell'oggetto Stringhetta
	}
	int newLunghezza;//si determina la lunghezza della sottostringa
	if ((l == 0) || (n + l > lunghezza)) {//se l è uguale a 0 oppure se n+l è maggiore della lunghezza totale della Stringhetta
		newLunghezza = lunghezza - n;//allora la lunghezza della nuova Stringhetta è dal'indice n fino alla fine 
	}
	else {
		newLunghezza = l;//altrimenti è uguale a l
	}

	char *ptrTmpStringa = new char[newLunghezza + 1];//c'è sempre il carattere di terminazione 
	//copio la sottostringa nell'area di memoria a lei dedicata
	strncpy(ptrTmpStringa, &ptrStringa[n], newLunghezza); //copio in ptrTempStringa la sottostringa di ptrStringa lunga newLunghezza partendo dalla posizione n
	ptrTmpStringa[newLunghezza] = '\0';//aggiungo il carattere di terminazione

	//creo per copia l'oggetto Tmpstringa

	Stringhetta tmpStringa(ptrTmpStringa);//richiamo il costruttore
	delete[] ptrTmpStringa;//cancello l'array temporaneo (la sottostringa è oramai salva in tmpStringa

	return tmpStringa; //ritorno una copia della Stringhetta temporanea
}





int main()
{
	Stringhetta k="ciao mondo";

    Stringhetta m=" bello ";
    
    Stringhetta j;
    k+=m;
    cout<<k<<endl;
    if(k==j)
    cout<<"Uguali\n";
    cin>>k;
    k[0]='Q';
    cout<<k[3]<<endl;
    cout<<k<<endl;
    Stringhetta t;
    string s="ciaoesvgfngmyumyu,i";
    for(int i=0;i<4;i++)
    t+=s[i];
    cout<<t<<endl;
    s[0]='Q';
    cout<<t<<endl;
    Stringhetta d("ciao");
    if(d==t)
    cout<<"Uguali\n";
  
    
    
}