diff --git a/HOMEWORK_LIST.md b/HOMEWORK_LIST.md new file mode 100644 index 0000000..153143c --- /dev/null +++ b/HOMEWORK_LIST.md @@ -0,0 +1,541 @@ +# Список всех домашних заданий (от легкого к сложному) + +## 🟢 Уровень 1: Базовые концепции (Очень легко) + +### Занятие 1: Введение в C++ +1. **Настроить среду разработки** (компилятор, IDE) + - Простота: ⭐ + - Концепции: установка инструментов + - **Текст задания:** Настроить среду разработки (компилятор, IDE) + +2. **Программа "Hello, World" с именем и группой** + - Простота: ⭐ + - Концепции: базовый вывод, функция main() + - **Текст задания:** Написать программу, которая выводит ваше имя и группу + +3. **Программа-приветствие** (запрос имени пользователя и вывод приветствия) + - Простота: ⭐ + - Концепции: ввод/вывод, переменные + - **Текст задания:** Написать программу, которая запрашивает имя пользователя и выводит приветствие + +### Занятие 2: Базовые типы данных +4. **Изучение размеров типов данных** + - Простота: ⭐ + - Концепции: sizeof(), типы данных + - **Текст задания:** Изучить размеры различных типов данных на вашей системе + +5. **Демонстрация переполнения переменных** + - Простота: ⭐⭐ + - Концепции: переполнение, предельные значения + - **Текст задания:** Написать программу, демонстрирующую переполнение переменных + +6. **Конвертация между целочисленными типами** + - Простота: ⭐⭐ + - Концепции: signed/unsigned, преобразование типов + - **Текст задания:** Создать программу для конвертации между различными целочисленными типами. Познакомиться с модификаторами `signed` и `unsigned` + +--- + +## 🟡 Уровень 2: Базовые алгоритмы (Легко) + +### Занятие 3: Практика 1 - Переменные и типы +7. **Калькулятор базовых операций** + - Простота: ⭐⭐ + - Концепции: арифметика, ввод/вывод + - **Текст задания:** Напишите программу, которая: + - Принимает два числа от пользователя + - Выполняет операции: сложение, вычитание, умножение, деление + - Выводит результаты с правильными типами данных + +8. **Конвертер единиц измерения** (температура, длина, масса) + - Простота: ⭐⭐ + - Концепции: формулы, типы данных + - **Текст задания:** Создайте программу для конвертации: + - Температуры (Цельсий ↔ Фаренгейт) + - Длины (метры ↔ футы) + - Массы (килограммы ↔ фунты) + +9. **Анализ чисел** (четность, знак, абсолютное значение) + - Простота: ⭐⭐ + - Концепции: условные операторы, математические функции + - **Текст задания:** Напишите программу, которая: + - Принимает число от пользователя + - Определяет, является ли оно четным/нечетным + - Определяет знак числа (положительное/отрицательное/ноль) + - Вычисляет абсолютное значение + +10. **Работа с символами** (буква/цифра, регистр, ASCII) + - Простота: ⭐⭐ + - Концепции: символы, ASCII коды + - **Текст задания:** Создайте программу, которая: + - Принимает символ от пользователя + - Определяет, является ли он буквой, цифрой или специальным символом + - Если это буква, определяет регистр (верхний/нижний) + - Выводит ASCII код символа + +11. **Калькулятор с проверкой типов** (int и double) + - Простота: ⭐⭐⭐ + - Концепции: преобразование типов, точность + - **Текст задания:** Создайте программу, которая: + - Принимает два числа разных типов (int и double) + - Выполняет все арифметические операции + - Демонстрирует потерю точности при преобразовании типов + - Выводит результаты с указанием типов + +12. **Анализ диапазонов типов** (min/max, размер, переполнение) + - Простота: ⭐⭐⭐ + - Концепции: numeric_limits, типы данных + - **Текст задания:** Напишите программу, которая: + - Запрашивает у пользователя тип данных (char, int, long, float, double) + - Выводит минимальное и максимальное значение для этого типа + - Показывает размер типа в байтах + - Демонстрирует переполнение для выбранного типа + +13. **Работа с константами** (const, constexpr) + - Простота: ⭐⭐ + - Концепции: константы, constexpr функции + - **Текст задания:** Создайте программу, использующую: + - `const` переменные для хранения конфигурации + - `constexpr` для вычислений на этапе компиляции + - Демонстрацию разницы между `const` и `constexpr` + +14. **Система единиц измерения** (метры, километры, мили) + - Простота: ⭐⭐⭐ + - Концепции: типы данных, точность вычислений + - **Текст задания:** Реализуйте программу для работы с единицами измерения: + - Хранение значений в различных единицах (метры, километры, мили) + - Конвертация между единицами + - Использование правильных типов данных (float/double) + - Обработка точности вычислений + +--- + +## 🟠 Уровень 3: Функции и массивы (Средне) + +### Занятие 4: Функции и указатели +15. **Функция обмена значений** (через указатели и ссылки) + - Простота: ⭐⭐⭐ + - Концепции: указатели, ссылки, передача параметров + - **Текст задания:** Реализовать функцию для обмена значений двух переменных (через указатели и ссылки). Изучить разницу между передачей по значению, указателю и ссылке + +16. **Функция поиска максимума в массиве** (возвращает указатель) + - Простота: ⭐⭐⭐ + - Концепции: указатели, массивы, функции + - **Текст задания:** Написать функцию, которая принимает массив и его размер, возвращает указатель на максимальный элемент + +17. **Указатель на функцию как параметр** + - Простота: ⭐⭐⭐⭐ + - Концепции: указатели на функции + - **Текст задания:** Создать функцию, которая принимает указатель на функцию как параметр + +### Занятие 5: Массивы и строки +18. **Функция поиска максимума в массиве** + - Простота: ⭐⭐⭐ + - Концепции: массивы, функции + - **Текст задания:** Реализовать функцию поиска максимума в массиве + +19. **Функция инверсии массива** + - Простота: ⭐⭐⭐ + - Концепции: массивы, алгоритмы + - **Текст задания:** Написать функцию для инверсии массива + +20. **Работа со строками** (подсчет слов, поиск подстроки) + - Простота: ⭐⭐⭐ + - Концепции: строки, алгоритмы + - **Текст задания:** Создать программу для работы со строками (подсчет слов, поиск подстроки) + +21. **Преобразование между форматами строк** (C-string ↔ std::string) + - Простота: ⭐⭐⭐ + - Концепции: строки, преобразования + - **Текст задания:** Реализовать функции для преобразования между различными форматами строк + +22. **Работа с многострочным текстом** + - Простота: ⭐⭐⭐⭐ + - Концепции: строки, обработка текста + - **Текст задания:** Написать программу для работы с многострочным текстом + +### Занятие 6: Практика 2 - Функции и массивы +23. **Поиск медианы из 3 чисел** (task_01) + - Простота: ⭐⭐ + - Концепции: функции, условные операторы + - **Текст задания:** Написать функцию, которая возвращает медиану из 3 чисел + +24. **Поиск максимума в массиве** (task_02) + - Простота: ⭐⭐⭐ + - Концепции: указатели, массивы, функции + - **Текст задания:** Создайте функцию, которая принимает указатель на массив целых чисел и его размер, и возвращает максимальное значение в массиве + +25. **Инверсия массива** (task_03) + - Простота: ⭐⭐⭐ + - Концепции: указатели, массивы, алгоритмы + - **Текст задания:** Создайте функцию, которая принимает указатель на массив целых чисел и его размер, и инвертирует порядок его элементов (первый элемент становится последним, второй предпоследним и т.д.) + +26. **Сдвиг элементов массива** (task_04) + - Простота: ⭐⭐⭐⭐ + - Концепции: массивы, алгоритмы, циклический сдвиг + - **Текст задания:** Создайте функцию, которая принимает указатель на массив целых чисел, его размер, и целое число N. Функция должна сдвинуть все элементы массива на N позиций вправо, чтобы первые элементы стали последними. Элементы, которые "выталкиваются" из массива, должны появиться с левой стороны + +27. **Работа со строками** (подсчет слов, самое длинное слово, переворот) + - Простота: ⭐⭐⭐ + - Концепции: строки, алгоритмы + - **Текст задания:** Создайте программу, которая: + - Принимает строку от пользователя + - Подсчитывает количество слов + - Находит самое длинное слово + - Переворачивает строку + +28. **Набор функций для работы со строками** (слова, палиндром, пробелы) + - Простота: ⭐⭐⭐⭐ + - Концепции: строки, алгоритмы, функции + - **Текст задания:** Создайте набор функций для работы со строками: + - Функция подсчета количества слов в строке + - Функция поиска самого длинного слова + - Функция переворота строки + - Функция проверки, является ли строка палиндромом + - Функция удаления всех пробелов из строки + +29. **Многомерные массивы** (заполнение, вывод, транспонирование, максимум) + - Простота: ⭐⭐⭐⭐ + - Концепции: двумерные массивы, матрицы + - **Текст задания:** Реализуйте функции для работы с двумерными массивами: + - Функция заполнения матрицы случайными числами + - Функция вывода матрицы + - Функция транспонирования матрицы + - Функция поиска максимального элемента и его координат + +30. **Массивы структур** (Student: имя, возраст, балл) + - Простота: ⭐⭐⭐⭐ + - Концепции: структуры, массивы, функции + - **Текст задания:** Создайте структуру `Student` и функции для работы с массивом студентов: + - Структура: имя, возраст, средний балл + - Функция поиска студента с максимальным баллом + - Функция сортировки студентов по баллу + - Функция подсчета студентов с баллом выше заданного + +31. **Указатели на функции** (сортировка, map, фильтрация) + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: указатели на функции, алгоритмы + - **Текст задания:** Используйте указатели на функции для: + - Создания функции сортировки, которая принимает функцию сравнения + - Реализации функции `map` для применения функции к каждому элементу массива + - Создания функции фильтрации массива по условию + +### Занятие 7: Управление потоком выполнения +32. **Алгоритмы с циклами** (поиск, сортировка, фильтрация) + - Простота: ⭐⭐⭐ + - Концепции: циклы, алгоритмы + - **Текст задания:** Реализовать различные алгоритмы с использованием циклов (поиск, сортировка, фильтрация) + +33. **Вложенные циклы** (паттерны, матрицы) + - Простота: ⭐⭐⭐ + - Концепции: вложенные циклы + - **Текст задания:** Написать программу с вложенными циклами (вывод паттернов, работа с матрицами) + +34. **Интерактивное меню** (switch-case) + - Простота: ⭐⭐⭐ + - Концепции: switch, циклы + - **Текст задания:** Использовать switch для создания интерактивного меню + +35. **Калькулятор с меню операций** + - Простота: ⭐⭐⭐ + - Концепции: циклы, switch, функции + - **Текст задания:** Создать программу-калькулятор с циклом и меню операций + +36. **Игра "Угадай число"** + - Простота: ⭐⭐⭐ + - Концепции: циклы, случайные числа, условия + - **Текст задания:** Реализовать игру "Угадай число" с использованием циклов + +--- + +## 🔴 Уровень 4: Динамическая память (Сложно) + +### Занятие 8: Динамическая память +37. **Динамический массив** (добавление/удаление элементов) + - Простота: ⭐⭐⭐⭐ + - Концепции: new/delete, динамическая память + - **Текст задания:** Реализовать динамический массив с функциями добавления/удаления элементов + +38. **Программа без утечек памяти** + - Простота: ⭐⭐⭐⭐ + - Концепции: управление памятью, отладка + - **Текст задания:** Написать программу, которая работает с динамической памятью без утечек. Изучить инструменты для обнаружения утечек памяти (valgrind, AddressSanitizer) + +39. **Класс для управления динамическим массивом** + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: классы, динамическая память, конструкторы/деструкторы + - **Текст задания:** Создать класс для управления динамическим массивом + +40. **Функции для работы с динамическими матрицами** + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: динамическая память, двумерные массивы + - **Текст задания:** Реализовать функции для работы с динамическими матрицами + +### Занятие 9: Практика 3 - Алгоритмы и структуры данных +41. **Динамический массив** (класс или функции: создание, добавление, удаление, вставка, поиск) + - Простота: ⭐⭐⭐⭐ + - Концепции: динамическая память, структуры данных + - **Текст задания:** Реализуйте класс или набор функций для работы с динамическим массивом: + - Создание массива заданного размера + - Добавление элемента в конец + - Удаление элемента по индексу + - Вставка элемента по индексу + - Поиск элемента + - Освобождение памяти + +42. **Алгоритмы сортировки** (пузырьковая, выбором, быстрая) + - Простота: ⭐⭐⭐⭐ + - Концепции: алгоритмы, сортировка + - **Текст задания:** Реализуйте функции сортировки: + - Пузырьковая сортировка + - Сортировка выбором + - Быстрая сортировка (опционально) + +43. **Алгоритмы поиска** (линейный, бинарный) + - Простота: ⭐⭐⭐ + - Концепции: алгоритмы, поиск + - **Текст задания:** Реализуйте алгоритмы поиска: + - Линейный поиск + - Бинарный поиск (для отсортированного массива) + +44. **Работа со строками** (частота символов, удаление дубликатов, палиндром, поиск подстроки) + - Простота: ⭐⭐⭐⭐ + - Концепции: строки, алгоритмы + - **Текст задания:** Создайте программу для: + - Подсчета частоты символов в строке + - Удаления дубликатов символов + - Проверки, является ли строка палиндромом + - Поиска подстроки в строке + +45. **Матрицы** (создание, транспонирование, умножение) + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: динамическая память, матрицы, алгоритмы + - **Текст задания:** Реализуйте функции для работы с матрицами: + - Создание матрицы (динамическое выделение памяти) + - Транспонирование + - Умножение матриц + - Освобождение памяти + +46. **Динамический стек** (класс Stack: push, pop, top, isEmpty, size) + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: классы, динамическая память, структуры данных + - **Текст задания:** Реализуйте класс `Stack` для работы со стеком: + - Динамическое выделение памяти + - Методы: `push()`, `pop()`, `top()`, `isEmpty()`, `size()` + - Автоматическое увеличение размера при необходимости + - Конструктор, деструктор, конструктор копирования + - Оператор присваивания + +47. **Динамическая очередь** (класс Queue: enqueue, dequeue, front, isEmpty, size) + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: классы, динамическая память, кольцевой буфер + - **Текст задания:** Создайте класс `Queue`: + - Кольцевой буфер для эффективности + - Методы: `enqueue()`, `dequeue()`, `front()`, `isEmpty()`, `size()` + - Автоматическое расширение при переполнении + - Правильное управление памятью + +48. **Односвязный список** (Node, insert, remove, find, size) + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: классы, указатели, структуры данных + - **Текст задания:** Реализуйте простой односвязный список: + - Структура `Node` для хранения данных и указателя + - Методы: `insert()`, `remove()`, `find()`, `size()` + - Правильное освобождение памяти + - Итерация по списку + +49. **Класс Matrix** (динамические матрицы, конструкторы, методы, операторы) + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: классы, динамическая память, операторы + - **Текст задания:** Реализуйте класс `Matrix` для работы с динамическими матрицами: + - Выделение и освобождение памяти + - Конструкторы (по умолчанию, с параметрами, копирования) + - Методы: `get()`, `set()`, `transpose()`, `multiply()` + - Операторы `[]` для доступа к строкам + - Деструктор для освобождения памяти + +--- + +## 🟣 Уровень 5: Объектно-ориентированное программирование (Очень сложно) + +### Занятие 10: Структуры и классы +50. **Структура Student** (с функциями) + - Простота: ⭐⭐⭐ + - Концепции: структуры, функции-члены + - **Текст задания:** Создать структуру для представления студента с функциями + +51. **Класс Complex** (комплексные числа) + - Простота: ⭐⭐⭐⭐ + - Концепции: классы, конструкторы, методы + - **Текст задания:** Реализовать класс для работы с комплексными числами + +52. **Класс BankAccount** (пополнение, снятие) + - Простота: ⭐⭐⭐⭐ + - Концепции: классы, методы, инкапсуляция + - **Текст задания:** Создать класс `BankAccount` с методами пополнения и снятия + +53. **Перечисления для статусов** + - Простота: ⭐⭐ + - Концепции: enum, enum class + - **Текст задания:** Использовать перечисления для статусов + +54. **Массивы объектов** + - Простота: ⭐⭐⭐⭐ + - Концепции: классы, массивы + - **Текст задания:** Работать с массивами объектов + +### Занятие 11: Практика 4 - ООП +55. **Класс Student** (имя, фамилия, возраст, оценки, средний балл, конструкторы, деструктор) + - Простота: ⭐⭐⭐⭐ + - Концепции: классы, динамическая память, конструкторы/деструкторы + - **Текст задания:** Создайте класс `Student` со следующими возможностями: + - Хранение имени, фамилии, возраста + - Хранение оценок (динамический массив) + - Методы для добавления оценки + - Метод для вычисления среднего балла + - Конструкторы (по умолчанию, с параметрами, копирования) + - Деструктор + - Метод для вывода информации о студенте + +56. **Класс BankAccount** (номер счета, баланс, пополнение, снятие, защита от отрицательного баланса, логирование) + - Простота: ⭐⭐⭐⭐ + - Концепции: классы, инкапсуляция, валидация + - **Текст задания:** Реализуйте класс `BankAccount`: + - Хранение номера счета и баланса + - Методы для пополнения и снятия средств + - Проверка баланса + - Защита от отрицательного баланса + - Логирование операций + - Конструкторы и деструктор + +57. **Класс Vector** (координаты x, y, z, конструкторы, длина, нормализация, операции) + - Простота: ⭐⭐⭐⭐ + - Концепции: классы, математические операции + - **Текст задания:** Создайте класс `Vector` для работы с математическими векторами: + - Хранение координат (x, y, z) + - Конструкторы (по умолчанию, с параметрами, копирования) + - Методы для вычисления длины вектора + - Методы для нормализации вектора + - Операции сложения и вычитания векторов (как методы) + - Скалярное произведение + +58. **Иерархия фигур** (Shape: area, perimeter, draw; Circle, Rectangle, Triangle) + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: наследование, виртуальные функции, полиморфизм + - **Текст задания:** Создайте иерархию классов для геометрических фигур: + - Базовый класс `Shape` с виртуальными методами: + - `area()` - вычисление площади + - `perimeter()` - вычисление периметра + - `draw()` - вывод информации о фигуре + - Производные классы: + - `Circle` (радиус) + - `Rectangle` (ширина, высота) + - `Triangle` (три стороны) + - Создайте массив указателей на `Shape` и продемонстрируйте полиморфизм + +59. **Система сотрудников** (Employee: Manager, Developer, SalesPerson) + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: наследование, виртуальные функции, полиморфизм + - **Текст задания:** Реализуйте систему для управления сотрудниками компании: + - Базовый класс `Employee`: + - Имя, ID, зарплата + - Виртуальный метод `calculateSalary()` + - Виртуальный метод `getInfo()` + - Производные классы: + - `Manager` (бонус) + - `Developer` (часы работы, ставка) + - `SalesPerson` (процент от продаж) + - Создайте функцию для вывода информации о всех сотрудниках + +60. **Перегрузка операторов для Vector** (+, -, *, +=, -=, <<, >>, []) + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: перегрузка операторов, дружественные функции + - **Текст задания:** Для класса `Vector` из задания 3: + - Перегрузите операторы `+`, `-`, `*` (скалярное произведение) + - Перегрузите операторы `+=`, `-=` + - Перегрузите операторы ввода/вывода `<<` и `>>` + - Перегрузите оператор `[]` для доступа к координатам + +--- + +## 🔵 Уровень 6: Продвинутые темы (Экспертный) + +### Занятие 12: Умные указатели +61. **Рефакторинг кода на умные указатели** (замена обычных указателей) + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: умные указатели, RAII + - **Текст задания:** Переписать код с обычными указателями на умные указатели + +62. **Класс с unique_ptr** (управление ресурсами) + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: unique_ptr, RAII, классы + - **Текст задания:** Создать класс, использующий `unique_ptr` для управления ресурсами + +63. **Система с shared_ptr и weak_ptr** (разрыв циклических ссылок) + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: shared_ptr, weak_ptr, циклические ссылки + - **Текст задания:** Реализовать систему с `shared_ptr` и `weak_ptr` для разрыва циклических ссылок + +64. **Демонстрация всех типов умных указателей** + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: unique_ptr, shared_ptr, weak_ptr + - **Текст задания:** Написать программу, демонстрирующую работу всех типов умных указателей. Изучить разницу между `make_unique`/`make_shared` и `new` + +### Занятие 13: Итераторы +65. **Функции поиска с итераторами** + - Простота: ⭐⭐⭐⭐ + - Концепции: итераторы, алгоритмы + - **Текст задания:** Реализовать функции поиска с использованием итераторов + +66. **Функция для работы с любым контейнером** (через итераторы) + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: итераторы, шаблоны, STL + - **Текст задания:** Создать функцию для работы с любым контейнером через итераторы + +67. **Простой итератор для собственного класса** + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: итераторы, классы, перегрузка операторов + - **Текст задания:** Реализовать простой итератор для собственного класса + +68. **Алгоритмы STL с итераторами** + - Простота: ⭐⭐⭐⭐ + - Концепции: итераторы, STL алгоритмы + - **Текст задания:** Использовать алгоритмы STL с итераторами + +69. **Единый интерфейс для разных контейнеров** (через итераторы) + - Простота: ⭐⭐⭐⭐⭐ + - Концепции: итераторы, шаблоны, полиморфизм + - **Текст задания:** Написать код, работающий с разными типами контейнеров через единый интерфейс итераторов + +--- + +## 📊 Статистика по сложности + +- **Очень легко (⭐-⭐⭐):** 6 заданий +- **Легко (⭐⭐-⭐⭐⭐):** 8 заданий +- **Средне (⭐⭐⭐-⭐⭐⭐⭐):** 22 задания +- **Сложно (⭐⭐⭐⭐-⭐⭐⭐⭐⭐):** 20 заданий +- **Очень сложно (⭐⭐⭐⭐⭐):** 13 заданий + +**Всего заданий: 69** + +--- + +## 🎯 Рекомендации по порядку выполнения + +1. **Начните с уровня 1** - базовые концепции и настройка среды +2. **Переходите к уровню 2** - простые алгоритмы и работа с данными +3. **Освойте уровень 3** - функции, массивы и строки +4. **Изучите уровень 4** - динамическая память (критически важно!) +5. **Переходите к уровню 5** - объектно-ориентированное программирование +6. **Завершите уровнем 6** - продвинутые темы (опционально) + +--- + +## 📝 Примечания + +- Сложность оценивается относительно базового курса C++ +- Некоторые задания могут быть объединены или расширены +- Рекомендуется выполнять задания последовательно по урокам +- Для заданий уровня 4+ обязательно используйте инструменты отладки памяти (valgrind, AddressSanitizer) + diff --git a/doc/README.md b/doc/README.md index 4d3585e..6b9a7db 100644 --- a/doc/README.md +++ b/doc/README.md @@ -145,10 +145,15 @@ ### Дополнительные темы для изучения +#### Дополнительные занятия +- [Занятие 12: Умные указатели (Smart Pointers)](lesson_12.md) - 2 пары +- [Занятие 13: Итераторы (Iterators)](lesson_13.md) - 2 пары + #### После базового курса - Шаблоны (templates) и метапрограммирование - STL контейнеры и алгоритмы -- Умные указатели (smart pointers) +- Умные указатели (smart pointers) - см. [Занятие 12](lesson_12.md) +- Итераторы (iterators) - см. [Занятие 13](lesson_13.md) - Многопоточность (threading) - Лямбда-выражения и функциональное программирование - Move-семантика и rvalue references diff --git a/doc/exam_tickets.md b/doc/exam_tickets.md new file mode 100644 index 0000000..fee6492 --- /dev/null +++ b/doc/exam_tickets.md @@ -0,0 +1,288 @@ +# Билеты для зачёта по C++ (по списку тем) + +Формат каждого билета: +- **Теория**: 2 вопроса (кратко сформулированы). +- **Практика**: 1 задача с чёткой постановкой (ввод/вывод/требования/граничные случаи). + +Рекомендации к выполнению практики: +- Компилируйте с предупреждениями: `g++ -std=c++17 -Wall -Wextra -pedantic`. +- Не забывайте проверять корректность ввода (как минимум: `if (!(std::cin >> x))`). +- Для задач с делением/индексацией/файлами обязательно обрабатывайте ошибки. + +--- + +## Билет 1. Препроцессор и `main()` +- **Теория 1**: Директивы препроцессора `#include`, `#define`: назначение, пример использования. +- **Теория 2**: Функция `main()`: точка входа, возвращаемое значение, параметры `argc/argv` (что это). +- **Практика**: «Версия сборки и приветствие» + - **Задание**: Напишите программу, которая выводит приветствие и “версию” программы, заданную через макрос. + - **Требования**: + - В начале файла объявите макрос `APP_VERSION` через `#define` (например, `"1.0.0"`). + - Программа должна вывести две строки: + 1) `Hello, C++!` + 2) `Version: <значение APP_VERSION>` + - **Ввод**: отсутствует. + - **Вывод**: 2 строки, как указано выше. + - **Проверка**: программа компилируется без ошибок и предупреждений. + +--- + +## Билет 2. Встроенные типы. `std::string` и `std::vector` +- **Теория 1**: Встроенные типы данных (целые/вещественные/`bool`/`char`), `sizeof`, знаковые/беззнаковые. +- **Теория 2**: `std::string` и `std::vector`: назначение, отличие от C-строк и статических массивов. +- **Практика**: «Статистика слов» + - **Задание**: Считайте одну строку целиком и найдите: + - количество слов; + - самое длинное слово (если несколько — первое по порядку). + - **Ввод**: одна строка (может содержать пробелы в начале/в конце и несколько пробелов подряд). + - **Вывод**: + - `words=` + - `longest=<слово>` (если слов нет, вывести `longest=` пустым) + - **Требования**: + - Слова — это последовательности непробельных символов, разделённые пробелами/табами. + - Используйте `std::string` и `std::vector` для хранения слов. + - **Граничные случаи**: + - пустая строка; + - строка только из пробелов/табов; + - несколько пробелов подряд. + +--- + +## Билет 3. Константы: `const` и `constexpr` +- **Теория 1**: `const` vs `constexpr`: что гарантируется, когда вычисляется значение. +- **Теория 2**: Константность объектов/ссылок/методов: `const T&`, `T* const`, `const T*`, `const`-методы. +- **Практика**: «Вычисления на этапе компиляции» + - **Задание**: Реализуйте `constexpr`-функцию `int sq(int x)` и используйте её, чтобы: + - объявить `constexpr int A = sq(12);` + - вывести `A` в консоль. + - **Ввод**: отсутствует. + - **Вывод**: одна строка `A=<значение>`. + - **Требования**: + - Функция должна быть `constexpr`. + - Не используйте глобальные изменяемые переменные. + +--- + +## Билет 4. Операторы и приоритет. Присваивание +- **Теория 1**: Арифметические и логические операторы, короткое замыкание `&&`/`||`. +- **Теория 2**: Операции присваивания и составные присваивания (`+=`, `*=`, …). Приоритет и ассоциативность (идея). +- **Практика**: «Проверка выражений» + - **Задание**: Считайте `a`, `b`, `c` (целые) и вычислите два выражения: + 1) `r1 = a + b * c` + 2) `r2 = (a + b) * c` + затем выведите `r1` и `r2` и разницу `r2 - r1`. + - **Ввод**: три целых числа `a b c`. + - **Вывод**: + - `r1=<...>` + - `r2=<...>` + - `diff=<...>` + - **Граничные случаи**: допускаются отрицательные числа. + - **Примечание**: цель — показать влияние приоритета операторов. + +--- + +## Билет 5. Ветвления `if-else`, `switch` +- **Теория 1**: `if-else`, `else-if`, тернарный оператор (когда уместен). +- **Теория 2**: `switch`: `case`, `default`, `break`, fallthrough. +- **Практика**: «Мини-калькулятор по операции» + - **Задание**: Считать `x`, `y` (вещественные) и символ операции `op` из набора `+ - * /`. + - **Ввод**: `x y op` (например: `10 2 /`). + - **Вывод**: + - если операция корректна, вывести результат с точностью 6 знаков после запятой: `result=`; + - если `op` неизвестен: `error=unknown_op`; + - если деление на 0: `error=division_by_zero`. + - **Требования**: + - Использовать `switch` по `op`. + - Форматировать вывод через `std::fixed` и `std::setprecision(6)`. + +--- + +## Билет 6. Циклы и `break/continue` +- **Теория 1**: `while`, `do-while`, `for`: различия и типовые сценарии. +- **Теория 2**: `break`/`continue`, влияние на вложенные циклы. +- **Практика**: «Сумма положительных до стоп-слова» + - **Задание**: Вводится последовательность целых чисел, завершающаяся числом `0`. + - Нужно посчитать сумму **только положительных** чисел. + - Отрицательные пропускать (использовать `continue`). + - При встрече `0` завершить ввод (использовать `break`). + - **Ввод**: целые числа, по одному, заканчиваются `0`. + - **Вывод**: `sum=<значение>`. + - **Граничные случаи**: + - первое число — `0`; + - все числа отрицательные. + +--- + +## Билет 7. Ссылки +- **Теория 1**: Ссылки: инициализация, невозможность “переназначить”, отличие от указателя. +- **Теория 2**: `const`-ссылка и зачем она нужна (эффективность/безопасность). +- **Практика**: «Нормализация массива» + - **Задание**: Напишите функцию `void normalize(std::vector& v)`, которая вычитает из каждого элемента минимальный элемент вектора. + - **Ввод**: + - `n` (0 ≤ n ≤ 100000), + - затем `n` целых чисел. + - **Вывод**: `n` чисел после нормализации в одну строку через пробел (если `n==0`, вывести пустую строку). + - **Требования**: + - `normalize` принимает **ссылку** на вектор и изменяет его “на месте”. + - Не использовать дополнительные векторы размера `n`. + +--- + +## Билет 8. Функции, параметры, `constexpr`-функции +- **Теория 1**: Прототип и определение функции, возвращаемое значение, `void`. +- **Теория 2**: Формальные/фактические параметры, аргументы по умолчанию (идея), `constexpr`-функции. +- **Практика**: «Медиана трёх» + - **Задание**: Напишите функцию `int median3(int a, int b, int c)`, возвращающую медиану трёх чисел. + - **Ввод**: три целых `a b c`. + - **Вывод**: `median=<значение>`. + - **Требования**: + - Не использовать массивы и сортировку. + - Обработать равные значения корректно (например, `1 1 2` → `1`). + +--- + +## Билет 9. Классы. Поля/методы. `this` +- **Теория 1**: Класс и объект, поля и методы, `public/private`, инкапсуляция. +- **Теория 2**: Указатель `this`: что хранит, где доступен, зачем `return *this`. +- **Практика**: «Счётчик с цепочкой вызовов» + - **Задание**: Реализовать класс `Counter`: + - поле `int value`; + - конструктор по умолчанию (0) и конструктор от начального значения; + - методы: + - `Counter& inc()` увеличивает `value` на 1 и возвращает `*this`; + - `Counter& dec()` уменьшает `value` на 1 и возвращает `*this`; + - `int get() const`. + - **Ввод**: целое `start` и строка-команда из символов `+` и `-` (например: `++-+-`). + - **Вывод**: итоговое значение: `value=<...>`. + - **Требования**: + - Использовать цепочку вызовов (например, применить команду, многократно вызывая `inc/dec`). + +--- + +## Билет 10. Перечисления: `enum` и `enum class` +- **Теория 1**: Различия `enum` и `enum class`: область видимости, преобразования типов. +- **Теория 2**: Когда выбирать `enum class` (избежание конфликтов имён, типобезопасность). +- **Практика**: «Статусы задач» + - **Задание**: Создайте `enum class Status { Ok, Error, Pending };` и функцию: + - `Status parseStatus(const std::string& s)` где `s` — `"ok"`, `"error"`, `"pending"`; + - `std::string toString(Status st)`. + - **Ввод**: одно слово-статус. + - **Вывод**: + - если статус распознан: `status=<нормализованное_имя>` (`ok/error/pending`); + - иначе: `error=bad_status`. + - **Требования**: не использовать “магические числа”, только перечисление. + +--- + +## Билет 11. Перегрузка операторов +- **Теория 1**: Зачем перегружать операторы, общие правила (смысл должен быть естественным). +- **Теория 2**: Перегрузка `operator<<`/`operator>>`: почему это обычно свободные функции, `friend` (когда нужен). +- **Практика**: «Вектор 3D» + - **Задание**: Реализуйте класс `Vector3` с полями `double x,y,z` и перегрузите: + - `operator+` и `operator-`; + - `operator+=` и `operator-=`; + - `operator<<` для вывода в виде `(x,y,z)` с 2 знаками после запятой. + - **Ввод**: две тройки чисел `x1 y1 z1 x2 y2 z2`. + - **Вывод**: + - `sum=<...>` + - `diff=<...>` + - **Требования**: + - Методы/операторы, не изменяющие объект, должны быть `const`. + - `operator+`/`operator-` не должны менять операнды. + +--- + +## Билет 12. Файлы. Форматирование ввода/вывода. Позиционирование +- **Теория 1**: Потоки ввода-вывода: состояния (`good/fail/bad/eof`), обработка ошибок. +- **Теория 2**: Форматирование (например, `fixed`, `setprecision`, ширина поля) и позиционирование в файле (`seekg/tellg`). +- **Практика**: «Числа в файле и размер файла» + - **Задание**: + 1) Считать `n` и затем `n` целых чисел. + 2) Записать их в файл `numbers.txt` (в одну строку через пробел). + 3) Открыть файл на чтение, найти сумму чисел. + 4) Определить размер файла в байтах через позиционирование (`seekg(0, end)` + `tellg()`). + - **Ввод**: `n`, затем `n` целых. + - **Вывод**: + - `sum=<...>` + - `bytes=<...>` + - **Требования**: + - Проверять, что файлы открылись. Если нет — вывести `error=file_open`. + - Файл создавать/перезаписывать. + +--- + +## Билет 13. Стиль оформления. “Хороший тон” +- **Теория 1**: Читаемость: именование, функции “делают одну вещь”, отсутствие дублирования. +- **Теория 2**: Константность (`const`), минимизация области видимости, аккуратный ввод/вывод. +- **Практика**: «Рефакторинг мини-программы» + - **Задание**: Напишите небольшую программу “учёт оценок” и оформите её по правилам хорошего тона. + - **Функциональность**: + - Ввести `n` (0…1000), затем `n` целых оценок. + - Посчитать `min`, `max`, `avg` (среднее как `double`). + - **Ввод**: `n` и `n` чисел. + - **Вывод**: + - `min=<...>` + - `max=<...>` + - `avg=<...>` (ровно 2 знака после запятой). + - **Требования к коду**: + - Вынести расчёты в отдельные функции. + - Использовать осмысленные имена. + - Избегать “магических чисел”. + +--- + +## Билет 14. Этапы и средства разработки +- **Теория 1**: Этапы разработки: постановка → проектирование → реализация → тестирование → отладка. +- **Теория 2**: Инструменты: предупреждения компилятора, отладчик (GDB), санитайзеры/valgrind (назначение). +- **Практика**: «План и тест-кейсы» + - **Задание**: Для задачи “Банковский счёт” составить: + - список требований (5–8 пунктов); + - структуру классов/функций (какие поля/методы); + - набор тест-кейсов (минимум 8), включая граничные случаи. + - **Формат сдачи**: текст в комментариях в начале `main.cpp` или отдельный `plan.txt`. + - **Критерии**: полнота требований, наличие негативных тестов (ошибочный ввод, снятие сверх баланса). + +--- + +## Билет 15. Организация программы: объявления/определения/память/область видимости +- **Теория 1**: Объявление vs определение, единицы трансляции, заголовочные файлы. +- **Теория 2**: Область видимости, время жизни объектов, стек/куча (в общих чертах). +- **Практика**: «Разделение на файлы» + - **Задание**: Разнести программу “Статистика слов” (из Билета 2) на 3 файла: + - `text_stats.h` — объявления функций, + - `text_stats.cpp` — реализации, + - `main.cpp` — ввод/вывод. + - **Требования**: + - В заголовке должны быть include guard’ы или `#pragma once`. + - Компиляция одной командой (пример): `g++ -std=c++17 -Wall -Wextra main.cpp text_stats.cpp`. + +--- + +## Билет 16. Тестирование и отладка +- **Теория 1**: Базовые подходы к тестированию (unit/manual), тесты на граничные случаи. +- **Теория 2**: Отладка: воспроизведение бага, минимальный пример, диагностика. +- **Практика**: «Найти и исправить ошибку ввода» + - **Задание**: Напишите программу, которая читает `n` и `n` чисел и печатает сумму. + Затем добавьте обработку ошибок: + - если ввод некорректный (не число) — вывести `error=bad_input` и завершиться; + - если `n < 0` — вывести `error=bad_n`. + - **Ввод**: `n` и далее поток данных пользователя. + - **Вывод**: либо `sum=<...>`, либо ошибка, как указано выше. + - **Примечание**: цель — показать корректную проверку `std::cin`. + +--- + +## Билет 17. Ввод/вывод и модель потоков +- **Теория 1**: Потоки: буферизация, форматированный и неформатированный ввод (идея). +- **Теория 2**: Обработка ошибок ввода: `failbit`, очистка состояния, игнорирование “мусора”. +- **Практика**: «Надёжное чтение целого» + - **Задание**: Реализуйте цикл, который читает целые числа до тех пор, пока пользователь не введёт слово `stop`. + - Суммировать все корректно введённые целые. + - Любые другие “плохие” токены (например `abc`, `12x`) пропускать и продолжать. + - **Ввод**: последовательность токенов (слова/числа) через пробел/перевод строки, заканчивается `stop`. + - **Вывод**: `sum=<...>`. + - **Требования**: + - Не завершаться на первой ошибке ввода. + - Аккуратно восстанавливать поток после ошибки (очистка флагов и чтение токена как строки). + + diff --git a/doc/lesson_12.md b/doc/lesson_12.md new file mode 100644 index 0000000..802fb15 --- /dev/null +++ b/doc/lesson_12.md @@ -0,0 +1,291 @@ +# Дополнительная тема: Умные указатели (Smart Pointers) + +**Длительность:** 2 пары (4 академических часа) - дополнительное занятие + +## Цели занятия +- Понять проблемы с обычными указателями +- Изучить концепцию RAII (Resource Acquisition Is Initialization) +- Освоить умные указатели: `unique_ptr`, `shared_ptr`, `weak_ptr` +- Научиться правильно использовать умные указатели в коде + +--- + +## Пара 1: Проблемы обычных указателей и RAII + +### Теоретический материал + +#### Проблемы с обычными указателями + +```cpp +// Проблема 1: Утечка памяти +void leak() { + int* ptr = new int[100]; + // Забыли вызвать delete[] + // Память утекла! +} + +// Проблема 2: Двойное освобождение +void doubleDelete() { + int* ptr = new int; + delete ptr; + delete ptr; // ОШИБКА! +} + +// Проблема 3: Использование после освобождения +void useAfterFree() { + int* ptr = new int; + delete ptr; + *ptr = 10; // ОШИБКА! Использование после освобождения +} + +// Проблема 4: Исключения +void exceptionProblem() { + int* ptr = new int[100]; + someFunction(); // Может выбросить исключение + delete[] ptr; // Не выполнится, если было исключение +} +``` + +#### Концепция RAII + +RAII (Resource Acquisition Is Initialization) - идиома C++, где: +- Ресурс захватывается в конструкторе +- Ресурс освобождается в деструкторе +- Деструктор вызывается автоматически при выходе из области видимости + +```cpp +// Пример RAII с классом +class Resource { + int* data; +public: + Resource(int size) { + data = new int[size]; + } + + ~Resource() { + delete[] data; // Автоматически освобождается + } +}; + +void useResource() { + Resource res(100); // Ресурс захвачен + // Использование res + // При выходе из функции деструктор автоматически освободит память + // Даже если произойдет исключение! +} +``` + +#### Зачем нужны умные указатели + +Умные указатели - это классы-обертки над обычными указателями, которые: +- Автоматически управляют памятью +- Следуют принципу RAII +- Предотвращают утечки памяти +- Безопасны при исключениях + +--- + +## Пара 2: Типы умных указателей + +### Теоретический материал + +#### std::unique_ptr + +`unique_ptr` - умный указатель с единоличным владением. Нельзя копировать, только перемещать. + +```cpp +#include + +// Создание unique_ptr +std::unique_ptr ptr1 = std::make_unique(42); +auto ptr2 = std::make_unique(100); // Рекомендуемый способ + +// Перемещение (не копирование!) +std::unique_ptr ptr3 = std::move(ptr1); // ptr1 теперь nullptr + +// Доступ к данным +*ptr2 = 50; +int value = *ptr2; + +// Проверка на nullptr +if (ptr2 != nullptr) { + // Использование +} + +// Освобождение памяти вручную (обычно не нужно) +ptr2.reset(); +ptr2 = nullptr; + +// Получение обычного указателя (осторожно!) +int* raw = ptr2.get(); +``` + +#### Примеры использования unique_ptr + +```cpp +// С массивом +std::unique_ptr arr = std::make_unique(10); +arr[0] = 1; +arr[1] = 2; + +// С пользовательским классом +class MyClass { +public: + MyClass(int x) : value(x) {} + void doSomething() {} +private: + int value; +}; + +std::unique_ptr obj = std::make_unique(42); +obj->doSomething(); + +// В функции +std::unique_ptr createValue() { + return std::make_unique(100); +} + +void useValue(std::unique_ptr ptr) { + // ptr владеет памятью + // При выходе из функции память автоматически освободится +} +``` + +#### std::shared_ptr + +`shared_ptr` - умный указатель с разделяемым владением. Использует подсчет ссылок. + +```cpp +#include + +// Создание shared_ptr +std::shared_ptr ptr1 = std::make_shared(42); +auto ptr2 = std::make_shared(100); + +// Копирование разрешено +std::shared_ptr ptr3 = ptr1; // Оба указывают на один объект +std::shared_ptr ptr4 = ptr1; + +// Подсчет ссылок +std::cout << ptr1.use_count() << std::endl; // Выведет 3 + +// Освобождение одного указателя +ptr3.reset(); // Счетчик уменьшится до 2 + +// Когда последний shared_ptr уничтожается, память освобождается +``` + +#### Примеры использования shared_ptr + +```cpp +class Resource { +public: + Resource() { std::cout << "Resource created\n"; } + ~Resource() { std::cout << "Resource destroyed\n"; } +}; + +void function1(std::shared_ptr res) { + // res использует ресурс + std::cout << "use_count: " << res.use_count() << std::endl; +} + +void function2(std::shared_ptr res) { + // res также использует ресурс + std::cout << "use_count: " << res.use_count() << std::endl; +} + +int main() { + auto res = std::make_shared(); + function1(res); // use_count: 2 + function2(res); // use_count: 2 + // При выходе из main память освободится автоматически + return 0; +} +``` + +#### std::weak_ptr + +`weak_ptr` - умный указатель, который не увеличивает счетчик ссылок. Используется для разрыва циклических ссылок. + +```cpp +#include + +std::shared_ptr shared = std::make_shared(42); +std::weak_ptr weak = shared; // Не увеличивает счетчик + +// Проверка, жив ли объект +if (auto locked = weak.lock()) { + // Объект еще существует, можно использовать + *locked = 100; +} else { + // Объект уже уничтожен +} + +// Пример с циклическими ссылками +struct Node { + std::shared_ptr next; + std::weak_ptr prev; // Используем weak_ptr для разрыва цикла +}; +``` + +#### Сравнение умных указателей + +| Тип | Владение | Копирование | Использование | +|-----|----------|-------------|---------------| +| `unique_ptr` | Единоличное | Только перемещение | Один владелец | +| `shared_ptr` | Разделяемое | Разрешено | Несколько владельцев | +| `weak_ptr` | Не владеет | Разрешено | Наблюдатель | + +### Практические примеры + +```cpp +// Класс с умными указателями +class Container { +private: + std::unique_ptr data; + int size; + +public: + Container(int s) : size(s) { + data = std::make_unique(size); + } + + // Деструктор не нужен! unique_ptr сам освободит память + // ~Container() {} - можно не писать + + int& operator[](int index) { + return data[index]; + } +}; + +// Фабричная функция +std::unique_ptr createMyClass(int value) { + return std::make_unique(value); +} + +// Передача в функцию +void process(std::unique_ptr ptr) { + // Владение передано функции +} + +void processRef(const std::unique_ptr& ptr) { + // Только использование, без передачи владения + *ptr = 100; +} +``` + +### Домашнее задание +- Переписать код с обычными указателями на умные указатели +- Создать класс, использующий `unique_ptr` для управления ресурсами +- Реализовать систему с `shared_ptr` и `weak_ptr` для разрыва циклических ссылок +- Изучить разницу между `make_unique`/`make_shared` и `new` +- Написать программу, демонстрирующую работу всех типов умных указателей + +### Дополнительные материалы +- Правило нуля (Rule of Zero) - использование умных указателей вместо ручного управления +- Кастомные удалители (custom deleters) +- `make_unique` vs `new` - преимущества `make_unique` +- Циклические ссылки и как их избегать +- Производительность умных указателей + + diff --git a/doc/lesson_13.md b/doc/lesson_13.md new file mode 100644 index 0000000..075ad38 --- /dev/null +++ b/doc/lesson_13.md @@ -0,0 +1,368 @@ +# Дополнительная тема: Итераторы (Iterators) + +**Длительность:** 2 пары (4 академических часа) - дополнительное занятие + +## Цели занятия +- Понять концепцию итераторов в C++ +- Изучить различные типы итераторов +- Освоить работу с итераторами STL контейнеров +- Научиться создавать собственные итераторы + +--- + +## Пара 1: Основы итераторов + +### Теоретический материал + +#### Что такое итератор? + +Итератор - это объект, который позволяет перебирать элементы контейнера, не зная его внутренней структуры. Итератор - это обобщение указателя. + +```cpp +#include +#include + +std::vector vec = {1, 2, 3, 4, 5}; + +// Обычный способ (с индексами) +for (size_t i = 0; i < vec.size(); ++i) { + std::cout << vec[i] << " "; +} + +// С итераторами +for (std::vector::iterator it = vec.begin(); it != vec.end(); ++it) { + std::cout << *it << " "; +} + +// С auto (C++11) +for (auto it = vec.begin(); it != vec.end(); ++it) { + std::cout << *it << " "; +} + +// Range-based for (C++11) - использует итераторы под капотом +for (int value : vec) { + std::cout << value << " "; +} +``` + +#### Базовые операции с итераторами + +```cpp +std::vector vec = {10, 20, 30, 40, 50}; + +// Получение итераторов +auto begin = vec.begin(); // Итератор на первый элемент +auto end = vec.end(); // Итератор после последнего элемента + +// Разыменование +int first = *begin; // 10 + +// Инкремент +++begin; // Переход к следующему элементу +int second = *begin; // 20 + +// Сравнение +if (begin != end) { + // Итератор валиден +} + +// Арифметика (для итераторов произвольного доступа) +auto it = vec.begin(); +it += 2; // Переход на 2 позиции вперед +int third = *it; // 30 + +it -= 1; // Переход на 1 позицию назад +int second_again = *it; // 20 +``` + +#### Типы итераторов + +В C++ существует 5 категорий итераторов: + +1. **Input Iterator** - только чтение, однонаправленный +2. **Output Iterator** - только запись, однонаправленный +3. **Forward Iterator** - чтение и запись, однонаправленный +4. **Bidirectional Iterator** - чтение и запись, двунаправленный +5. **Random Access Iterator** - чтение и запись, произвольный доступ + +```cpp +// Forward Iterator (например, std::forward_list) +std::forward_list flist = {1, 2, 3}; +for (auto it = flist.begin(); it != flist.end(); ++it) { + std::cout << *it << " "; +} +// Можно: ++it +// Нельзя: --it, it + 5 + +// Bidirectional Iterator (например, std::list) +std::list list = {1, 2, 3}; +for (auto it = list.begin(); it != list.end(); ++it) { + std::cout << *it << " "; +} +for (auto it = list.rbegin(); it != list.rend(); ++it) { + std::cout << *it << " "; // Обратный порядок +} +// Можно: ++it, --it +// Нельзя: it + 5 + +// Random Access Iterator (например, std::vector) +std::vector vec = {1, 2, 3, 4, 5}; +auto it = vec.begin(); +it += 3; // Можно +it -= 2; // Можно +int value = it[1]; // Можно +int dist = it - vec.begin(); // Можно +``` + +--- + +## Пара 2: Работа с итераторами STL + +### Теоретический материал + +#### Итераторы для различных контейнеров + +```cpp +#include +#include +#include +#include +#include + +// std::vector - Random Access Iterator +std::vector vec = {1, 2, 3, 4, 5}; +for (auto it = vec.begin(); it != vec.end(); ++it) { + *it *= 2; // Можно изменять +} + +// std::list - Bidirectional Iterator +std::list list = {1, 2, 3, 4, 5}; +for (auto it = list.begin(); it != list.end(); ++it) { + *it *= 2; +} + +// std::set - Bidirectional Iterator (только чтение значений) +std::set set = {1, 2, 3, 4, 5}; +for (auto it = set.begin(); it != set.end(); ++it) { + std::cout << *it << " "; // Только чтение + // *it = 10; // ОШИБКА! Нельзя изменять элементы set +} + +// std::map - Bidirectional Iterator +std::map map = {{"one", 1}, {"two", 2}}; +for (auto it = map.begin(); it != map.end(); ++it) { + std::cout << it->first << ": " << it->second << std::endl; + it->second = 100; // Можно изменять значение + // it->first = "new"; // ОШИБКА! Ключ нельзя изменять +} +``` + +#### Обратные итераторы + +```cpp +#include +#include + +std::vector vec = {1, 2, 3, 4, 5}; + +// Обратный итератор +for (auto it = vec.rbegin(); it != vec.rend(); ++it) { + std::cout << *it << " "; // 5 4 3 2 1 +} + +// Преобразование обратного итератора в обычный +auto rit = vec.rbegin(); +auto it = rit.base(); // Обычный итератор +``` + +#### Константные итераторы + +```cpp +std::vector vec = {1, 2, 3, 4, 5}; + +// Обычный итератор (можно изменять) +for (auto it = vec.begin(); it != vec.end(); ++it) { + *it = 10; // Можно +} + +// Константный итератор (нельзя изменять) +for (auto it = vec.cbegin(); it != vec.cend(); ++it) { + std::cout << *it << " "; // Можно читать + // *it = 10; // ОШИБКА! Нельзя изменять +} + +// Константный контейнер +const std::vector cvec = {1, 2, 3}; +for (auto it = cvec.begin(); it != cvec.end(); ++it) { + // it автоматически const_iterator + // *it = 10; // ОШИБКА! +} +``` + +#### Использование итераторов с алгоритмами STL + +```cpp +#include +#include +#include + +std::vector vec = {5, 2, 8, 1, 9}; + +// Поиск +auto it = std::find(vec.begin(), vec.end(), 8); +if (it != vec.end()) { + std::cout << "Найдено на позиции: " << it - vec.begin() << std::endl; +} + +// Сортировка +std::sort(vec.begin(), vec.end()); + +// Поиск минимума/максимума +auto minIt = std::min_element(vec.begin(), vec.end()); +auto maxIt = std::max_element(vec.begin(), vec.end()); + +// Подсчет +int count = std::count(vec.begin(), vec.end(), 5); + +// Сумма +int sum = std::accumulate(vec.begin(), vec.end(), 0); + +// Заполнение +std::fill(vec.begin(), vec.end(), 0); + +// Трансформация +std::transform(vec.begin(), vec.end(), vec.begin(), + [](int x) { return x * 2; }); +``` + +#### Вставка и удаление с итераторами + +```cpp +#include +#include + +// std::vector +std::vector vec = {1, 2, 3, 4, 5}; +auto it = vec.begin() + 2; +vec.insert(it, 99); // Вставка перед позицией it +vec.erase(it); // Удаление элемента (it инвалидирован!) + +// std::list +std::list list = {1, 2, 3, 4, 5}; +auto it = list.begin(); +std::advance(it, 2); // Переход на 2 позиции +list.insert(it, 99); // Вставка +it = list.erase(it); // Удаление, it указывает на следующий элемент +``` + +#### Создание собственного итератора + +```cpp +#include + +// Простой итератор для массива +template +class ArrayIterator { +private: + T* ptr; + +public: + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = T*; + using reference = T&; + + ArrayIterator(T* p) : ptr(p) {} + + // Базовые операции + T& operator*() { return *ptr; } + T* operator->() { return ptr; } + + // Инкремент + ArrayIterator& operator++() { + ++ptr; + return *this; + } + + ArrayIterator operator++(int) { + ArrayIterator tmp = *this; + ++ptr; + return tmp; + } + + // Декремент + ArrayIterator& operator--() { + --ptr; + return *this; + } + + // Сравнение + bool operator==(const ArrayIterator& other) const { + return ptr == other.ptr; + } + + bool operator!=(const ArrayIterator& other) const { + return ptr != other.ptr; + } + + // Арифметика (для Random Access) + ArrayIterator operator+(difference_type n) const { + return ArrayIterator(ptr + n); + } + + difference_type operator-(const ArrayIterator& other) const { + return ptr - other.ptr; + } +}; + +// Использование +int arr[] = {1, 2, 3, 4, 5}; +ArrayIterator begin(arr); +ArrayIterator end(arr + 5); + +for (auto it = begin; it != end; ++it) { + std::cout << *it << " "; +} +``` + +### Практические примеры + +```cpp +// Поиск и удаление элементов +std::vector vec = {1, 2, 3, 4, 5, 2, 6, 2}; +int value = 2; + +// Удаление всех вхождений +vec.erase( + std::remove(vec.begin(), vec.end(), value), + vec.end() +); + +// Работа с поддиапазонами +std::vector vec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; +auto start = vec.begin() + 2; +auto finish = vec.begin() + 7; + +// Сортировка поддиапазона +std::sort(start, finish); + +// Поиск в поддиапазоне +auto it = std::find(start, finish, 5); +``` + +### Домашнее задание +- Реализовать функции поиска с использованием итераторов +- Создать функцию для работы с любым контейнером через итераторы +- Реализовать простой итератор для собственного класса +- Использовать алгоритмы STL с итераторами +- Написать код, работающий с разными типами контейнеров через единый интерфейс итераторов + +### Дополнительные материалы +- Итераторные адаптеры (back_inserter, front_inserter) +- Stream итераторы +- Итераторы вставки (insert iterators) +- Концепты итераторов (C++20) +- Range-based for и его связь с итераторами + +