Лабораторная работа №6. std::array, std::span и указатели на функции
Цель занятия: закрепить контейнер фиксированного размера и научиться передавать функцию или предикат как параметр алгоритма.
Необходимые темы и конструкции C++:
std::array: инициализация,size,fill,front,back, итераторы- указатели на функции и псевдонимы через
using - callback-функции, предикаты и массивы указателей на функции
std::spanтолько как обзорное невладеющее представление диапазона
Структура проекта
Разместите решение в следующих файлах:
main.cppcallbacks.hcallbacks.cpp
Общие требования
- Соблюдайте указанные сигнатуры функций: ввод и вывод организуйте в
main. - Проверьте каждую функцию не менее чем на трёх наборах данных, включая граничный случай.
- Не используйте средства, которые не перечислены в разделе необходимых тем, если условие прямо их не разрешает.
std::span в лекции вводится обзорно. В этой работе ни одно задание не требует его применения; используйте std::array и привычную пару «указатель + размер».Основные задания
-
Обработка std::array
Для массива из восьми вещественных измерений вычислить сумму, среднее и число элементов, превышающих среднее. Реализуйте вычисления обычными циклами по
std::array.Требуемая сигнатура:
double sum
(const std::array<double, 8>& values);double mean(const std::array<double, 8>& values); int count_above(const std::array<double, 8>& values, double level);Входные данные / вызов Результат [2, 4, 4, 6, 8, 8, 8, 8]mean=6; count_above=4 -
Преобразование массива функцией
Применить переданную функцию к каждому элементу массива. Проверьте алгоритм с функциями возведения в квадрат, изменения знака и увеличения на единицу.
Требуемая сигнатура:
using Transform = int(*)(int); void transform(int* data, size_t size, Transform operation);Требования:
- Перед вызовом проверьте, что указатель на функцию не равен
nullptr.
Входные данные / вызов Результат [1, -2, 3], square[1, 4, 9] - Перед вызовом проверьте, что указатель на функцию не равен
-
Отбор по предикату
Скопировать в результирующий массив элементы исходного массива, для которых предикат возвращает
true. Функция возвращает число записанных элементов.Требуемая сигнатура:
using Predicate = bool(*)(int); int copy_if(const int* source, size_t size, int* result, Predicate predicate);Требования:
- Сохраните исходный порядок элементов.
- Проверьте функции
is_even,is_positiveиis_two_digit.
Входные данные / вызов Результат [-12, 5, 18, 0, 7], is_two_digit[-12, 18]; size=2 -
Отбор по предикату
Дан массив вещественных чисел размера size. Также дана функция-предикат, принимающая вещественный параметр и возвращающая логическое значение. Преобразовать массив, сместив элементы, удовлетворяющие предикату к началу массива. Функция возвращает количество "хороших" элементов, удовлетворяющих предикату. Для определения типа предиката определяем указатель на функцию
using double_predicate = bool(*)(double);
Сигнатура функции следующая:size_t filter_double(double* array, size_t size, double_predicate pred);
Проверить работы для функции, возвращающей истину для функции, возвращающей истину для положительных чисел, а также для функции, возвращающей истину для чисел, по модулю меньших переменной LIMIT. Переменную LIMIT определяем в заголовочном файле следующим образомextern double LIMIT;
затем определяем саму функциюbool limited(double x);
а в main.cpp сперва перед функцией main определяем LIMITdouble LIMIT;
и в самой функции main() присваиваем ей значениеLIMIT = 1; //(например)
-
Обработка двух массивов
Даны два массива целых чисел одинакового размера. Также дана функция f, принимающая два целых параметра и возвращающая целое значение. Построить новый массив по правилу
c[i] = f(a[i], b[i]);
Определяем указатель на функциюusing zip_int = int(*)(int, int);
Сигнатура функции следующая:template<size_t N>
array<int, N> zip_arrays(const array<int, N>& a, const array<int, N>& b, zip_int f);Проверить работы для функций, возвращающих сумму и максимум двух целых чисел.
Домашнее задание
-
Нормализация измерений
Преобразовать непостоянный массив вещественных чисел так, чтобы его минимальный элемент стал 0, а максимальный — 1:
\[ y_i=\frac{x_i-x_{min}}{x_{max}-x_{min}}. \]Требуемая сигнатура:
void normalize(std::array<double, 10>& values);Требования:
- Если все элементы равны, заполните массив нулями.
-
Табличный калькулятор
Создать массив указателей на четыре функции: сложение, вычитание, умножение и деление. По номеру операции вызвать соответствующую функцию.
Требуемая сигнатура:
using BinaryOperation = double(*)(double, double); double calculate(double left, double right, int operation, const std::array<BinaryOperation, 4>& operations);Требования:
- Номер операции должен находиться в диапазоне 0–3.
- Деление на ноль обработайте до вызова функции деления.
-
Обработка строк матрицы по условию
Для каждой строки статической матрицы, удовлетворяющей предикату, вычислить значение переданного агрегатора. Предикат проверяет строку целиком, агрегатор получает указатель на её первый элемент и длину.
Требуемая сигнатура:
using RowPredicate = bool(*)(const int*, int); using RowAggregate = long long(*)(const int*, int); constexpr int COLS = 4; void process_rows(const int matrix[][COLS], int rows, RowPredicate predicate, RowAggregate aggregate);Требования:
- Проверьте предикат «все элементы положительны» и агрегатор суммы.