Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Тема8.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
252.93 Кб
Скачать

Приклади, які використовують вектори символів

У попередньому прикладі були використані прості рядки з покажчиком типу char*, які є просто масивами символів. Властивістю всіх параметричних алгоритмів STL є їх застосування до масивів, але оскільки масиви є порівняно слабким засобом С/С++, будуватимемо подальші приклади, використовуючи переважно один із контейнерів послідовностей, поданих STL, наприклад вектор. Вектори мають всі стандартні властивості масивів, але додатково мають багато інших корисних властивостей, які буде розглянуто далі. Отже, найтиповіший приклад використання функції reverse має вигляд:

#include <iostream.h>

#include <algo.h>

#include <vector.h>

#include <assert.h>

vector <char> vec(char* s)

//перетворює рядок s до структури vector <char>

//(завершуючий рядок порожній символ у струк-

//туру не включається).

{

vector <char> x;

while (*s!=`\0’)

x.push_back(*s++);

return X;

}

int main ()

{

cout <<«Using reverse algorithm with a vector.»<<end1;

vector < char > vector1 = vec («mark twain»);

reverse (vector1.begin (),vector1.end ());

assert (strcmp (vector1, «niawt kram») == 0);

};

У цій програмі визначена допоміжна функція vec, яка перетворює масив символів на vector <char>. Функція робить це за допомогою функції-члена pash-back, щоб перенести черговий символ рядка у вектор. Розмір пам’яті, займаної вектором, збільшується в міру того, як символи надходять до нього; автоматичне виділення пам’яті є однією з переваг векторів (та взагалі всіх контейнерів STL) над масивами. У програмі для конструювання рядка використовується функція vec, а також функція reverse того рядка, з яким зрівнюється результат. При виклику функції reverse використовуються функ­ції — члени класу vector begin та end. При цьому прийнято погодження, що кінцевою позицією є перша позиція, наступна за останньою, зайнятою змістом вектора.

Для зрівняння результату функції reverse з vec («mark twain») використовується операція = =, оскільки у STL визначена така операція для перевірки рівності векторів. Взагалі у STL визначена операція = = для всіх контейнерних класів.

Приклади, які містять типи, визначені користувачем

Слід мати на увазі, що контейнери STL можуть використовуватися не лише для символів, а й для об’єктів вільного типу. Можна використовувати вільний тип U, визначений користувачем як клас чи структура, хоч при цьому можуть бути доступні не всі операції у класі U. Зокрема, багато контейнерних операцій та параметричних алгоритмів потребують від типу U, щоб у ньому була визначена операція = = як операція рівності. У наступному прикладі наведено клас U з мінімальними властивостями (ми називатимемо його мінімальним типом чи мінімальним класом):

#include <iostream.h>

#include <algo.h>

#include <vector.h>

#include <assert.h>

class U {

public:

insigned long id;

U(): id(0) { }

U(insigned long x): id(x) { }

};

//Визначення операції == для об’єктів класу U ( воно не-

//обхідне для операції == векторів.

Bool operator==(const U& x,const U& y)

{

return x.id == y.id;

}

int main()

{

vector<U> vector1, vector2;

const int N = 1000;

for(int k=0; k!=N1; ++k) vector1.push_back(U(k));

for(k=0; k!=N1; ++k) vector2.push_back(U(N1-1-k));

cout <<«Using generic reverse algorithm with a»

<<«vector of user-defined objects» <<end1;

reverse (vector1.begin(),vector1.end());

assert(vector1 == vector2);

};

У прикладі клас U має data-член id. Конструктори забезпечують породження об’єкта з довільним конкретним id. Наявність такого ідентифікованого члена в класі, звичайно, необов’язкове, але він використовується тут як зручний засіб ідентифікації об’єктів розглядуваного класу.

Алгоритм reverse не використовує операцію = = для об’єктів класу U, але вона має бути визначена для пар об’єктів класу U як рівність їх data-членів id, щоб можна було перевірити рівність двох векторів. Адже операція = = визначена для векторів лише в тому разі, коли вона визначена для об’єктів, розміщених усередині векторів.

Для кількох функцій — членів чи параметричних алгоритмів, насамперед для сортування або злиття, потрібна ще одна операція, <, визначена для об’єктів, розміщених всередині контейнерів. Ця операція визначається аналогічно операції = =:

bool operator == (const U& x, const U& y)

{

return x.id == y.id;

}

Після того як операція < визначена для об’єктів, розміщених усередині контейнера, вона стає визначеною для контейнерних об’єктів (точніше, стають доступними відповідні операції, ви- значені в контейнерних класах. Іноді буває корисно додати й операцію

ostream& operator « (ostream& o, const U& x)

{

o << x.id

return o

}

яка видає номер id об’єкта U.

Наведені приклади показують загальний характер параметричних алгоритмів та контейнерних операцій STL. Зазначимо, що можливі й більш складні застосування контейнерів. Можна, наприклад, розміщувати одні контейнери в інших, що дає можливість визначити, наприклад, вектори списків цілих значень:

vector<list<int>> vector1, vector2;