Лабораторная работа №4. Итераторы, указатели на функцию

Для решения каждой задачи потребуется создать несколько функций, которые требуют комментариев. Проект должен состоять из трёх файлов: main.cpp,  Lesson4.cpp, Lesson4.h. Перед тем, как приступить к выполнению задания, создать пустой проект и добавить три файла-заготовки. Пользуемся функциями printVector для печати элементов вектора и VectorWithRandomNumbers для создания вектора, заполненного случайными значениями

  1. Дан вектор вещественных чисел. Найти сумму и среднее арифметическое его элементов. Решать задачу при помощи функции void sumAndAverage(vector<double>, double&, double&);
    Указание 1: Для обхода элементов вектора использовать конструкцию

    for (auto x : a) {// x - название переменной, а - имя вектора
    		//нужные действия
    	}
    
    Указание 2: Для вычисления размера вектора используем метод size();
  2. Создать функцию, которая обнуляет отрицательные и удваивает положительные элементы целочисленного вектора 
    Указание: Для обхода элементов вектора использовать конструкцию

    for (auto &x : a) {
    		//нужные действия
    	}
    
  3. Создать функцию int filterDouble(vector<double> a, vector<double> &b, PredDouble p), которая переписывает в вектор b элементы вектора a, удовлетворяющие предикату (функции, возвращающей логическое значение) p и возвращает их количество.
    Указание 1: Тип PredDouble - указатель на функцию, определяется в файле Lesson4.h следующим образом:
    typedef bool(*PredDouble)(double);
    
    Указание 2: Существует два способа задать предикат. Первый - определить функцию-предикат, например
    bool isPositive(double x) {
    	return x > 0;
    }
    
    и затем обратиться к filterDouble следующим образом:
    	filterDouble(a, b, isPositive);
    
    второй способ - воспользоваться лямбда-выражением
    	filterDouble(a, b, [](double x) {return (x > 0); });
    
    Указание 3: Для заполнения вектора b пользуемся методами clear() и push_back()
    Указание 4: При необходимости подключить заголовочный файл
    #include<iterator>
    В функции main() вызвать эту функцию для массива случайных вещественных чисел со следующими предикатами
    • предикат, возвращающий истину для положительных чисел;
    • предикат, возвращающий истину для чисел, косинус которых - положительный;
    • придумать два своих предиката;
  4. Описать функцию void intFilter(vector<int> &a, PredInt p) которая удаляет из вектора все элементы, удовлетворяющие предикату p.
    Указание 1: Тип PredInt - указатель на функцию, определяется в файле Lesson4.h следующим образом:
    typedef bool(*PredInt)(int);
    
    Указание 2: Для обхода вектора используем итераторы
    	auto it = a.begin();   //объявляем итератор 
    	while (it != a.end())  // it.begin() - указатель на первый элемент вектора, it.end() - на последний;
    		if (/*условие*/) { //обращаемся к элементу вектора при помощи оператора разыменования *it;
    			// совершаем действия
    			it = a.erase(it);//удаляем элемент
    		}
    		else ++it;//переходим на следующий элемент		
    
    В функции main() вызвать эту функцию для массива случайных вещественных чисел со следующими предикатами
    • предикат, возвращающий истину для положительных чисел;
    • предикат, возвращающий истину для чётных чисел;
    • придумать два своих предиката;

Дополнительные задачи

  1. Описать функцию void intEmplace(vector& a, PredInt p), которая "дублирует" элементы удовлетворяющие предикату p

    Указание: используем итераторы и метод insert()

    Пример: Для случайно сгенерированного вектора
    3 2 9 -4 -6 4 -5 3 -3 -1
    
    вызов
    	intEmplace(a, [](int x) {return (x > 0); });
    
    даёт результат:
    3 3 2 2 9 9 -4 -6 4 4 -5 3 3 -3 -1
  2. Создать функцию-шаблон
    template<class T>
    vector<T> intZipWith(vector<T> a, vector<T> b, function<T(T, T)> f)
    которая принимает два вектора одинаковой длины и возвращает вектор, сформированный по следующему правилу:
    	c[i]=f(a[i],b[i]);
    
    Например, для векторов
    a: 4, 5, -2, -10, -3, 0, -5, -4, -5, -5
    b: 8, 7, -8,   4,  3, 3, -4,  6, -2,  2
    
    Вызов
    auto c = intZipWith(a, b, [](int a, int b) {return a + b; });
    
    даёт результат
    12, 12, -10, -6, 0, 3, -9, 2, -7, -3
    
    Продемонстрировать использование функции для векторов типа int и типа double, для каждого типа придумать по два предиката

    Указание: Подключаем заголовочный файл

    #include<functional>