Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Не підтверджено.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
3.08 Mб
Скачать

Int mainO

{

char str[] = "STL-програмування - це сила!"; vector<char> vek; unsigned int i;

for(int i=0; str[i]; І++) vek.push_back(str[i]); cout«"Послідовність:";

for(int i=0; i<vek.sizeO; i++) cout« vek[i]; cout« endl;

int n; charch = 'h';

n = count(vek.begin(), vek.end(), ch); cout« n «" символи« ch « « endl;

n = count_if(vek. beginO, vek.endO, isvowel);

cout« n «" символів представляють голосні звуки"« endl;

getchO; return 0;

}

Внаслідок виконання ця програма відображає на екрані такі результати: Послідовність: STL-програмування - це сила!

  1. Символи н

  1. Символів представляють голосні звуки.

Програма починається із створення вектора, який містить рядок "STL-програму- вання - це сила!". Потім використовується алгоритм count() для підрахунку кількості букв 'н' у цьому векторі. Після цього викликається алгоритм count_if(), який підра­ховує кількість символів, що представляють голосні звуки з використанням як предикату функції isvowel(). Зверніть увагу на те, як закодований цей предикат. Всі унарні предикати отримують як параметр об'єкт, тип якого збігається з типом еле­ментів, що зберігаються у контейнері, для якого і створюється цей предикат. Пре­дикат повинен повертати значення ІСТИНА або ФАЛЬШ.

  1. Видалення та заміна елементів

Іноді корисно згенеруватн нову послідовність, яка складатиметься тільки з певних елементів початкової послідовності. Одним з алгоритмів, який може спра­витися з цим завданням, є remove_copy(). Його загальний формат має такий вигляд: template <class Forlter, class Outlter, class myType>

Outlter remove_copy(lnlter start, Inlter end,

Outlter result, const myType &i/a/);

Алгоритм remove_copyO копіює з вилученням із заданого діапазону елементи, які дорівнюють значенню val, і поміщає результат у послідовність, яка адресується параметром result. Алгоритм повертає ітератор, який вказує на кінець результату. Контейнер-приймач повинен бути достатньо великим, щоби прийняти отриманий результат.

Щоб у процесі копіювання у послідовності один елемент замінити іншим, ви­користовується алгоритм replace_copyO- Його загальний формат має такий вигляд: template <class Forlter, class Outlter, class myType>

Outlter replace_copy(lnlter start, Inlter end,

Outlter result, const myType &old, Const myType &new)\

Алгоритм replace_copy() копіює елементи із заданого діапазону у послідов­ність, яка адресується параметром result. У процесі копіювання відбувається заміна елементів, які мають значення old, елементами за значенням new. Алгоритм помі­щає результат у послідовність, яка адресується параметром result, і повертає ітера­тор, який вказує на кінець цієї послідовності. Контейнер-приймач повинен бути достатньо великим, щоби прийняти отриманий результат.

У наведеному нижче коді програми продемонстровано механізм використан­ня алгоритмів remove_copyO і replace_copy(). Під час її виконання створюється послі­довність символів, з якої видаляються всі букви 'е'. Потім здійснюється заміна всіх букв 'е' буквами 'х'.

Код програми 12.14. Демонстрація механізму використання алгоритмів remove_copy і replace_copy

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

#include <vector> // Для роботи з контейнерним класом "Вектор"

#include <algorithm> // Для роботи з алгоритмами бібліотеки STL

using namespace std; // Використання стандартного простору імен

int mainO

{

char str[] = "Це дуже простий тест."; vector<char> vek, vek2(30);

for(int i=0; str[i]; І++) vek.push_back(str[i]);

// **** Демонстрація алгоритму remove_copy ****

cout « "Вхідна послідовність: ";

for(int і=0; i<vek.sizeO; і++) cout« vek[i]; cout« endl;

// Видаляємо всі букви 'є'.

remove_copy(vek.begin(), vek.endO, vek2.begin0, V);

cout«"Після видалення букв 'т': for(int i=0; vek2[i]; І++) cout« vek2[i]; cout« endl« endl;

// **** Демонстрація алгоритму replace_copy ****

cout«"Вхідна послідовність:"; for(int i=0; i<vek.size(); І++) cout« vek[i]; cout« endl;

// Замінюємо букви 'є' буквами 'X'. replace_copy(vek.begin(), vek.endO, vek2.begin0, 'o', 'x');

cout«"Після заміни букв 'e' буквами 'X':"; for(int i=0; vek2[i]; І++) cout« vek2[i]; cout« endl« endl; getchO; return 0;

}

Внаслідок виконання ця програма відображає на екрані такі результати: Вхідна послідовність: Це дуже простий тест.

Після видалення букв 'е': Ц дуж простий тст.

Вхідна послідовність: Це дуже простий тест.

Після заміни букв 'е' буквами 'X': ЦХ дужХ простий тХст.

  1. Реверсування послідовності

У програмах часто використовують алгоритм reverse(), який у діапазоні, зада­ному параметрами start і end, змінює порядок слідування елементів на протилеж­ний. Його загальний формат має такий вигляд:

template <class Bilter> void reverse(Bilter start, Bilter end)]

У наведеному нижче коді програми продемонстровано механізм використан­ня цього алгоритму.

#include <vcl> #include <iostream> #include <conio> #include <vector> #include <algorithm> using namespace std;

Код програми 12.15. Демонстрація механізму використання алгоритму reverse

// Для потокового введення-виведення // Для консольного режиму роботи // Для роботи з контейнерним класом "Вектор" // Для роботи з алгоритмами бібліотеки STL // Використання стандартного простору імен

int mainO

{

vector<int> vek; unsigned int i;

for(int і=0; і<10; І++) vek.push_back(i);

cout«"Початкова послідовність: for(int і=0; i<vek.sizeO; і++) cout« vek[i]«" cout« endl;

reverse(vek. beginO, vek.endO);

cout«"Реверсована послідовність: for(int i=0; i<vek.sizeO; i++) cout« vek[i]«" getchO; return 0;

}

Внаслідок виконання ця програма відображає на екрані такі результати: Початкова послідовність: 0123456789 Реверсована послідовність: 9876543210

  1. Перетворення послідовності

Одним з найцікавіших є алгоритм перетворення послідовності transform(), який дає змогу модифікувати кожен елемент у діапазоні відповідно до заданої функції. Алгоритм transform() використовується у двох загальних форматах: template <class Inlter, class Outlter, class Func>

Outltertransform(lnlter start, Inlter end,

Outlter result, Func unaryfunc)',

template <class Inlterl, class Inlter2, class Outlter, class Func>

Outltertransform(lnlter1 startl, Inlterl endl,

Inlter2 start2, Outlter result, Func binaryfunc);

Алгоритм transform() застосовує функцію до діапазону елементів і зберігає ре­зультат у послідовності, яка задається параметром result. У першій формі діапазон задається параметрами start і end. Використовувана для перетворення функція за­дається параметром unaryfunc. Вона приймає значення елемента як параметр повер­тає перетворене значення. У другому форматі алгоритму перетворення здійсню­ється з використанням бінарної функції, яка приймає як перший параметр значен­ня, призначеного для перетворення елемента з послідовності, а як другий пара­метр - елемент з другої послідовності. Обидві версії повертають ітератор, який вказує на кінець остаточної послідовності.

У наведеному нижче коді програми використовується проста функція перет­ворення xformO, яка підносить до квадрату кожен елемент списку. Зверніть увагу на те, що остаточна послідовність зберігається у тому ж списку, який містив по­чаткову послідовність.

Код програми 12.16. Демонстрація механізму використання алгоритму transform()

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

#include <list> // Для роботи зі списками

#include <algorithm> // Для роботи з алгоритмами бібліотеки STL

using namespace std; // Використання стандартного простору імен

// Проста функція перетворення, int xform(int і) {

return і * і; // Квадрат початкового значення

}

int mainO

{

list<int> xList; inti;

// Поміщаємо значення у список. for(int і=0; і<10; І++) xList.push_back(i);

cout«"Початковий список xList:"; list<int>::iteratorp = xList.beginO; while(p != xList.endO) {

cout«*p «""; p++;

}

cout« endl;

// Перетворення списку xList.

p = transform(xList.beginO, xListendO, xList.beginO, xform);

cout«"Перетворений список xList:"; p = xList.beginO; while(p != xListendO) { cout«*p «""; p++;

}

getchO; return 0;

}

Внаслідок виконання ця програма відображає на екрані такі результати: Початковий список xList: 0123456789 Перетворений список xList: 0 1 4 9 16 25 36 49 64 81

Як бачите, кожен елемент у списку xList тепер зведено у квадрат.

Описані вище алгоритми є тільки малою частиною всього вмісту бібліотеки STL. Зазвичай Вам потрібно самим досліджувати інші алгоритми. Заслуговують уваги, наприклад, такі алгоритми, як set_unionO і set_difference(). Вони призначені для оброблення вмісту такого контейнера, як множина. Цікаві також алгоритми next_permutation() і prev_permutation(). Вони створюють наступну і попередню перес­тановки елементів заданої послідовності. Час, витрачений на вивчення алгоритмів бібліотеки STL, - це час, витрачений не дарма!

  1. Особливості використання об'єктів класу string

Як уже зазначалося вище, мова програмування C++ не підтримує вбудовано­го рядкованого типу. Проте він надає два способи оброблення рядків. По-перше, для представлення рядків можна використовувати традиційний символьний ма­сив, який завершується нулем. Рядки, що створюються у такий спосіб (Ви вже оз­найомлені з ним), іноді називають С-рядками. По-друге, можна використовувати об'єкти класу string, і саме цей спосіб ми зараз розглянемо.

Клас string забезпечує альтернативу для рядків, які мають завершаль­ний нуль-символ.

Насправді клас string є не чим іншим, як спеціалізація більш загального шаб­лонного класу basic_string. Існує дві спеціалізації типу basic_string: тип string, який підтримує 8-бітові символьні рядки, і тип wstring, який підтримує рядки, утворені двобайтовими символами. Найчастіше у звичайному програмуванні використову­ють рядкові об'єкти типу string. Для використання рядкових класів C++ необхідно приєднати до програми заголовок <string>.

  1. Клас string - частина С++-бібліотеки

Перед тим, як розглядати особливості роботи з класом string, важливо зрозу­міти, чому він є частиною С++-бібліотеки. Стандартні класи не відразу були дода­ні у визначення мови програмування C++. Насправді кожному нововведенню пе­редували серйозні дискусії та запеклі суперечки. При тому, що мова C++ вже міс­тить підтримку рядків у вигляді масивів, що завершуються нулем, внесення класу string у мову програмування C++, на перший погляд, може видатися винятком з цього правила. Але це далеко не так. І ось чому: рядки з завершальним нуль-сим- волом, не можна обробляти стандартними С++-операторами, і їх не можна вико­ристовувати у звичайних С++-виразах. Розглянемо, наприклад, такий фрагмент коду програми:

char s1 [80], s2[80], s3[80]; s1 = "один"; // так робити не можна s2 = "два"; // так робити не можна s3 = s1+s2; //Помилка

Як зазначено у коментарях до цього коду програми, у мові програмування C++ неможливо використовувати оператор присвоєння для надання символьному масиву нового значення (за винятком настанови ініціалізації), а також не можна застосовувати операцію додавання "+" для конкатенації двох рядків. Ці операції можна виконати за допомогою бібліотечних функцій. strcpy(s1, "один"); strcpy(s2, "два"); strcpy(s3, s1); strcpy(s3, s2);

Оскільки символьний масив, який завершується нулем, формально не є са­мостійним типом даних, то до нього не можна застосувати С++-оператори. Це по­збавляє "вишуканості" навіть найелементарніші операції з рядками. І саме нездат­ність обробляти рядки з завершальним нуль-символом, за допомогою стандартних С++-операторів привела до розроблення стандартного рядкового класу. Прига­дайте: створюючи клас у мові програмування C++, ми визначаємо новий тип да­них, який можна повністю інтегрувати у С++-середовигце. Це, звичайно ж, озна­чає, що для нового класу можна перевизначати оператори. Таким чином, вводячи в мову стандартний рядковий клас, ми створюємо можливість для оброблення ря­дків так само, як і даних будь-якого іншого типу, а саме за допомогою операторів.

Проте існує ще одна причина, яка реабілітує створення стандартного класу string: безпека. Руками недосвідченого або необережного програміста дуже легко забезпечити вихід за межі масиву, який містить рядок з завершальним нулем. Роз­глянемо, наприклад, стандартну функцію копіювання strcpy(). Ця функція не пе­редбачає механізм перевірки факту порушення меж масиву приймача. Якщо по­чатковий масив містить більше символів, ніж може прийняти масив приймач, то внаслідок цієї помилки дуже вірогідна повна відмова системи. Як буде показано далі, стандартний клас string не допускає виникнення подібних помилок

Отже, існує три причини для внесення у мову програмування C++ стандар­тного класу string: несуперечність даних (рядок тепер визначається самостійним типом даних), зручність (програміст може використовувати стандартні С++-опе- ратори) і безпечність (межі масивів відтепер не порушуватимуться). Необхідно мати на увазі, що все перераховане вище зовсім не означає, що програміст пови­нен відмовлятися від використання звичайних рядків, які мають завершальний нуль-символ. Вони, як і раніше, залишаються найбільш ефективним засобом ре­алізації рядків. Але, якщо швидкість виконання програми не є для Вас визначаль­ним фактором, то використання нового класу string дасть Вам доступ до безпечно­го і повністю інтегрованого способу оброблення рядків.

І хоча клас string традиційно не сприймається як частина бібліотеки STL, про­те він є ще одним контейнерним класом, який визначено у мові програмування C++. Це означає, що він підтримує алгоритми, описані у попередньому розділі. До того ж, рядки мають додаткові можливості. Для отримання доступу до класу string необхідно приєднати до програми заголовок <string>.

Клас string дуже великий, він містить багато конструкторів і функцій-членів. Окрім цього, багато функцій-членів класу мають декілька перевизначених форм. Оскільки в одному розділі неможливо розглянути весь вміст класу string, ми звер­ніть увагу тільки на найпопулярніших його засобах. Отримавши загальне уявлен­ня про роботу класу string, Ви зможете легко розібратися в інших його можливос­тях самі.

Прототипи трьох найпоширеніших конструкторів класу string мають такий вигляд: stringO;

string(constchar*sfr); string(const string &sfr);

Перша форма конструктора створює порожній об'єкт класу string. Друга фор­ма створює string-об'єкт з рядка, який завершується нульовим символом, який ад­ресується параметром str. Ця форма конструктора забезпечує перетворення рядка з завершальним нуль-символом на об'єкт типу string. Третя форма створює string- об'єкт з іншого string-об'єкта.

Оператор

Опис

=

Присвоєння

+

Конкатенація

+=

Присвоєння з конкатенацією

==

Рівність

! =

Нерівність

<

Менше

<=

Менше або дорівнює

>

Більше

>=

Більше або дорівнює

Індексація

«

Введення

»

Виведення

Ці оператори дають змогу використовувати об'єкти типу string у звичайних виразах і позбавляють програміста потреби викликати такі функції, як strcpyO або strcpy(). У загальному випадку у виразах можна змішувати string-об'єкти і рядки з завершальним нуль-символом. Наприклад, string-об'єкт можна присвоїти рядку, що завершується нулем.

Оператор додавання "+" можна використовувати для конкатенації одного string-об'єкта з іншим або string-об'єкта з рядком, створеним у С-стилі (С-рядком). Іншими словами, підтримуються такі операції: string-об'єкг + string-об'єкт string-об'єкт + С-рядок С-рядок + string-об'єкт

Оператор додавання "+" дає змогу також додавати символ у кінець рядка.

У класі string визначено константу npos, яка дорівнює -1. Вона представляє розмір рядка максимально можливої довжини.

Рядковий клас у мові програмування C++ істотно полегшує оброблення ряд­ків. Наприклад, використовуючи string-об'єкти, можна застосовувати оператор присвоєння для призначення string-об'єкту рядка в лапках, оператор конкатенації "+" - для конкатенації рядків і оператори порівняння - для порівняння рядків. Ви­конання цих операцій продемонстровано у наведеному нижче коді програми.

Код програми 12.17. Демонстрація механізму використання класу string для оброблення рядків

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

#include <string> // Для роботи з рядковими типами

using namespace std; // Використання стандартного простору імен

int mainO

{

string strl ("Клас string дає змогу ефективно"); string str2 ("обробляти рядки.");

string str3;

// Присвоєння string-об'єкта str3 = strl;

cout« strl « endl« str3 « endl;

// Конкатенація двох string-об'єктів. str3 = strl + str2; cout« str3 « endl;

// Порівняння string-об'єктів.

if(str3 > strl) cout "str3 ^ strl" endl;

if(str3 == strl + str2)

cout«"str3 == strl + str2"« endl;

// Об'єкту класу string можна також присвоїти звичайний рядок, strl = "Це рядок, який завершується нульовим символом"« endl; cout« strl;

// Створення string-об'єкта за допомогою іншого string-об'єкта, string str4(str1); cout« str4;

// Введення рядка.

cout«"Введіть рядок:"; сіп » str4;

cout« str4;

getchO; return 0;

}

Внаслідок виконання ця програма відображає на екрані такі результати:

Клас string дає змогу ефективно

Клас string дає змогу ефективно

Клас string дає змогу ефективно обробляти рядки.

str3 > strl

str3 == strl + str2

Це рядок, який завершується нульовим символом.

Це рядок, який завершується нульовим символом.

Введіть рядок: Привіт Привіт

Зверніть увагу на те, як легко тепер здійснюється оброблення рядків. Наприк­лад, оператор конкатенації "+" використовує для конкатенації рядків, а оператор ">" - для порівняння двох рядків. Для виконання цих операцій з використанням С-стилю оброблення рядків, тобто використання рядків, що мають завершальний нуль-символ, довелося б застосовувати менш зручні засоби, а саме викликати фу­нкції streat() і strcmp(). Оскільки С++-об'єкти типу string можна вільно змішувати з С-рядками, то їх (string-об'єкти) можна використовувати в будь-якій програмі не тільки без жодних втрат для ефективності її роботи, але навіть з помітним вигра­шем.

Важливо також відзначити, що у попередній програмі розмір рядків не за­дається. Об'єкти типу string автоматично отримують розмір, потрібний для збері­гання заданого рядка. Таким чином, у процесі виконання операцій присвоєння або конкатенації рядків рядок-прнймач збільшиться у довжину настільки, наскільки це необхідно для зберігання нового вмісту рядка. Під час оброблення string- об'єктів неможливо вийти за межі рядка. Саме цей динамічний аспект string- об'єктів вигідно відрізняє їх від рядків, що мають завершальний нуль-символ (які часто страждають від порушення меж).

  1. Огляд функцій-членів класу string

Якщо найпростіші операції з рядками можна реалізувати за допомогою опе­раторів, то у процесі виконання дещо складніших операцій не можливо обійтися без функцій-членів класу string. Клас string містить дуже багато функцій-членів, ми ж розглянемо тут тільки найпоширеніші з поміж них.

Нео! хідноапам ятати'.аОскільки клас String- контейнер, він підтримує та­кі звичайні контейнерні функції, як begin(), end() і sizeQ.

Основні маніпуляції над рядками. Щоб присвоїти один рядок іншому, най­частіше використовують функцію assign(). Ось як виглядають два можливі форма­ти її реалізації:

string &assign(const string &strob, size_type start sizetype num)]

string &assign(const char *str. size_type num);

Перший формат дає змогу присвоїти викликуваному об'єкту пит символів з рядка, який задано параметром strob, починаючи з індексу start. Під час викорис­тання другого формату викликуваного об'єкта присвоюються перші пит символів рядка, який завершується нульовим символом, які задаються параметром sfr. У кожному випадку повертається посилання на викликуваний об'єкт. Звичайно, на­багато простіше для присвоєння одного повного рядка іншому використовувати оператор присвоєння Про функцію-члена assign() згадують, в основному, тоді, коли потрібно присвоїти тільки частину рядка.

За допомогою функції-члена класу append() можна частину одного рядка при­єднати до кінця іншого. Два можливі формати її реалізації мають такий вигляд:

string &append(const string &strob. size_type start size_type num)]

string &append(const char*sfr, size_type num)]

У цих записах при використанні першого формату пит символів з рядка, який задано параметром strob, починаючи з індексу start, буде приєднано до кінця викли­куваного об'єкта. Другий формат дає змогу приєднати до кінця викликуваного об'єкта, перші пит символів рядка, який завершується нульовим символом, який задається параметром sfr. У кожному випадку повертається посилання на виклику­ваний об'єкт. Звичайно, набагато простіше для приєднання одного повного рядка до кінця іншого використовувати оператор конкатенації "+". Функція ж append() застосовується тоді, коли необхідно приєднати до кінця викликуваного об'єкта, тільки частину рядка.

Вставлення або заміну символів у рядку можна виконувати за допомогою функцій-членів класу insert() і replace(). Ось як виглядають прототипи їх найбільш використовуваних форматів:

string &insert(size_type start, const string &sfrob);

string &insert(size_type start, const string &strob, size_type insStart, size_type num);

string &replace(size_type start, size_type num, const string &sfrob);

string &replace(size_type start, size_type orgNum, const string &strob, size_type replaceStart, size_type replaceNum)',

Перший формат функції insert() дає змогу вставити рядок, який задається па­раметром strob, у позицію викликуваного рядка, який задано параметром start. Дру­гий формат функції insert() призначений для вставлення пит символів з рядка, який задано параметром strob, починаючи з індексу insStart, у позицію викликуваного рядка, який задано параметром start.

Перший формат функції replaceO слугує для заміни пит символів у викликува­ному рядку, починаючи з індексу start, рядком, який задано параметром strob. Дру­гий формат дає змогу замінити orgNum символів у викликуваному рядку, почина­ючи з індексу start, replaceNum символами рядка, який задано параметром strob, по­чинаючи з індексу replaceStart. У кожному випадку повертається посилання на вик­ликуваний об'єкт.

Видалити символи з рядка можна за допомогою функції erase(). Один з її фор­матів має такий вигляд:

string &erase(size_type start = 0 size_type num = npos);

Ця функція видаляє num символів із викликуваного рядка, починаючи з індек­су start. Функція повертає посилання на викликуваний об'єкт.

Використання функцій insertO, eraseO і replace() продемонстровано у наведено­му нижче коді програми.

Код програми 12.18. Демонстрація механізму використання функцій insert(), eraseQ і replaceO

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

#include <string> // Для роботи з рядковими типами

using namespace std; // Використання стандартного простору імен

int mainO

{

string strl ("Це простий тест.");

string str2 С'ABC D EF G");

cout«"Початкові рядки:"« endl;

cout«"strl:"« strl « endl;

cout«"str2:"« str2 « endl« endl;

// Демонструємо механізм використання функції insertO- cout«"Вставляємо рядок str2 у рядок strl:"« endl; strl insert(5, str2); cout« strl « endl« endl;

// Демонструємо механізм використання функції eraseQ.

cout«"Видаляємо 7 символів з рядка strl« endl;

strl ,erase(5,7);

cout« strl «endl« endl;

// Демонструємо механізм використання функції replaceO- cout«"Замінюємо 2 символи в strl рядком str2:"« endl; strl replace(5,2, str2); cout« strl « endl;

getchO; return 0;

}

Внаслідок виконання ця програма відображає на екрані такі результати: Початкові рядки: strl: Це простий тест. str2: ABCDEFG

Вставляємо рядок str2 у рядок strl:

Це пАВСОЕРСростий тест.

Видаляємо 7 символів з рядка strl:

Це простий тест.

Замінюємо 2 символи в strl рядком str2:

Це пАВСОЕРСстий тест.

Пошук у рядку. У класі string передбачено декілька функцій-членів класу, які здійснюють пошук. Це, наприклад, такі функції, як find() і rfind(). Розглянемо прототипи найбільш використовуваних версій цих функцій: size_type find(const string &strob, size_type start = 0) const;

size_type rfind(const string &strob, size_type start = npos) const;

Функція findO, починаючи з позиції start, проглядає викликуваний рядок на предмет пошуку першого входження рядка, який задано параметром strob. Якщо пошук відбувся успішно, то функція findO повертає індекс, за яким у викликувано­му рядку було виявлено збіг. Якщо збігу не виявлено, то повертається значення npos. Функція rfindO здійснює ту ж саму дію, але з кінця. Починаючи з позиції start, вона проглядає викликуваний рядок у зворотному порядку на предмет пошуку першого входження рядка, який задано параметром strob (тобто вона знаходить у викликуваному рядку останнє входження рядка, який задано параметром strob). Якщо пошук відбувся вдало, то функція findO повертає індекс, за яким у виклику­ваному рядку був виявлений збіг. Якщо збігу не виявлено, то повертається зна­чення npos.

Розглянемо короткий приклад використання функції findO-

Код програми 12.19. Демонстрація механізму використання функції find()

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

#include <string> // Для роботи з рядковими типами

using namespace std; // Використання стандартного простору імен

int mainO

{

int c;

string s1 = "Клас string полегшує оброблення рядків.";

string s2;

c = s1 findf string");

if(c != string::npos) {

cout«"Збіг виявлений у позиції"« с « endl; cout«"Залишок рядка такий:"; s2.assign(s1, с, s1 .sizeO); cout« s2;

}

getchO; return 0;

}

Внаслідок виконання ця програма відображає на екрані такі результати:

Збіг виявлений у позиції 6

Залишок рядка такий: string полегшує оброблення рядків.

Порівняння рядків. Щоб порівняти повний вміст одного string-об'єкта з ін­шим, зазвичай використовуються описані вище перевизначені оператори відно­шення. Але, якщо потрібно порівняти частину одного рядка з іншим, Вам дове­деться використовувати функцію-члена compare():

int compare(size_type start sizejype num, const string &strob) const;

Функція compare() порівнює із викликуваним рядком пит символів рядка, який за­дано параметром strob, починаючи з індексу start. Якщо викликуваний рядок мен­ший від рядка strob, то функція compare() поверне негативне значення. Якщо викли­куваний рядок більший від рядка strob, то вона поверне позитивне значення. Якщо рядок strob дорівнює викликуваному рядку, то функція compare() поверне нуль.

Отримання рядка, який завершується нульовим символом. Незважаючи на незаперечну корисність об'єктів типу string, можливі ситуації, коли Вам дове­деться отримувати з такого об'єкта символьний масив, який завершується нулем, тобто його версію С-рядка. Наприклад, Ви могли б використовувати string-об'єкт для створення імені файлу. Але, відкриваючи файл, Вам потрібно задати покаж­чик на стандартний рядок, який завершується нульовим символом. Для вирішення цього питання і використовується функція-член c_str(). Її прототип має такий ви­гляд:

const char*c_str() const;

Ця функція повертає покажчик на С-версію рядка (тобто на рядок, який завер­шується нульовим символом), який міститься у викликуваному об'єкті типу string. Отриманий рядок, який завершується нульовим символом, зміні не підлягає. Ок­рім цього, після виконання інших операцій над цим string-об'єктом допустимість застосування отриманого С-рядка не гарантується.

  1. Зберігання рядків у інших контейнерах

Оскільки клас string визначає тип даних, то можна створити контейнери, які міститимуть об'єкти типу string. Розглянемо, наприклад, вдаліший варіант програ- ми-словника, яку було показано вище.

Код програми 12.20. Демонстрація механізму використання відображення string-об'єктів для створення словника

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

#include <map> // Для роботи з асоціативними контейнерами

#include <string> // Для роботи з рядковими типами

using namespace std; // Використання стандартного простору імен