Библиотечный метод
Продемонстрируйте работу метода сортировки вставками по возрастанию. Для этого выведите состояние данного массива после каждой вставки на отдельных строках. Если массив упорядочен изначально, не нужно ничего выводить.
Формат входных данных:
На первой строке дано целое число n (1 ≤ n ≤ 100) – количество элементов в массиве. На второй строке задан сам массив: последовательность натуральных чисел, не превышающих 10^9.
Формат выходных данных:
В выходной файл выведите строки (по количеству вставок) по n чисел каждая.
Продемонстрируйте работу метода сортировки вставками по возрастанию. Для этого выведите состояние данного массива после каждой вставки на отдельных строках. Если массив упорядочен изначально, не нужно ничего выводить.
Формат входных данных:
На первой строке дано целое число n (1 ≤ n ≤ 100) – количество элементов в массиве. На второй строке задан сам массив: последовательность натуральных чисел, не превышающих 10^9.
Формат выходных данных:
В выходной файл выведите строки (по количеству вставок) по n чисел каждая.
Общие хитрости для C++
Никогда не используйте INT_MAX в качестве бесконечности для целых чисел. В некоторых алгоритмах, например, Флойда–Уоршелла, используются значения вроде ∞+w, что приведёт к переполнению при использовании INT_MAX. Вместо этого лучше использовать int oo = 0x3f3f3f3f, поскольку:
• Это число достаточно большое для задач, связанных с целыми числами;
• 2 * oo не приведёт к переполнению;
• Все байты равны, поэтому вы без проблем можете использовать memset(array, oo, sizeof(array));
• Его довольно легко запомнить.
Однако будьте осторожны: не используйте 0x3f3f3f3f для long long, так как в таком случае фокус уже не пройдёт, и вы потом потратите кучу времени на поиск ошибки.
Никогда не используйте INT_MAX в качестве бесконечности для целых чисел. В некоторых алгоритмах, например, Флойда–Уоршелла, используются значения вроде ∞+w, что приведёт к переполнению при использовании INT_MAX. Вместо этого лучше использовать int oo = 0x3f3f3f3f, поскольку:
• Это число достаточно большое для задач, связанных с целыми числами;
• 2 * oo не приведёт к переполнению;
• Все байты равны, поэтому вы без проблем можете использовать memset(array, oo, sizeof(array));
• Его довольно легко запомнить.
Однако будьте осторожны: не используйте 0x3f3f3f3f для long long, так как в таком случае фокус уже не пройдёт, и вы потом потратите кучу времени на поиск ошибки.
Введение в UB
В языке C++ важную роль играют понятия неопределенное поведение undefined behavior, UB и определяемое реализацией поведение implementation-defined behavior, IB, характеризующие действия, результаты которых не определяются стандартом языка.
Когда некоторое действие объявляется как порождающее UB, это означает, что программист не должен полагаться на какой-то определенный результат — всё зависит от выбора компилятора в данном конкретном случае и особенностей платформы, причём разработчики платформы и компилятора не обязаны указывать в документации последствия такого действия. В случае IB, разработчик компилятора должен выбрать некоторую, разумную с его точки зрения, реализацию и описать это в документации.
Например, компилятор g++ известен тем, что при определённых условиях просто выбрасывает из программы участки, зависящие от неопределённого поведения.
К сожалению, программа, опирающаяся на конкретное поведение на данной платформе с данным компилятором, строго говоря, не является переносимой. Часто использование конструкций, эффект которых заявлен как IB или UB, является неосознанным из-за невнимательности, недостатка опыта или знаний программиста. Если, например, поведение программы различается в отладочной (debug, оптимизация машинного кода компилятором выключена) и окончательной (release, оптимизация включена) сборках, то, скорее всего, виноват код, порождающий UB.
В языке C++ важную роль играют понятия неопределенное поведение undefined behavior, UB и определяемое реализацией поведение implementation-defined behavior, IB, характеризующие действия, результаты которых не определяются стандартом языка.
Когда некоторое действие объявляется как порождающее UB, это означает, что программист не должен полагаться на какой-то определенный результат — всё зависит от выбора компилятора в данном конкретном случае и особенностей платформы, причём разработчики платформы и компилятора не обязаны указывать в документации последствия такого действия. В случае IB, разработчик компилятора должен выбрать некоторую, разумную с его точки зрения, реализацию и описать это в документации.
Например, компилятор g++ известен тем, что при определённых условиях просто выбрасывает из программы участки, зависящие от неопределённого поведения.
К сожалению, программа, опирающаяся на конкретное поведение на данной платформе с данным компилятором, строго говоря, не является переносимой. Часто использование конструкций, эффект которых заявлен как IB или UB, является неосознанным из-за невнимательности, недостатка опыта или знаний программиста. Если, например, поведение программы различается в отладочной (debug, оптимизация машинного кода компилятором выключена) и окончательной (release, оптимизация включена) сборках, то, скорее всего, виноват код, порождающий UB.
Введение в обработку исключений
Одним из преимуществ C++ перед C является обработка исключений. Исключения - это ненормальные условия, с которыми программа сталкивается во время своего выполнения.
Есть два типа исключений: а) синхронные, б) асинхронные (например, которые находятся вне контроля программы, сбой диска и т. д.). Для этой цели C++ предоставляет следующие специализированные ключевые слова.
try: представляет блок кода, который может вызвать исключение.
catch: представляет блок кода, который выполнится при возникновении определенного исключения.
throw: используется для создания исключения. Также используется для перечисления исключений, которые генерирует функция, но не обрабатывает себя.
Одним из преимуществ C++ перед C является обработка исключений. Исключения - это ненормальные условия, с которыми программа сталкивается во время своего выполнения.
Есть два типа исключений: а) синхронные, б) асинхронные (например, которые находятся вне контроля программы, сбой диска и т. д.). Для этой цели C++ предоставляет следующие специализированные ключевые слова.
try: представляет блок кода, который может вызвать исключение.
catch: представляет блок кода, который выполнится при возникновении определенного исключения.
throw: используется для создания исключения. Также используется для перечисления исключений, которые генерирует функция, но не обрабатывает себя.
Пример UB (Undefined behavior)
Ярким примером UB и ошибочного кода является повторное использование (в том числе повторное изменение) изменяемой переменной при вычислении выражения, когда относительный порядок вычисления термов не определен (то же касается фактических параметров функции в точке вызова).
Ярким примером UB и ошибочного кода является повторное использование (в том числе повторное изменение) изменяемой переменной при вычислении выражения, когда относительный порядок вычисления термов не определен (то же касается фактических параметров функции в точке вызова).
Функция std::stold
Функция
Возвращаемое значение:
Возвращает значение типа
#для_начинающих
Функция
std::stold
из стандартной библиотеки C++ преобразует строку, представляющую десятичное число с плавающей запятой, в тип long double
.Возвращаемое значение:
Возвращает значение типа
long double
, полученное из преобразованной строки.#для_начинающих
std::consume
Синтаксис:
#для_продвинутых
std::consume
— это функция, предназначенная для потребления значения из атомарной переменной. Она гарантирует, что все изменения, сделанные в атомарной переменной до вызова std::consume, будут видны в потоке, который ее вызывает.Синтаксис:
void std::consume(std::atomic<T>& var);
#для_продвинутых
#вопросы_с_собеседований
Как можно использовать лямбда-выражения в C++ для создания анонимных блоков кода, которые могут изменять переменные захваченного контекста без изменения сигнатуры лямбды?
В C++ можно использовать лямбда-выражения с захватом по ссылке, чтобы анонимный блок кода мог изменять переменные из внешнего контекста. Захват по ссылке указывается с помощью символа & в списке захвата лямбды. Это позволяет лямбде изменять значения переменных, не меняя при этом сигнатуру лямбды.
В этом примере лямбда modifyX захватывает переменную x по ссылке и изменяет её значение. Такой подход позволяет лямбдам влиять на состояние переменных в области видимости, где они были определены, без необходимости изменять сигнатуру лямбды.
Как можно использовать лямбда-выражения в C++ для создания анонимных блоков кода, которые могут изменять переменные захваченного контекста без изменения сигнатуры лямбды?
В C++ можно использовать лямбда-выражения с захватом по ссылке, чтобы анонимный блок кода мог изменять переменные из внешнего контекста. Захват по ссылке указывается с помощью символа & в списке захвата лямбды. Это позволяет лямбде изменять значения переменных, не меняя при этом сигнатуру лямбды.
В этом примере лямбда modifyX захватывает переменную x по ссылке и изменяет её значение. Такой подход позволяет лямбдам влиять на состояние переменных в области видимости, где они были определены, без необходимости изменять сигнатуру лямбды.
Функция std::atomic_store
Функция
В примере на картинке функция
#для_продвинутых
Функция
std::atomic_store
используется для атомарного изменения значения атомарной переменной. Это означает, что изменение значения происходит мгновенно и не может быть прервано другими потоками.В примере на картинке функция
atomic_store
используется для атомарного увеличения значения счетчика counter на 1
. Функция atomic_load
используется для получения нового значения счетчика.#для_продвинутых
Функция std::count
Функция
#для_начинающих
Функция
std::count
используется для подсчета количества элементов в диапазоне, которые совпадают с заданным значением. Она работает с итераторами, что позволяет использовать ее с различными типами контейнеров, таких как массивы, векторы, списки и т.д.#для_начинающих
Функция std::find_end
Функция
Синтаксис:
#для_продвинутых
Функция
std::find_end
в С++ используется для поиска последнего вхождения подпоследовательности элементов в заданном диапазоне. Она работает с итераторами, что делает её универсальной для различных контейнеров, таких как массивы, векторы, списки и т.д.Синтаксис:
template < class ForwardIterator1, class ForwardIterator2 >
ForwardIterator1 find_end ( ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2 );
#для_продвинутых
std::partial_sum()
Функция
Функция вычисляет частичные суммы элементов в диапазоне от
#для_продвинутых
Функция
std::partial_sum()
из библиотеки стандартных алгоритмов языка C++ вычисляет частичные суммы элементов в диапазоне. Частичная сумма — это сумма элементов, разделенная на несколько частей. Функция вычисляет частичные суммы элементов в диапазоне от
first
до last
и записывает их в диапазон, начиная с d_first
. При этом используется указанный в качестве первого аргумента оператор сложения. Если в качестве первого аргумента не указан оператор, то используется оператор сложения по умолчанию.#для_продвинутых
std::reduce
Функция
1. Она начинается с первого элемента последовательности.
2. Она применяет функцию к первому элементу и к начальному значению.
3. Она сохраняет результат.
4. Она повторяет эти шаги для каждого последующего элемента последовательности.
В результате функция
#для_продвинутых
Функция
std::reduce
в C++ используется для объединения элементов последовательности в одно значение. std::reduce
работает следующим образом:1. Она начинается с первого элемента последовательности.
2. Она применяет функцию к первому элементу и к начальному значению.
3. Она сохраняет результат.
4. Она повторяет эти шаги для каждого последующего элемента последовательности.
В результате функция
std::reduce
возвращает значение, которое является объединением всех элементов последовательности.#для_продвинутых
std::pair
Для объявления переменной типа
где:
#для_продвинутых
std::pair
— это шаблон класса, который позволяет хранить два значения одного или разных типов в одной переменной.Для объявления переменной типа
std::pair
используется следующий синтаксис:std::pair<Тип1, Тип2> имя_переменной;
где:
Тип1
— тип первого значенияТип2
— тип второго значенияимя_переменной
— имя переменной#для_продвинутых
Библиотека Fast Light Toolkit
Fast Light Toolkit (FLTK) — это кроссплатформенный инструментарий для создания графических интерфейсов (GUI) на языке программирования C++. Она поддерживает такие операционные системы, как UNIX/Linux(X11), Microsoft Windows и macOS.
FLTK предлагает современные функции для создания GUI, при этом оставаясь компактной и не перегруженной лишними компонентами. Библиотека также поддерживает 3D-графику через OpenGL и его встроенную эмуляцию GLUT.
#для_продвинутых
Fast Light Toolkit (FLTK) — это кроссплатформенный инструментарий для создания графических интерфейсов (GUI) на языке программирования C++. Она поддерживает такие операционные системы, как UNIX/Linux(X11), Microsoft Windows и macOS.
FLTK предлагает современные функции для создания GUI, при этом оставаясь компактной и не перегруженной лишними компонентами. Библиотека также поддерживает 3D-графику через OpenGL и его встроенную эмуляцию GLUT.
#для_продвинутых
Фреймворк Catch2
Catch2 — это современный фреймворк для модульного тестирования на C++, простой, но при этом обладающий всеми необходимыми функциями.
Он подходит как для TDD (разработки через тестирование), так и для BDD (поведенческого тестирования).
#для_начинающих
Catch2 — это современный фреймворк для модульного тестирования на C++, простой, но при этом обладающий всеми необходимыми функциями.
Он подходит как для TDD (разработки через тестирование), так и для BDD (поведенческого тестирования).
#для_начинающих