This repository has been archived on 2026-07-28. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
cmc/seminars/3.md
T
2025-04-13 21:48:15 +03:00

260 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Третий семинар
## Шаблоны
```cpp
// template <typename>
template <class T>
void swap(T& a, T& b) {
T tmp;
tmp = a;
a = b;
b = tmp;
}
```
Можно применять и от нескольких неизвестных параметров
```cpp
template <typename T, typename K>
void transfer(T fromAccount, T toAccount, K code, int sum)
{
std::cout << "From: " << fromAccount << "\nTo: " << toAccount
<< "\nSum: " << sum << "\nCode: " << code << std::endl;
}
```
Пример кода для абсолютного значения:
```cpp
template <class T> T abs(const T& x) {
// template <class T> T abs(T x) {
return x >= 0 ? x : -x;
}
```
Суммирование элементов массива
```cpp
template <class T> T sum(T* mas, int N) {
T res = 0;
for (int i = 0; i < N; ++i) {
res += mas[i];
}
return res;
}
int main() {
double mas[5] = {...};
std::cout << sum(mas, 5);
return 0;
}
```
```cpp
template <class T> T sum(T* mas, int N) {
T res = 0;
for (int i = 0; i < N; ++i) {
res += mas[i];
}
return res;
}
int main() {
double mas[5] = {...};
std::cout << sum<double, 5>(mas);
return 0;
}
```
## Что-то про стэк
Вторая задача:
Суть была реализовывать динамически расширяемый массив
```cpp
template<class T, int SIZE>
class st {
T st[SIZE];
int top = 0;
public:
void push(T a) {
if (top == SIZE) {
// error
} else {
st[top++] = a;
}
}
T pop();
}
template<class T, int SIZE>
T st<T, SIZE>::pop() {
return st[--top];
}
```
Если указать стандартное значение для каких-то параметров, вызов обычный
## Библиотеки
### Контейнеры
#### Последовательности
- list - двунаправленный список
- vector
- deque - очередь
На их основе создаются:
- stack
- queue
#### Ассоциативные массивы
- map - отображения
- multimap - ключ может несколько раз встречаться
- set - уникальные упорядоченные ключи
- multiset - совпадающие ключи
### Итераторы
`#include <algorithm>` - подключение библиотеки
- value_type - тип значений в контейнере
- size_type - аналог size_t
- reference/ const reference - ссылки на элемент
- pointer/const pointer - указатели
Исполняют роль указателей
Для каждого контейнера определён:
- iterator - идёт от начала
- reverse_iterator - идёт с конца
- const_iterator - не меняет значений
- const_reverse_iterator - не меняет значений, ревёрс
```cpp
begin(), end();
rbegin(), rend();
cbegin(), cend(); // для константных
```
Виды итераторов:
- input
- output
- forward
- bidirectional - list, map, set
- random_access - для vector deque, можно индексировать, += n
```cpp
#include <vector>
int main() {
vector<int> v1; // длина 0
vector<int> v2(5); // длина 5, занулены
vector<int> v3(10, '*');
int m[] = {1, 2, 3, 4};
vector<int> v4(m, m + 4);
// vector<int> v4(m.begin(), m.end());
}
```
```cpp
for (int i = 0; i < v.size(); ++i)
cout << v[i] << " "; // только для random_access контейнера
v[i] == v.at(i) // выдаёт out_of_range, если нет элемента
```
Печать элементов в прямом и обратном при помощи итераторов
```cpp
#include <vector>
#include <iostream>
// прямой с помощью прямого
void f1(std::vector<int> mas) {
std::vector<int>::std::iterator iter = mas.begin();
while (iter != mas.end()) {
std::cout << *iter << " ";
iter++;
}
}
// обратный с помощью реверсивного
void f2(std::vector<int> mas) {
std::vector<int>::std::reverse_iterator iter = mas.rbegin();
while (iter != mas.rend()) {
std::cout << *iter << " ";
iter++;
}
}
// обратный с помощью прямого
void f3(std::vector<int> mas) {
std::vector<int>::std::iterator iter = mas.end();
while (iter != mas.begin()) {
--iter;
std::cout << *iter << " ";
}
}
```
Или же код нормального человека:
```cpp
for (auto x : v) cout << x << " ";
```
### Алгоритмы
Некоторые методы контейнеров:
- `size_type size()` - количество элементов в контейнере
- `bool empty()` - пустой ли контейнер
- `void clear()` - очищает контейнер
- `void push_back()` - добавляет в конец value_type<>
- `void pop_back()` - удаляет последний элемент
- `reference back()` - возвращает ссылку на последний элемент
- `reference front()` - возвращает ссылку на первый элемент
- `iterator insert(iterator p, value_type<>)` - вставка перед позицией p, возвращает на новый элемент
- `iterator erase(iterator p)` - удаляет, куда указывает, возвращает итератор на некст элемент
- `iterator erase(iterator p1, iterator p2)` - c первого до последнего (не включительно)
для list, deque
- `void push_front(value_type<>)`
- `void pop_front(value_type<>)`
Для bidirectional итераторов можно использовать
- `advance(p1, 3)` для плюса
- `n = distance(p1, p2)` для вычитания
```cpp
void f(vactor<char>& mas) {
auto iter = mas.begin();
while (iter < mas.end()) {
++iter;
if (iter != mas.end())
iter = mas.erase(iter);
}
}
```