Mam kolejne zadanie z klasami. Tym razem na stringach więc kolejna porcja nauki będzie. Mam dopisać 3 moduły do podanej klasy: atoi, tolower, left (usuwa od lewej n znaków)
Ale jako pierwsze zadanie to raczej trzeba zrozumieć co oznacza już kod, który mamy podany. Dodałem komentarze do kodu żeby móc się odnaleźć i rozumieć to bardziej ale i tak potrzebuję pomocy w tym.
rcstring.h:
#ifndef __RCSTRING_H__
#define __RCSTRING_H__
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#include <iostream>
using namespace std;
class rcstring {
struct rctext;
rctext* data;
public:
class Range {
};
class Cref;
rcstring();
rcstring(const char*);
rcstring(const rcstring&);
~rcstring();
rcstring& operator=(const char*);
rcstring& operator=(const rcstring&);
rcstring& operator+=(const rcstring&);
rcstring operator+(const rcstring&) const;
friend ostream& operator<<(ostream&, const rcstring&);
void check(unsigned int i) const;
char read(unsigned int i) const;
void write(unsigned int i, char c);
char operator[](unsigned int i) const;
Cref operator[](unsigned int i);
};
/////////////////POCZATEK STRUCT RCTEXT //////////////////
struct rcstring::rctext {
char* s;
unsigned int size;
unsigned int n;
rctext(unsigned int nsize, const char* p) //konstruktor
{
n = 1;
size = nsize;
s = new char[size + 1];
strncpy(s, p, size); //skopiuje "size" znaków z p do s
s[size] = '\0';
};
~rctext() //destruktor
{
delete[] s;
};
rctext* detach() //funkcja detach() zwykle pozwala wątkowi kontynuować działanie niezależnie, tutaj jeszcze nie wiem o co chodzi
{
if (n == 1)
return this;
rctext* t = new rctext(size, s);
n--;
return t;
};
void assign(unsigned int nsize, const char* p)
{
if (size != nsize) {
char* ns = new char[nsize + 1];
size = nsize;
strncpy(ns, p, size); //skopiuje "size" znaków z p do ns
delete[] s;
s = ns;
}
else
strncpy(s, p, size);
s[size] = '\0';
}
private:
rctext(const rctext&);
rctext& operator=(const rctext&);
};
////////////////////KONIEC STRUCT RCTEXT ///////////////////////////
////////////////////POCZĄTEK CLASS CREF ////////////////////////////
class rcstring::Cref {
friend class rcstring;
rcstring& s;
int i;
Cref(rcstring& ss, unsigned int ii)
: s(ss)
, i(ii){};
public:
operator char() const
{
cout << "operator char() const" << endl;
return s.read(i);
}
rcstring::Cref& operator=(char c)
{
cout << "void operator = (char c)" << endl;
s.write(i, c);
return *this;
}
rcstring::Cref& operator=(const Cref& ref)
{
return operator=((char)ref);
}
};
//////////////////KONIEC CLASS CREF ///////////////////////////
inline rcstring::rcstring()
{
data = new rctext(0, "");
}
inline rcstring::rcstring(const rcstring& x)
{
x.data->n++;
data = x.data;
}
inline rcstring::~rcstring()
{
if (--data->n == 0)
delete data;
}
rcstring& rcstring::operator=(const rcstring& x)
{
x.data->n++;
if (--data->n == 0)
delete data;
data = x.data;
return *this;
}
rcstring::rcstring(const char* s)
{
data = new rctext(strlen(s), s);
}
rcstring& rcstring::operator=(const char* s)
{
if (data->n == 1)
data->assign(strlen(s), s);
else {
rctext* t = new rctext(strlen(s), s);
data->n--;
data = t;
};
return *this;
}
ostream& operator<<(ostream& o, const rcstring& s) //wypisanie do konsoli
{
return o << s.data->s;
}
rcstring& rcstring::operator+=(const rcstring& s)
{
unsigned int newsize = data->size + s.data->size;
rctext* newdata = new rctext(newsize, data->s); //wykorzystanie konstruktora chyba
strcat(newdata->s, s.data->s); //dopisanie na koniec newdata->s tego co po prawej
if (--data->n == 0) //Co oznacza --data?
delete data;
data = newdata;
return *this;
}
rcstring rcstring::operator+(const rcstring& s) const
{
return rcstring(*this) += s;
}
inline void rcstring::check(unsigned int i) const
{
if (data->size <= i)
throw Range();
}
inline char rcstring::read(unsigned int i) const
{
return data->s[i];
}
inline void rcstring::write(unsigned int i, char c)
{
data = data->detach();
data->s[i] = c;
}
char rcstring::operator[](unsigned int i) const
{
cout << "char rcstring::operator[](unsigned int i) const" << endl; //Nie wiem na co to wypisywanie do konsoli
check(i); //check robi: if(data->size<=i) to throw Range() ? Range to pusta klasa więc nwm;
return data->s[i];
}
rcstring::Cref rcstring::operator[](unsigned int i) // to co wyżej tylko, że to akurat jest używane w programie patrząc na konsole
{
cout << "Cref rcstring::operator[](unsigned int i)" << endl;
check(i);
return Cref(*this, i);
}
#endif /* __RCSTRING_H__ */
Plik cpp:
#include "rcstring.h"
int main()
{
#include "rcstring.h"
int main()
{
rcstring a, b, c;
a = "10";
b = "ala ma kota";
cout << a << " " << b << endl; // 10 ala ma ma kota
c = a + b;
cout << c << endl; // 10ala ma kota
c = a + rcstring(" ") + b;
cout << c << endl; //10 ala ma kota
rcstring d("a");
cout << d << endl; //a
d += "ula";
cout << d << endl; //aula
d += "15";
cout << d << endl; //aula15
cout << d[3] << endl; //a
d[3] = 'b';
cout << d << endl; //aulb15
d[2] = d[1] = d[0];
cout << d << endl; //aaab15
return 0;
}