КАТЕГОРИИ: Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748) |
Namespace CounterNameSpace 4 страница. Результати виконання цієї програми є такими:
getch (); return 0; } Результати виконання цієї програми є такими: Розмір = 0 Новий розмір = 10 Поточний вміст: 0 1 2 3 4 5 6 7 8 9 Новий розмір =20 Новий вміст: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Вміст подвоєно: 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 Розглянемо уважно код цієї програми. У функції main () створюється вектор vek для зберігання int -елементів. Оскільки під час його створення не було передбачено ніякої ініціалізації, то вектор vek вийшов порожнім, а його місткість дорівнює нулю. Іншими словами, ми створили вектор нульової довжини. Це підтверджується викликом функції-члена класу size (). Потім, використовуючи функцію-члена push_back (), у кінець цього вектора ми поміщаємо 10 елементів, що примушує вектор збільшитися в розмірі, щоб розмістити нові елементи. Тепер розмір вектора став таким, що дорівнює 10. Звернемо Вашу увагу на те, що для відображення вмісту вектора vek використовується стандартний запис індексації масивів. Після цього у вектор додаються ще 10 елементів, і вектор vek автоматично збільшується в розмірі, щоб і їх прийняти на зберігання. Нарешті, використовуючи знову-таки стандартний запис індексації масивів, ми змінюємо значення елементів вектора vek. Зверніть також увагу на те, що для керування циклами, які використовуються для відображення вмісту вектора vek і його модифікації, як ознака їх завершення застосовується значення розміру вектора, що отримується за допомогою функції vek. size (). Одна з переваг векторів перед масивами полягає у тому, що у нас є змога дізнатися поточний розмір вектора, який у певних ситуаціях є дуже корисним засобом. 22.3.1. Доступ до вектора за допомогою ітератора Як уже зазначалося вище, масиви і покажчики у мові програмування C++ тісно пов'язані між собою. До елементів масиву можна отримати доступ як за допомогою індексу, так і за допомогою покажчика. У бібліотеці STL аналогічний зв'язок існує між векторами й ітераторами. Це означає, що до членів вектора можна звертатися як за допомогою індексу, так і за допомогою ітератора. Цю можливість продемонстровано у наведеному нижче коді програми.
Код програми 22.2. Демонстрація механізму доступу до вектора за допомогою ітератора #include <iostream> // Для потокового введення-виведення #include <vector> // Для роботи контейнерним класом "Вектор" using namespace std; // Використання стандартного простору імен
int main () { vector < char > vek; // Побудова вектора нульової довжини int i;
// Поміщаємо значення у вектор. for (i=0; i<10; i++) vek. push_back ('A' + i);
// Отримуємо доступ до вмісту вектора за допомогою індексу. for (i=0; i<10; i++) cout << vek[i] << " "; cout << endl;
// Отримуємо доступ до вмісту вектора за допомогою ітератора. vector < char >:: iterator p = vek. begin (); while (p!= vek .end ()) { cout << *p << " "; p++; }
getch (); return 0; } Ось як виглядають результати виконання цієї програми: ABCDEFGHIJ ABCDEFGHIJ У цій програмі спочатку створюється вектор нульової довжини. Потім за допомогою функції push_back () у кінець вектора поміщаються символи, внаслідок чого розмір вектора відповідним чином збільшується. Звернемо Вашу увагу на те, як оголошується ітератор р. Тип цього ітератора визначається контейнерними класами. Тому для отримання ітератора для конкретного контейнера використовуйте оголошення, аналогічне показаному у цьому прикладі: просто вкажіть для цього ітератора ім'я контейнера. У нашій програмі ітератор р ініціалізувався так, щоб він указував на початок вектора (за допомогою функції-члена класу begin ()). Ітератор, який повертає ця функція, можна потім використовувати для поелементного доступу до вектора, інкрементуючи його відповідним чином. Цей процес аналогічний тому, як можна використовувати покажчик для доступу до елементів масиву. Щоб визначити, коли буде досягнуто кінець вектора, використовується функція-член end (). Ця функція повертає ітератор, встановлено за останнім елементом вектора. Тому, якщо значення р дорівнює vek .end (), то кінець вектора досягнуто.
22.3.2. Вставлення та видалення елементів з вектора Окрім занесення нових елементів у кінець вектора, у нас є можливість вставляти елементи у середину вектора, використовуючи функцію insert (). Видаляти елементи можна за допомогою функції erase (). Використання функцій insert () і erase () продемонстровано у наведеному нижче коді програми. Код програми 22.3. Демонстрація механізму вставлення елементів у вектор і видалення їх з нього #include <iostream> // Для потокового введення-виведення #include <vector> // Для роботи контейнерним класом "Вектор" using namespace std; // Використання стандартного простору імен
int main () { vector < char > vek; // Побудова вектора нульової довжини unsigned int i; // Поміщаємо значення у вектор. for (i=0; i<10; i++) vek. push_back ('A' + i);
// Відображаємо початковий вміст вектора. cout << "Розмір = " << vek. size () << endl; cout << "Початковий вміст вектора:\n"; for (i=0; i<vek. size (); i++) cout << vek[i] << " "; cout << endl; // Отримуємо доступ до вмісту вектора за допомогою ітератора. vector < char >:: iterator p = vek. begin (); p += 2; // Покажчик на 3-й елемент вектора
// Вставляємо 10 символів 'x' у вектор vek. vek. insert (p, 10, 'x');
// Відображаємо вміст вектора після вставки символів. cout << "Розмір вектора після вставки = " << vek. size () << endl; cout << "Вміст вектора після вставки:\n"; for (i=0; i<vek. size (); i++) cout << vek[i] << " "; cout << endl;
// Видалення вміщених елементів. p = vek. begin (); p += 2; // Покажчик на 3-й елемент вектора vek. erase (p, p+10); // Видаляємо 10 елементів підряд.
// Відображаємо вміст вектора після видалення символів. cout << "Розмір вектора після видалення символів = " << vek. size () << endl; cout << "Вміст вектора після видалення символів:\n"; for (i=0; i<vek.sized; i++) cout << vek[i] << " "; cout << endl;
getch (); return 0; } У процесі виконання ця програма відображає такі результати: Розмір = 10 Початковий вміст вектора: A B C D E F G H I J
Розмір вектора після вставки = 20
Вміст вектора після вставки: A B x x x x x x x x x x C D E F G H I J
Розмір вектора після видалення символів = 10 Вміст вектора після видалення символів: A B C D E F G H I J 22.3.3. Збереження у векторі об'єктів класу У попередніх прикладах вектори слугували для зберігання значень тільки вбудованих типів, але цим їх можливості не обмежуються. У вектор можна поміщати об'єкти будь-якого типу, в т.ч. об'єкти класів, що створюються програмістом. Розглянемо приклад, у якому вектор використовують для зберігання об'єктів класу kooClass. Звернемо Вашу увагу на те, що у цьому класі визначаються конструктор за замовчуванням і перевантажені версії операторів "<" і "==". Майте на увазі, що, можливо, Вам доведеться визначити і інші оператори порівняння. Це залежить від того, як використовуваний Вами компілятор реалізує бібліотеку STL. Код програми 22.4. Демонстрація механізму зберігання у векторі об'єктів класу #include <vcl> #include <iostream> // Для потокового введення-виведення #include <conio> // Для консольного режиму роботи #include <vector> // Для роботи контейнерним класом "Вектор" using namespace std; // Використання стандартного простору імен class kooClass { // Оголошення класового типу int x, y, z; // Тривимірні координати public: kooClass() {x = y = z = 0;} kooClass(int a, int b, int c) {x = a; y = b; z = c;} // Повертає модифікований об'єкт, адресований покажчиком kooClass & operator +(int a) { x += a; y += a; z += a; return * this;} friend ostream & operator <<(ostream & stream, kooClass obj); friend bool operator <(kooClass a_ob, kooClass b_ob); friend bool operator ==(kooClass a_ob, kooClass b_ob); }; // Відображаємо координати x, y, z за допомогою оператора // виведення для класу kooClass. ostream & operator <<(ostream & stream, kooClass obj) { stream << "x= " << obj.x << ", "; stream << "y= " << obj.y << ", "; stream << "z= " << obj.z << "\n"; return stream; // Повертає посилання на параметр stream }
bool operator <(kooClass a_ob, kooClass b_ob) { return (a_ob.x + a_ob.y + a_ob.z) < (b_ob.x + b_ob.y + b_ob.z); }
bool operator ==(kooClass a_ob, kooClass b_ob) { return (a_ob.x + a_ob.y + a_ob.z) == (b_ob.x + b_ob.y + b_ob.z); }
int main () { vector <kooClass> vek; // Побудова вектора об'єктів нульової довжини unsigned int i;
// Додаємо у вектор об'єкти.
for (i=0; i<10; i++) vek. push_back (kooClass(i, i+2, i-3));
cout << "Відображаємо вміст початкового вектора.\n"; for (i=0; i<vek. size (); i++) cout << i << " ==> " << vek[i]; cout << endl;
// Модифікуємо об'єкти у векторі. for (i=0; i<vek. size (); i++) vek[i] = vek[i] + 10;
cout << "Відображаємо вміст модифікованого вектора.\n"; for (i=0; i<vek. size (); i++) cout << i << " ==> " << vek[i];
getch (); return 0; } Внаслідок виконання цієї програми на моніторі буде відображено такі результати: Відображаємо вміст початкового вектора. 0 ==> x= 0, y= 2, z= -3 1 ==> x= 1, y= 3, z= -2 2 ==> x= 2, y= 4, z= -1 3 ==> x= 3, y= 5, z= 0 4 ==> x= 4, y= 6, z= 1 5 ==> x= 5, y= 7, z= 2 6 ==> x= 6, y= 8, z= 3 7 ==> x= 7, y= 9, z= 4 8 ==> x= 8, y= 10, z= 5 9 ==> x= 9, y= 11, z= 6
Відображаємо вміст модифікованого вектора. 0 ==> x= 10, y= 12, z= 7 1 ==> x= 11, y= 13, z= 8 2 ==> x= 12, y= 14, z= 9 3 ==> x= 13, y= 15, z= 10 4 ==> x= 14, y= 16, z= 11 5 ==> x= 15, y= 17, z= 12 6 ==> x= 16, y= 18, z= 13 7 ==> x= 17, y= 19, z= 14 8 ==> x= 18, y= 20, z= 15 9 ==> x= 19, y= 21, z= 16 Вектори забезпечують безпеку зберігання елементів, виявляючи при цьому надзвичайну потужність і гнучкість їх оброблення, але поступаються масивам у ефективності використання. Тому для більшості задач програмування частіше надається перевага звичайним масивам. Проте можливі ситуації, коли унікальні особливості векторів виявляються важливішими за витрати системних ресурсів, пов'язаних з їх використанням. 22.3.4. Доцільність використання ітераторів Частково потужність бібліотеки STL зумовлена тим, що багато її функцій використовують ітератори. Цей факт дає змогу виконувати операції з двома контейнерами одночасно. Розглянемо, наприклад, такий формат векторної функції insert (). template < class InIter > void insert (iterator i, InIter start, InIter end); Ця функція вставляє початкову послідовність, що визначається параметрами start і end, уприймальну послідовність, починаючи з позиції i. При цьому немає ніяких вимог, щоб ітератор i належав тому ж вектору, з яким пов'язані ітератори start і end. Таким чином, використовуючи цю версію функції insert (), можна один вектор вставити в іншій. Розглянемо такий приклад. Код програми 22.5. Демонстрація механізму використання ітераторів для вставлення одного вектора у іншій #include <iostream> // Для потокового введення-виведення #include <vector> // Для роботи контейнерним класом "Вектор" using namespace std; // Використання стандартного простору імен
int main () { vector < char > vek, vek2; // Побудова векторів нульової довжини unsigned int i; // Поміщаємо значення у вектор. for (i=0; i<10; i++) vek. push_back ('A' + i);
// Відображаємо початковий вміст вектора. cout << "Початковий вміст вектора:\n"; for (i=0; i<vek. size (); i++) cout << vek[i] << " "; cout << endl << endl;
// Ініціалізуємо другий вектор. char str[] = "-STL –– це сила!-"; for (i=0; str[i]; i++) vek2. push_back (str[i]);
/* Отримуємо ітератори для середини вектора vek, а також початку і кінця вектора vek2. */ vector < char >:: iterator p = vek. begin ()+5; vector < char >:: iterator p2start = vek2. begin (); vector < char >:: iterator p2end = vek2 .end ();
// Вставляємо вектор vek2 у вектор vek. vek. insert (p, p2.start, p2 .end);
// Відображаємо результат вставки. cout << "Вміст вектора vek після вставки:\n"; for (i=0; i<vek. size (); i++) cout << vek[i] << " "; cout << endl; getch (); return 0; } У процесі виконання ця програма відображає такі результати: Початковий вміст вектора: A B C D E F G H I J
Вміст вектора vek після вставки: A B C D E – S T L - - ц е c и л а! – F G Н I J Як бачите, вміст вектора vek2 поміщено у середину вектора vek. У міру подальшого вивчення можливостей, що надаються STL, можна дізнатися, що| ітератори є зв'язними засобами, які роблять бібліотеку єдиним цілим. Вони дають змогу виконувати дії з двома (і більше) об'єктами STL одночасно, але особливо корисні під час використання алгоритмів, описаних нижче у цьому розділі. 22.4. Робота зі списками Клас list підтримує функціонування двоспрямованого лінійного списку. На відміну від вектора, у якому реалізовано підтримку довільного доступу, список дає змогу отримувати до своїх елементів тільки послідовний доступ. Двоспрямованість списку означає, що доступ до його елементів можливий у двох напрямах: від початку до кінця і від кінця до початку. Список – це контейнер з двоспрямованим послідовним доступом до його елементів. Шаблонна специфікація класу list має такий вигляд. template < class myType, class Allocator = allocator <myType> class list У цьому записі myType – тип даних, що зберігаються у списку, а елемент Allocator означає розподільник пам'яті, який за замовчуванням використовує стандартний розподільник. У класі list визначено такі конструктори: explicit list (const Allocator & a = Allocator ()); explicit list (size_type num|, const myType &val = myType (), const Allocator & a = Allocator ()); list (const list <myType, Allocator > & ob); template < class InIter > list (InIter start, InIter end, const Allocator & a = Allocator ()); Конструктор, який представлено у першій формі, створює порожній список. Друга форма призначена для створення списку, який містить num елементів із значенням val. Третястворює список, який містить ті самі елементи, що і об'єкт ob. Четвертастворює список, який містить елементи у діапазоні, заданому параметрами start і end. Для класу list визначено такі оператори порівняння: ==, <, <=,!=, > і >=. 22.4.1. Використання базових операцій для роботи зі списком Функції-члени, визначені у класі list, подано у табл. 22.3. У кінець списку, як і у кінець вектора, елементи можна поміщати за допомогою функції push_back (), але за допомогою функції push_front () можна поміщати елементи у початок списку. Елемент можна також вставити і у середину списку, для цього використовується функція insert (). Один список можна помістити в інший, використовуючи функцію splice (). A за допомогою функції merge () два списки можна об'єднати і упорядкувати результат. Табл. 22.3. Функції-члени класу list
Щоб досягти максимальної гнучкості і переносності для будь-якого об'єкта, який підлягає зберіганню у списку, необхідно визначити конструктор за замовчуванням і оператор "<" (і бажано інші оператори порівняння). Точніші вимоги до об'єкта (як до потенційного елемента списку) необхідно погоджувати відповідно до документації на використовуваний Вами компілятор. Розглянемо простий приклад використання списку. Код програми 22.6. Демонстрація механізму використання базових операцій для роботи зі списком #include <iostream> // Для потокового введення-виведення #include <list> // Для роботи зі списками using namespace std; // Використання стандартного простору імен
int main () { list < char > lst; // Створення порожнього списку int i;
// Поміщаємо значення у список for (i=0; i<10; i++) lst. push_back ('A1+i);
// Відображаємо початковий розміру списку cout << "Розмір = " << lst. size () << endl;
// Відображаємо початковий вміст списку cout << "Вміст: "; list < char >:: iterator p = lst. begin (); // Отримуємо доступ до вмісту списку за допомогою ітератора. while (p!= lst .end ()) { cout << *p << " "; p++; } cout << endl;
getch (); return 0; } Результати виконання цієї програми є такі: Розмір = 10 Вміст: A B C D E F G H I J У процесі виконання ця програма створює список символів. Спочатку створюється порожній об'єкт списку. Потім у нього поміщається десять букв (від А до J). Заповнення списку реалізується шляхом використання функції push_back (), яка поміщає кожне нове значення у кінець наявного списку. Після цього відображається розмір списку і його вміст. Вміст списку виводиться на екран внаслідок виконання такого коду програми:
Дата добавления: 2014-11-29; Просмотров: 382; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |