6.9 Класс String
6.9 Класс String
Вот довольно реалистичный пример класса строк string. В нем производится учет ссылок на строку с целью минимизировать копирование и в качестве констант применяются стандартные символьные строки С++.
#include «stream.h» #include «string.h»
class string (* struct srep (* char* s; // указатель на данные int n; // счетчик ссылок *); srep *p;
public: string(char *); // string x = «abc» string(); // string x; string(string amp;); // string x = string ... string amp; operator=(char *); string amp; operator=(string amp;); ~string(); char amp; operator[](int i);
friend ostream amp; operator«„(ostream amp;, string amp;); friend istream amp; operator“»(istream amp;, string amp;);
friend int operator==(string amp; x, char* s) (*return strcmp(x.p-»s, s) == 0; *)
friend int operator==(string amp; x, string amp; y) (*return strcmp(x.p-»s, y.p-»s) == 0; *)
friend int operator!=(string amp; x, char* s) (*return strcmp(x.p-»s, s) != 0; *)
friend int operator!=(string amp; x, string amp; 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 amp; x) (* x.p-»n++; p = x.p; *)
string::~string() (* if (–p-»n == 0) (* delete p-»s; delete p; *) *)
Как обычно, операции присваивания очень похожи на контрукторы. Они должны обрабатывать очистку своего первого (лвого) операнда:
string amp; 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 amp; string::operator=(string amp; x) (* x.p-»n++; if (–p-»n == 0) (* delete p-»s; delete p; *) p = x.p; return *this; *)
Операция вывода задумана так, чтобы продемонстрировать применение учета ссылок. Она повторяет каждую вводимую строку (с помощью операции ««, которая определяется позднее):
ostream amp; operator«„(ostream amp; s, string amp; x) (* return s „„ x.p-“s „« « [“ «« x.p-“n «« «] “; *)
Операция ввода использует стандартную функцию ввода сивольной строки (#8.4.1).
istream amp; operator»»(istream amp; s, string amp; x) (* char buf[256]; s »» buf; x = buf; cout «„ "echo: " «« x «« « “; return s; *)
Для доступа к отдельным символам предоставлена операция индексирования. Осуществляется проверка индекса:
void error(char* p) (* cerr «„ p «« « “; exit(1); *)
char amp; string::operator[](int i) (* if (i«0 !! strlen(p-»s)«i) error(„индекс за границами“); return p-»s[i]; *)
Головная программа просто немного опробует действия над строками. Она читает слова со ввода в строки, а потом эти строки печатает. Она продолжает это делать до тех пор, пока не распознает строку done, которая завершает сохранение слов в строках, или пока не встретит конец файла. После этого она печатает строки в обратном порядке и завершается.
main() (* string x[100]; int n;
cout «„ „отсюда начнем “; for (n = 0; cin“»x[n]; n++) (* string y; if (n==100) error(«слишком много строк»); cout «„ (y = x[n]); if (y=="done") break; *) cout «« «отсюда мы пройдем обратно “;
for (int i=n-1; 0«=i; i–) cout «« x[i]; *)