Бьерн Страуструп. Язык программирования С++ Второе дополненное издание



Pdf көрінісі
бет148/256
Дата11.07.2022
өлшемі2,87 Mb.
#37591
1   ...   144   145   146   147   148   149   150   151   ...   256
7.11 Строковый класс 
Теперь можно привести более осмысленный вариант класса string. В нем подсчитывается число ссылок 
на строку, чтобы минимизировать копирование, и используются как константы стандартные строки C++. 
#include  
#include  
class string { 
struct srep { 
char* 
s; 
// указатель на строку 
int 
n; 
// 
счетчик числа ссылок 
srep() { n = 1; } 
}; 
srep 
*p; 
public: 
string(const char *); 
// string x = "abc" 
string(); 
// 
string 
x; 
string(const string &); 
// string x = string ... 
string& operator=(const char *); 
string& operator=(const string &); 
~string(); 
char& 
operator[](int 
i); 
friend ostream& operator<<(ostream&, const string&); 
friend istream& operator>>(istream&, string&); 
friend int operator==(const string &x, const char *s) 
{ return strcmp(x.p->s,s) == 0; } 
friend int operator==(const string &x, const string &y) 
{ return strcmp(x.p->s,y.p->s) == 0; } 
friend int operator!=(const string &x, const char *s) 
{ return strcmp(x.p->s,s) != 0; } 
friend int operator!=(const string &x, const string &y) 
{ return strcmp(x.p->s,y.p->s) != 0; } 
}; 
Конструкторы и деструкторы тривиальны: 
string::string() 

p = new srep; 
p->s = 0; 

string::string(const string& x) 

x.p->n++; 
p = x.p; 

string::string(const char* s) 

p = new srep; 
p->s = new char[ strlen(s)+1 ]; 
strcpy(p->s, 
s); 

string::~string() 

if (--p->n == 0) { 
delete[] 
p->s; 
delete 
p; 



Бьерн Страуструп.
Язык программирования С++ 
 
199 

Как и всегда операции присваивания похожи на конструкторы. В них нужно позаботиться об удалении 
первого операнда, задающего левую часть присваивания: 
string& string::operator=(const char* s) 

if (p->n > 1) { 
// отсоединяемся от старой строки 
p->n--; 
p = new srep; 

else 
// освобождаем строку со старым значением 
delete[] 
p->s; 
p->s = new char[ strlen(s)+1 ]; 
strcpy(p->s, 
s); 
return 
*this; 

string& string::operator=(const string& x) 

x.p->n++; 
// защита от случая ``st = st'' 
if (--p->n == 0) { 
delete[] 
p->s; 
delete 


p = x.p; 
return 
*this; 

Операция вывода показывает как используется счетчик числа ссылок. Она сопровождает как эхо 
каждую введенную строку (ввод происходит с помощью операции << , приведенной ниже): 
ostream& operator<<(ostream& s, const string& x) 

return s << x.p->s << " [" << x.p->n << "]\n"; 

Операция ввода происходит с помощью стандартной функции ввода символьной строки ($$10.3.1): 
istream& operator>>(istream& s, string& x) 

char 
buf[256]; 
s >> buf;
// ненадежно: возможно переполнение buf 
// правильное решение см. в $$10.3.1 
x = buf; 
cout << "echo: " << x << '\n'; 
return 
s; 

Операция индексации нужна для доступа к отдельным символам. Индекс контролируется: 
void error(const char* p) 

cerr << p << '\n'; 
exit(1); 

char& string::operator[](int i) 

if (i<0 || strlen(p->s)недопустимое значение индекса"); 
return 
p->s[i]; 



Бьерн Страуструп.
Язык программирования С++ 
 
200 
В основной программе просто даны несколько примеров применения строковых операций. Слова из 
входного потока читаются в строки, а затем строки печатаются. Это продолжается до тех пор, пока не 
будет обнаружена строка done, или закончатся строки для записи слов, или закончится входной поток. 
Затем печатаются все строки в обратном порядке и программа завершается. 
int main() 

string 
x[100]; 
int 
n; 
cout << " здесь начало \n"; 
for ( n = 0; cin>>x[n]; n++) { 
if 
(n==100) 

error("слишком много слов"); 
return 
99; 

string 
y; 
cout << (y = x[n]); 
if (y == "done") break; 

cout << "теперь мы идем по словам в обратном порядке \n"; 
for (int i=n-1; 0<=i; i--) cout << x[i]; 
return 
0; 



Достарыңызбен бөлісу:
1   ...   144   145   146   147   148   149   150   151   ...   256




©emirsaba.org 2024
әкімшілігінің қараңыз

    Басты бет