Операция сложения может конкатенировать объекты класса string не только между собой, но и со строками встроенного типа. Можно переписать пример, приведенный выше, так, чтобы специальные символы и знаки препинания представлялись встроенным типом, а значимые слова – объектами класса string:

const char *pc = ", ";

string s1( "hello" );

string s2( "world" );

string s3 = s1 + pc + s2 + "\n";

Подобные выражения работают потому, что компилятор знает, как автоматически преобразовывать объекты встроенного типа в объекты класса string. Возможно и простое присваивание встроенной строки объекту string:

string s1;

const char *pc = "a character array";

s1 = pc; // правильно

Обратное преобразование, однако, не работает. Попытка выполнить следующую инициализацию строки встроенного типа вызовет ошибку компиляции:

char *str = s1; // ошибка компиляции

Чтобы осуществить такое преобразование, необходимо явно вызвать функцию-член с несколько странным названием c_str():

char *str = s1.c_str(); // почти правильно

Функция c_str() возвращает указатель на символьный массив, содержащий строку объекта string в том виде, в каком она находилась бы во встроенном строковом типе.

Приведенный выше пример инициализации указателя char *str все еще не совсем корректен. c_str() возвращает указатель на константный массив, чтобы предотвратить возможность непосредственной модификации содержимого объекта через этот указатель, имеющий тип

const char *

(В следующем разделе мы расскажем о ключевом слове const). Правильный вариант инициализации выглядит так:

const char *str = s1.c_str(); // правильно

К отдельным символам объекта типа string, как и встроенного типа, можно обращаться с помощью операции взятия индекса. Вот, например, фрагмент кода, заменяющего все точки символами подчеркивания:

string str( "fa.disney.com" );

int size = str.size();

for ( int ix = 0; ix size; ++ix )

if ( str[ ix ] == '.' )

str[ ix ] = '_';

Вот и все, что мы хотели сказать о классе string прямо сейчас. На самом деле, этот класс обладает еще многими интересными свойствами и возможностями. Скажем, предыдущий пример реализуется также вызовом одной-единственной функции replace():

replace( str.begin(), str.end(), '.', '_' );

replace() – один из обобщенных алгоритмов, с которыми мы познакомились в разделе 2.8 и которые будут детально разобраны в главе 12. Эта функция пробегает диапазон от begin() до end(), которые возвращают указатели на начало и конец строки, и заменяет элементы, равные третьему своему параметру, на четвертый.

Упражнение 3.12

Найдите ошибки в приведенных ниже операторах:

(a) char ch = "The long and winding road";

(b) int ival = ch;

(c) char *pc = ival;

(d) string st( ch );

(e) pc = 0; (i) pc = '0';

(f) st = pc; (j) st = ival;

(g) ch = pc[0]; (k) ch = *pc;

(h) pc = st; (l) *pc = ival;

Упражнение 3.13

Объясните разницу в поведении следующих операторов цикла:

while ( st++ )

++cnt;

while ( *st++ )

++cnt;

Упражнение 3.14

Даны две семантически эквивалентные программы. Первая использует встроенный строковый тип, вторая – класс string:

// ***** Реализация с использованием C-строк *****

#include iostream

#include cstring

int main()

{

int errors = 0;

const char *pc = "a very long literal string";

for ( int ix = 0; ix 1000000; ++ix )

{

int len = strlen( pc );

char *pc2 = new char[ len + 1 ];

strcpy( pc2, pc );

if ( strcmp( pc2, pc ))

++errors;

delete [] pc2;

}

cout "C-строки: "

errors " ошибок.\n";

}

// ***** Реализация с использованием класса string *****

#include iostream

#include string

int main()

{

int errors = 0;

string str( "a very long literal string" );

for ( int ix = 0; ix 1000000; ++ix )

{

int len = str.size();

string str2 = str;

if ( str != str2 )

}

cout "класс string: "

errors " ошибок.\n;

}

Что эти программы делают?

Перейти на страницу:

Похожие книги