Введение
В этом лабораторном занятии вы узнаете, как использовать различные компоненты Стандартной Шаблонной Библиотеки (Standard Template Library, STL) языка C++ для создания и управления структурами данных, такими как векторы (vectors), списки (lists), ассоциативные массивы (maps), множества (sets) и другие. Вы изучите базовые операции с этими контейнерами STL, включая добавление, удаление и перебор элементов. Кроме того, вы узнаете, как использовать алгоритмы STL для сортировки, поиска и обработки данных в этих контейнерах. По завершении этого лабораторного занятия вы получите твердое понимание того, как использовать мощь и гибкость STL языка C++ для создания эффективных и надежных приложений.
Создание и управление контейнером vector
На этом этапе вы узнаете о контейнере vector из Стандартной Шаблонной Библиотеки (Standard Template Library, STL) языка C++. Это динамический массив, размер которого может увеличиваться и уменьшаться. Векторы (vectors) чрезвычайно полезны для хранения и управления коллекциями элементов.
Сначала откройте WebIDE и создайте новый файл с именем vector_demo.cpp в директории ~/project. Мы пошагово изучим базовые операции с векторами.
touch ~/project/vector_demo.cpp
Добавьте следующий код в файл vector_demo.cpp:
#include <iostream>
#include <vector>
int main() {
// Create an empty vector of integers
std::vector<int> numbers;
// Add elements to the vector using push_back()
numbers.push_back(10);
numbers.push_back(20);
numbers.push_back(30);
// Print the size of the vector
std::cout << "Vector size: " << numbers.size() << std::endl;
// Access elements using index
std::cout << "First element: " << numbers[0] << std::endl;
std::cout << "Second element: " << numbers[1] << std::endl;
// Iterate through the vector using a range-based for loop
std::cout << "All elements: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// Remove the last element
numbers.pop_back();
// Check the new size after removing an element
std::cout << "Vector size after pop_back(): " << numbers.size() << std::endl;
return 0;
}
Скомпилируйте и запустите программу:
g++ vector_demo.cpp -o vector_demo
./vector_demo
Пример вывода:
Vector size: 3
First element: 10
Second element: 20
All elements: 10 20 30
Vector size after pop_back(): 2
Основные моменты о векторах:
- Используйте
#include <vector>для включения библиотеки векторов std::vector<type>создает вектор определенного типаpush_back()добавляет элементы в конец вектораsize()возвращает количество элементов- Обращайтесь к элементам с помощью индекса
[] pop_back()удаляет последний элемент- Цикл for на основе диапазона (range-based for loop) - простой способ перебрать элементы вектора
Использование контейнера list для операций с связным списком
На этом этапе вы узнаете о контейнере list из Стандартной Шаблонной Библиотеки (STL) языка C++, который реализует двусвязный список (doubly - linked list). Списки (lists) обеспечивают эффективные операции вставки и удаления элементов в любом положении контейнера.
Откройте WebIDE и создайте новый файл с именем list_demo.cpp в директории ~/project:
touch ~/project/list_demo.cpp
Добавьте следующий код в файл list_demo.cpp:
#include <iostream>
#include <list>
int main() {
// Create an empty list of integers
std::list<int> numbers;
// Add elements to the list
numbers.push_back(10); // Add to the end
numbers.push_front(5); // Add to the beginning
numbers.push_back(20);
// Print the list size
std::cout << "List size: " << numbers.size() << std::endl;
// Iterate through the list
std::cout << "List elements: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// Remove elements
numbers.pop_front(); // Remove first element
numbers.pop_back(); // Remove last element
// Insert an element at a specific position
auto it = numbers.begin();
numbers.insert(it, 15);
// Print updated list
std::cout << "Updated list: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// Check if list is empty
std::cout << "Is list empty? "
<< (numbers.empty()? "Yes" : "No") << std::endl;
return 0;
}
Скомпилируйте и запустите программу:
g++ list_demo.cpp -o list_demo
./list_demo
Пример вывода:
List size: 3
List elements: 5 10 20
Updated list: 15 10
Is list empty? No
Основные моменты о списках:
- Используйте
#include <list>для включения библиотеки списков push_back()добавляет элементы в конец спискаpush_front()добавляет элементы в начало спискаpop_front()иpop_back()удаляют элементыinsert()позволяет добавлять элементы в определенную позициюbegin()возвращает итератор на первый элементempty()проверяет, является ли список пустым
Реализация пар «ключ - значение» с использованием контейнера map
На этом этапе вы узнаете о контейнере map из Стандартной Шаблонной Библиотеки (STL) языка C++, который хранит пары ключ-значение в отсортированном порядке по уникальным ключам. Ассоциативные массивы (maps) полезны для создания словарей или ассоциативных массивов.
Откройте WebIDE и создайте новый файл с именем map_demo.cpp в директории ~/project:
touch ~/project/map_demo.cpp
Добавьте следующий код в файл map_demo.cpp:
#include <iostream>
#include <map>
#include <string>
int main() {
// Create a map to store student names and their ages
std::map<std::string, int> students;
// Insert key-value pairs
students["Alice"] = 20;
students["Bob"] = 22;
students["Charlie"] = 21;
// Access values using keys
std::cout << "Alice's age: " << students["Alice"] << std::endl;
// Check if a key exists
if (students.count("David") == 0) {
std::cout << "David is not in the map" << std::endl;
}
// Iterate through the map
std::cout << "All students:" << std::endl;
for (const auto& student : students) {
std::cout << student.first << ": " << student.second << std::endl;
}
// Remove a key-value pair
students.erase("Bob");
// Check the size of the map
std::cout << "Number of students: " << students.size() << std::endl;
return 0;
}
Скомпилируйте и запустите программу:
g++ map_demo.cpp -o map_demo
./map_demo
Пример вывода:
Alice's age: 20
David is not in the map
All students:
Alice: 20
Bob: 22
Charlie: 21
Number of students: 2
Основные моменты о ассоциативных массивах:
- Используйте
#include <map>для включения библиотеки ассоциативных массивов map<KeyType, ValueType>создает ассоциативный массив с указанными типами ключей и значений- Обращайтесь к значениям с помощью квадратных скобок
[] count()проверяет, существует ли ключ- Перебирайте элементы ассоциативных массивов с помощью цикла for на основе диапазона (range-based for loop)
erase()удаляет пару ключ-значениеsize()возвращает количество элементов
Хранение уникальных элементов с использованием контейнера set
На этом этапе вы узнаете о контейнере set из Стандартной Шаблонной Библиотеки (STL) языка C++, который хранит уникальные элементы в отсортированном порядке. Множества (sets) автоматически предотвращают дубликаты значений и поддерживают элементы в определенном порядке.
Откройте WebIDE и создайте новый файл с именем set_demo.cpp в директории ~/project:
touch ~/project/set_demo.cpp
Добавьте следующий код в файл set_demo.cpp:
#include <iostream>
#include <set>
int main() {
// Create a set of integers
std::set<int> numbers;
// Insert elements
numbers.insert(10);
numbers.insert(20);
numbers.insert(30);
numbers.insert(10); // Duplicate, will not be added
// Print the size of the set
std::cout << "Set size: " << numbers.size() << std::endl;
// Iterate through the set
std::cout << "Set elements: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// Check if an element exists
if (numbers.count(20) > 0) {
std::cout << "20 is in the set" << std::endl;
}
// Remove an element
numbers.erase(20);
// Check the size after removal
std::cout << "Set size after removal: " << numbers.size() << std::endl;
// Clear the set
numbers.clear();
// Check if the set is empty
std::cout << "Is set empty? "
<< (numbers.empty()? "Yes" : "No") << std::endl;
return 0;
}
Скомпилируйте и запустите программу:
g++ set_demo.cpp -o set_demo
./set_demo
Пример вывода:
Set size: 3
Set elements: 10 20 30
20 is in the set
Set size after removal: 2
Is set empty? Yes
Основные моменты о множествах:
- Используйте
#include <set>для включения библиотеки множеств set<type>создает множество уникальных элементовinsert()добавляет элементы (дубликаты игнорируются)count()проверяет наличие элементаerase()удаляет элементclear()удаляет все элементыempty()проверяет, является ли множество пустым- Элементы автоматически сортируются
Сортировка элементов с использованием алгоритма std::sort из STL
На этом этапе вы узнаете, как использовать алгоритм sort из Стандартной Шаблонной Библиотеки (STL) для упорядочивания элементов в порядке возрастания или убывания. Библиотека <algorithm> предоставляет мощные возможности сортировки для различных контейнеров.
Откройте WebIDE и создайте новый файл с именем sort_demo.cpp в директории ~/project:
touch ~/project/sort_demo.cpp
Добавьте следующий код в файл sort_demo.cpp:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// Create a vector of integers
std::vector<int> numbers = {5, 2, 8, 1, 9, 3};
// Print original vector
std::cout << "Original vector: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// Sort the vector in ascending order
std::sort(numbers.begin(), numbers.end());
// Print sorted vector
std::cout << "Sorted vector (ascending): ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// Sort the vector in descending order
std::sort(numbers.begin(), numbers.end(), std::greater<int>());
// Print vector sorted in descending order
std::cout << "Sorted vector (descending): ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
Скомпилируйте и запустите программу:
g++ sort_demo.cpp -o sort_demo
./sort_demo
Пример вывода:
Original vector: 5 2 8 1 9 3
Sorted vector (ascending): 1 2 3 5 8 9
Sorted vector (descending): 9 8 5 3 2 1
Основные моменты о сортировке с использованием STL:
- Подключайте библиотеку
<algorithm>для сортировки std::sort()работает с различными контейнерами- По умолчанию сортировка выполняется в порядке возрастания
std::greater<type>()выполняет сортировку в порядке убывания- Сортировка выполняется на месте, изменяя исходный контейнер
- Алгоритм эффективно работает с разными типами контейнеров
Поиск элементов с использованием алгоритмов STL
На этом этапе вы узнаете, как использовать алгоритмы STL для поиска элементов в контейнерах. Библиотека <algorithm> предоставляет мощные функции для поиска и нахождения элементов.
Откройте WebIDE и создайте новый файл с именем find_demo.cpp в директории ~/project:
touch ~/project/find_demo.cpp
Добавьте следующий код в файл find_demo.cpp:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// Create a vector of integers
std::vector<int> numbers = {5, 2, 8, 1, 9, 3, 8};
// Find first occurrence of a specific element
auto it = std::find(numbers.begin(), numbers.end(), 8);
if (it!= numbers.end()) {
std::cout << "First occurrence of 8 at index: "
<< std::distance(numbers.begin(), it) << std::endl;
}
// Count occurrences of an element
int count = std::count(numbers.begin(), numbers.end(), 8);
std::cout << "Number of 8s in the vector: " << count << std::endl;
// Find if any element is greater than 6
bool has_large_element = std::any_of(numbers.begin(), numbers.end(),
[](int n) { return n > 6; });
std::cout << "Vector has element > 6: "
<< (has_large_element? "Yes" : "No") << std::endl;
// Find the minimum and maximum elements
auto min_it = std::min_element(numbers.begin(), numbers.end());
auto max_it = std::max_element(numbers.begin(), numbers.end());
std::cout << "Minimum element: " << *min_it << std::endl;
std::cout << "Maximum element: " << *max_it << std::endl;
return 0;
}
Скомпилируйте и запустите программу:
g++ find_demo.cpp -o find_demo
./find_demo
Пример вывода:
First occurrence of 8 at index: 2
Number of 8s in the vector: 2
Vector has element > 6: Yes
Minimum element: 1
Maximum element: 9
Основные моменты о алгоритмах поиска STL:
std::find()находит первое вхождение элементаstd::count()подсчитывает количество вхождений элементаstd::any_of()проверяет, удовлетворяет ли какой - то элемент условиюstd::min_element()иstd::max_element()находят минимальное и максимальное значения- Лямбда - функции можно использовать для настройки условий поиска
- Возвращаемые итераторы указывают на найденные элементы
Перебор элементов контейнеров
На этом этапе вы узнаете различные способы итерации по контейнерам STL с использованием различных методов перебора. Мы рассмотрим циклы for на основе диапазона (range-based for loops), итераторы и традиционный индексный способ перебора.
Откройте WebIDE и создайте новый файл с именем iteration_demo.cpp в директории ~/project:
touch ~/project/iteration_demo.cpp
Добавьте следующий код в файл iteration_demo.cpp:
#include <iostream>
#include <vector>
#include <list>
#include <map>
int main() {
// Vector iteration
std::vector<int> numbers = {10, 20, 30, 40, 50};
// Method 1: Range-based for loop (most modern and readable)
std::cout << "Vector iteration (range-based for):" << std::endl;
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// Method 2: Iterator-based iteration
std::cout << "Vector iteration (iterators):" << std::endl;
for (auto it = numbers.begin(); it!= numbers.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// Method 3: Index-based iteration
std::cout << "Vector iteration (index-based):" << std::endl;
for (size_t i = 0; i < numbers.size(); ++i) {
std::cout << numbers[i] << " ";
}
std::cout << std::endl;
// Map iteration
std::map<std::string, int> ages = {
{"Alice", 25},
{"Bob", 30},
{"Charlie", 35}
};
std::cout << "Map iteration:" << std::endl;
for (const auto& pair : ages) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}
Скомпилируйте и запустите программу:
g++ iteration_demo.cpp -o iteration_demo
./iteration_demo
Пример вывода:
Vector iteration (range-based for):
10 20 30 40 50
Vector iteration (iterators):
10 20 30 40 50
Vector iteration (index-based):
10 20 30 40 50
Map iteration:
Alice: 25
Bob: 30
Charlie: 35
Основные моменты об итерации по контейнерам:
- Циклы for на основе диапазона являются наиболее современными и читаемыми
- Итераторы обеспечивают детальный контроль над прохождением по контейнеру
- Индексный способ перебора хорошо работает с контейнерами, поддерживающими произвольный доступ
- Ключевое слово
autoпомогает с выводом типа - Различные контейнеры поддерживают разные методы итерации
Использование стека (stack) и очереди (queue) из STL
На этом этапе вы узнаете о двух важных адаптерах контейнеров STL: стеке (stack) и очереди (queue). Эти контейнеры предоставляют специализированные операции для управления данными по принципу "последним пришел - первым ушел" (LIFO - Last In, First Out) и "первым пришел - первым ушел" (FIFO - First In, First Out).
Откройте WebIDE и создайте новый файл с именем stack_queue_demo.cpp в директории ~/project:
touch ~/project/stack_queue_demo.cpp
Добавьте следующий код в файл stack_queue_demo.cpp:
#include <iostream>
#include <stack>
#include <queue>
int main() {
// Stack demonstration
std::stack<int> myStack;
// Push elements onto the stack
myStack.push(10);
myStack.push(20);
myStack.push(30);
std::cout << "Stack operations:" << std::endl;
std::cout << "Top element: " << myStack.top() << std::endl;
// Remove top element
myStack.pop();
std::cout << "Top element after pop: " << myStack.top() << std::endl;
std::cout << "Stack size: " << myStack.size() << std::endl;
// Queue demonstration
std::queue<std::string> myQueue;
// Add elements to the queue
myQueue.push("Alice");
myQueue.push("Bob");
myQueue.push("Charlie");
std::cout << "\nQueue operations:" << std::endl;
std::cout << "Front element: " << myQueue.front() << std::endl;
std::cout << "Back element: " << myQueue.back() << std::endl;
// Remove front element
myQueue.pop();
std::cout << "Front element after pop: " << myQueue.front() << std::endl;
std::cout << "Queue size: " << myQueue.size() << std::endl;
return 0;
}
Скомпилируйте и запустите программу:
g++ stack_queue_demo.cpp -o stack_queue_demo
./stack_queue_demo
Пример вывода:
Stack operations:
Top element: 30
Top element after pop: 20
Stack size: 2
Queue operations:
Front element: Alice
Back element: Charlie
Front element after pop: Bob
Queue size: 2
Основные моменты о стеке и очереди:
- Стек (Stack, LIFO - Последним пришел, первым ушел)
push()добавляет элемент на вершину стекаpop()удаляет элемент с вершины стекаtop()возвращает элемент, находящийся на вершине стека
- Очередь (Queue, FIFO - Первым пришел, первым ушел)
push()добавляет элемент в конец очередиpop()удаляет элемент из начала очередиfront()возвращает первый элемент очередиback()возвращает последний элемент очереди
- У обоих контейнеров есть метод
size()для проверки количества элементов - Необходимо подключить заголовочные файлы
<stack>и<queue>
Обработка безопасности контейнеров при исключениях
На этом этапе вы узнаете, как обрабатывать исключения и обеспечить безопасную работу с контейнерами STL. Обработка исключений помогает предотвратить аварийное завершение программы и обеспечивает надежное управление ошибками.
Откройте WebIDE и создайте новый файл с именем exception_safety_demo.cpp в директории ~/project:
touch ~/project/exception_safety_demo.cpp
Добавьте следующий код в файл exception_safety_demo.cpp:
#include <iostream>
#include <vector>
#include <stdexcept>
void demonstrateVectorSafety() {
std::vector<int> numbers;
try {
// Attempt to access an element from an empty vector
std::cout << "Attempting to access element from empty vector:" << std::endl;
numbers.at(0); // This will throw an out_of_range exception
}
catch (const std::out_of_range& e) {
std::cout << "Out of Range Error: " << e.what() << std::endl;
}
// Safe element addition
try {
numbers.push_back(10);
numbers.push_back(20);
std::cout << "Vector size: " << numbers.size() << std::endl;
// Safe element access
std::cout << "First element: " << numbers.at(0) << std::endl;
std::cout << "Second element: " << numbers.at(1) << std::endl;
}
catch (const std::exception& e) {
std::cout << "An error occurred: " << e.what() << std::endl;
}
}
int main() {
// Demonstrate vector exception safety
demonstrateVectorSafety();
return 0;
}
Скомпилируйте и запустите программу:
g++ exception_safety_demo.cpp -o exception_safety_demo
./exception_safety_demo
Пример вывода:
Attempting to access element from empty vector:
Out of Range Error: vector
Vector size: 2
First element: 10
Second element: 20
Основные моменты о безопасности контейнеров в случае исключений:
- Используйте блоки
try-catchдля обработки потенциальных исключений. - Исключение
std::out_of_rangeвыбрасывается при попытке доступа к несуществующему элементу вектора. - Метод
at()выполняет проверку границ, в отличие от оператора[]. - Сначала обрабатывайте конкретные исключения, а затем более общие.
- Всегда обрабатывайте потенциальные исключения, чтобы предотвратить аварийное завершение программы.
- Используйте стандартные классы исключений из
<stdexcept>.
Резюме
В этом практическом занятии (лабораторной работе) вы узнали о различных компонентах Стандартной Шаблонной Библиотеки C++ (C++ Standard Template Library, STL) и о том, как эффективно их использовать. Вы начали с изучения контейнера vector, который представляет собой динамический массив, размер которого может изменяться. Вы научились добавлять и удалять элементы, обращаться к ним по индексам и проходить по вектору с использованием цикла for на основе диапазона.
Затем вы углубились в изучение контейнера list, который представляет собой реализацию двусвязного списка. Вы узнали, как выполнять общие операции с связным списком, такие как вставка, удаление и обход элементов. Вы также изучили контейнер map, который позволяет хранить пары "ключ - значение", и контейнер set, который хранит уникальные элементы. Кроме того, вы научились использовать алгоритмы STL, такие как sort и find, для манипулирования и поиска элементов в этих контейнерах. Наконец, вы изучили контейнеры stack и queue и обсудили важность безопасности в случае исключений при работе с компонентами STL.



