Функция for_each в библиотеке vector

134
02 января 2021, 06:30

Нужно выполнить задание:

Поменять знак у всех элементов массива между первым максимальным и последним максимальным элементами.

Подсказали с помощью функции for_each сделать. Но стоит вопрос, как передать функцию саму как аргумент в for_each?

Нашел вариант void(*pfi)(int) = fun;, не сработало.

#define _CRT_SECURE_NO_WARNINGS 
#include <iostream> 
#include <stdio.h> 
#include <conio.h> 
#include <vector>
#include <string>
#include <algorithm>  
using namespace std;
void fun(vector<int> &v);
int main () {
    setlocale(LC_ALL, "Rus");
    int N, k;
    cout << "Введите количество элементов" << endl;
cin >> N;
    vector <int> v(N);   
    cout << "Введите элементы" << endl;
    for (int i = 0; i < N; i++)  
    {
        cin >> v[i];                    
    }
    cout << "Значения второго вектора " << endl;
    for (int i = 0; i < N; i++) {
        cout << v[i] << " ";
    }
    cout << endl<< "какому числу должно быть кратное? k= " << endl;
    cin >> k;
    double sum = 0;
    int kol = 0;
    for (int i = 0; i <N; i++)
    {
        if (v[i]%k == 0) {
            sum += v[i];
            kol += 1;
        }
    }
    cout << sum / kol << endl;
    auto max =  *max_element(v.begin(), v.end());
    cout << "Максимум " << max << endl;
    void(*pfi)(int) = fun;

    auto kon = std::find(v.rbegin(), v.rend(), max);
    if (kon != v.rend()) {
        std::for_each(max, kon, pfi);
    }
    _getch();
return 0;
}
void fun(vector<int> v) {
    int i;
    cout << v[i] * (-1);
}

Попытался сделать без этой функции, тоже показывает ошибку, ругается на v[beg] *= -1;

vector<int> fun(vector<int> v,vector<int>::iterator beg, vector<int>::iterator end) {
    while (beg != end)
    {
        v[beg] *= -1;
        beg++;
    }
    return v;
}

И как последний вопрос, нашел код в интернете:

#include <vector>
#include <algorithm>
#include <iostream>
struct Sum {
    Sum() { sum = 0; }
    void operator()(int n) { sum += n; }
    int sum;
};
int main()
{
    std::vector<int> nums{3, 4, 2, 9, 15, 267};
    std::cout << "до: ";
    for (auto n : nums) {
        std::cout << n << " ";
    }
    std::cout << '\n';
    std::for_each(nums.begin(), nums.end(), [](int &n){ n++; });
    Sum s = std::for_each(nums.begin(), nums.end(), Sum());
    std::cout << "после:  ";
    for (auto n : nums) {
        std::cout << n << " ";
    }
    std::cout << '\n';
    std::cout << "сумма: " << s.sum << '\n';
}

Можете подсказать, что означает:

std::for_each(nums.begin(), nums.end(), [](int &n){ n++; }); 

, т.е все, что стоит после квадратных скобок?

Answer 1

А зачем обязательно через for_each? вот такой способ - чем хуже?

void doit(vector<int>&v)
{
    if (v.empty()) return;
    int b = 0, e = 0, m = v[0];
    for(int i = 0; i < v.size(); ++i)
    {
        if (v[i] > m)        m = v[b = e = i];
        else if (v[i] == m)  e = i;
    }
    for(int i = b+1; i < e; ++i)
        v[i] = -v[i];
}
Answer 2
  1. Оператор вектора operator[] не может принимать итератор, а принимает беззнаковый целый тип(индекс), поэтому v[beg] *= -1; ошибка. Вместо этого должно быть *beg = -1;
  2. И вы пытаетесь решать какую то другую задачу, не имеющую связь с заданием, которую нужно выполнить. Или же вы просто не смогли найти правильный подход. Ниже пример функции, которая может решать задачу тримя способами, последный из которых считаю вариантом лучше и проще, чем неоднократные вызовы функции и лишняя писанина. И, так как в задании не говорится о типах элементов, я ее сделал шаблонным:

    //некоторая функция
    template<typename T>
    void fun(T& i) { i *= 10; }        
    // режимы для решения задачи разными способами
    enum Mode{old_metod, new_metod, prefer_metod};
    // для массивов и контейнеров, поддерживающих двунаправленный итератор
    template < class Cont>
    void answer(Cont& v, Mode mode = prefer_metod )
    {
        auto first  = std::begin(v), last = std::end(v);
        if (first == last) return;
        // находим максимальный
        first = std::max_element(first, last);
        //находим последный элемент, имеющий такое значение
        while (*--last != *first);
        //если еще есть такой и они не соседные
        // то выполняем операцию над элементами между ними
        if (first++ != last) {
            using Tp = decltype(*first); //тип элементов
            switch (mode) {
            case old_metod:
                std::for_each(first, last,  std::ptr_fun(fun<Tp>));
                break;
            case new_metod:
                std::for_each(first, last, [](Tp& i) {i += 10;});
                break;
            default:
               while (first != last)
                   *first++ *= -1;
            }
        }
    }
    

    Осталось передать в функцию выбранный вами контейнер (можно массив) и режим

READ ALSO
Есть ли способ передать значение из QString в QGraphicsTextItem?

Есть ли способ передать значение из QString в QGraphicsTextItem?

Делаю график в QtНужно подписать координатные оси

112
Qt LineEdit search in the site

Qt LineEdit search in the site

В моем приложении у меня есть LineEdit и мне нужно при вводе, к примеру - "Собака" на определенном сайте выводился результат поискаПодскажите пожалуйста...

101
Как повернуть спрайт не от нижнего левого угла?

Как повернуть спрайт не от нижнего левого угла?

Переписал на си функцию glm::rotate, теперь хочу сделать так, чтобы можно было повернуть изображение относительно другой координаты, а не координаты...

98