Класс Строка
СОДЕРЖАНИЕ: Вот довольно реалистичный пример класса string. В нем производится учет ссылок на строку с целью минимизировать копирование и в качестве констант применяются стандартные символьные строки C++.Вот довольно реалистичный пример класса string. В нем производится учет ссылок на строку с целью минимизировать копирование и в качестве констант применяются стандартные символьные строки C++.
#include
#include
class string {
struct srep {
char* s; // указатель на данные
int n; // счетчик ссылок
};
srep *p;
public:
string(char *); // string x = abc
string(); // string x;
string(string ); // string x = string ...
string operator=(char *);
string operator=(string );
~string();
char operator[](int i);
friend ostream operator(ostream, string);
friend istream operator(istream, string);
friend int operator==(string x, char* s)
{return strcmp(x.p-s, s) == 0; }
friend int operator==(string x, string y)
{return strcmp(x.p-s, y.p-s) == 0; }
friend int operator!=(string x, char* s)
{return strcmp(x.p-s, s) != 0; }
friend int operator!=(string x, string y)
{return strcmp(x.p-s, y.p-s) != 0; }
};
Конструкторы и деструкторы просты (как обычно):
string::string()
{
p = new srep;
p-s = 0;
p-n = 1;
}
string::string(char* s)
{
p = new srep;
p-s = new char[ strlen(s)+1 ];
strcpy(p-s, s);
p-n = 1;
}
string::string(string x)
{
x.p-n++;
p = x.p;
}
string::~string()
{
if (--p-n == 0) {
delete p-s;
delete p;
}
}
Как обычно, операции присваивания очень похожи на конструкторы. Они должны обрабатывать очистку своего первого (левого) операнда:
string string::operator=(char* s)
{
if (p-n 1) { // разъединить себя
p-n--;
p = new srep;
}
else if (p-n == 1)
delete p-s;
p-s = new char[ strlen(s)+1 ];
strcpy(p-s, s);
p-n = 1;
return *this;
}
Благоразумно обеспечить, чтобы присваивание объекта самому себе работало правильно:
string string::operator=(string x)
{
x.p-n++;
if (--p-n == 0) {
delete p-s;
delete p;
}
p = x.p;
return *this;
}
Операция вывода задумана так, чтобы продемонстрировать применение учета ссылок. Она повторяет каждую вводимую строку (с помощью операции , которая определяется позднее):
ostream operator(ostream s, string x)
{
return s x.p-s [ x.p-n ]\n;
}
Операция ввода использует стандартную функцию ввода символьной строки.
istream operator(istream s, string x)
{
char buf[256];
s buf;
x = buf;
cout echo: x \n;
return s;
}
Для доступа к отдельным символам предоставлена операция индексирования. Осуществляется проверка индекса:
void error(char* p)
{
cerr p \n;
exit(1);
}
char string::operator[](int i)
{
if (i0 || strlen(p-s)s[i];
}
Головная программа просто немного опробует действия над строками. Она читает слова со ввода в строки, а потом эти строки печатает. Она продолжает это делать до тех пор, пока не распознает строку done, которая завершает сохранение слов в строках, или не встретит конец файла. После этого она печатает строки в обратном порядке и завершается.
main()
{
string x[100];
int n;
cout отсюданачнем\n;
for (n = 0; cinx[n]; n++) {
string y;
if (n==100) error(слишкоммногострок);
cout (y = x[n]);
if (y==done) break;
}
cout отсюда мы пройдем обратно\n;
for (int i=n-1; 0=i; i--) cout x[i];
}