0

I am new to C++, and I have run into a total lack of understanding on how to sum only even values stored in a vector in C++.

The task itself requests a user to input some amount of random integers, stop when input is 0, and then to return the amount of even values and the sum of those even values.

This is as far as I have managed to get:

#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>
#include <numeric>

using namespace std;

int main()

{
    vector<int> vet;
    int s = 1;
        while (s != 0) {
        std::cin >> s;
        vet.push_back(s);
    }


    int n = count_if(vet.begin(), vet.end(),
        [](int n) { return (n % 2) == 0; });
    cout << n << endl;
    

    //here is the start of my problems and lack of undertanding. Basically bad improv from previous method
    int m = accumulate(vet.begin(), vet.end(), 0,
        [](int m) { for (auto m : vet) {
              return (m % 2) == 0; });
              cout << m << endl;          //would love to see the sum of even values here

        
        
   return 0;
}
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Labveelis
  • 3
  • 2

7 Answers7

6

The function to be passed to std::accumulate takes 2 values: current accumulation value and value of current element.

What you should do is add the value if it is even and make no change when not.

int m = accumulate(vet.begin(), vet.end(), 0,
        [](int cur, int m) {
            if ((m % 2) == 0) {
                return cur + m; // add this element
            } else {
                return cur; // make no change
            }
        });
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
4

From c++20, you can separate out the logic that checks for even numbers, and the logic for summing up those values:

auto is_even = [](int i) { return i % 2 == 0; };

auto evens = vet | std::views::filter(is_even);

auto sum = std::accumulate(std::begin(evens), std::end(evens), 0);  

Here's a demo.

cigien
  • 57,834
  • 11
  • 73
  • 112
  • does `vet | std::views::filter(is_even);` create a new vector? – Aykhan Hagverdili Oct 08 '20 at 15:45
  • 1
    @AyxanHaqverdili No, that's one of the major advantages of ranges :) `evens` is a `view`, and it's basically an iterator into `vet`. But with the convenience of being able to use it like a container. – cigien Oct 08 '20 at 15:50
  • I wonder why there is no constrained [`std::ranges::accumulate`](https://en.cppreference.com/w/cpp/algorithm/ranges) (range abstraction)? (`view` types are constrained to the [`range`](https://en.cppreference.com/w/cpp/ranges/range) concept, and most `std::` algos on `begin/end` iterators can be applied directly on views via their `std::range::` algo counterparts). – dfrib Oct 08 '20 at 16:12
  • ... I guess the necessary concepts for numerics algos didn't make it in in time for C++20 ([p1813r0](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1813r0.pdf)). – dfrib Oct 08 '20 at 16:15
  • @dfri Yes, there's even a [question](https://stackoverflow.com/questions/63933163/why-didnt-accumulate-make-it-into-ranges-for-c20) asking why :) – cigien Oct 08 '20 at 16:20
0

This is my solution(sorry if it's not right I'm writing it on my phone)

You don't need a vector form this, you just need to check right from the input if the number is divisible to 2 My solution:(a littie bit ugly)

#include <iostream>

using namespace std;

    int main()
    {
        int s {1};
        int sum{};
        int countNum{};
        while (s != 0)
        {
            cin >> s;
            if (s % 2 == 0)
            {
                sum += s;
                countNum++;
            }
        }
        cout << countNum << ' ' << sum;
    }
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
0

i don't realy know what you want to do in the second part of your code but you can sum the even numbers by this way and i want to told you another thing when you using namespace std you don't need to write std::cin you can only write cin directly

#include <iostream>
#include <vector>

using namespace std;

int main()

{
    vector<int> vet;
    int s = 1;
    //Take Input
    while (s != 0) {
        cin >> s;
        vet.push_back(s);
    }
    //count elements
    int elements_count = vet.size(); //vet.size() return the total number of elements of vector

    //store the sum here
    int sum=0;

    //loop on the vector and sum only even numbers
    for(int i=0;i<elements_count;i++){
        if(vet[i] %2 ==0)
            sum += vet[i];//check of the element of index i in the vector is even if it true it will add to sum
    }
    cout << sum;

   return 0;
}
  • 2
    fwiw, the common advice on `using namespace std;` is the other way: [Why is “using namespace std;” considered bad practice?](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice). Not a big deal in small example programs but important to know what problems it can cause when used wrong – 463035818_is_not_an_ai Oct 08 '20 at 15:13
0
int sumEven=0;
int v[100];
int n;//number of elements you want to enter in the array
do{cout<<"Enter n";
  cin>>n;}while(n<=0);
//in a normal 1 dimensional array
for(int i=0;i<n;i++)
if(v[i]%2==0)
    sumEven+=v[i];

//in a vector
vector<int> v;
for(vector<int>::iterator it=v.begin();it!=v.end();it++)
if(*it%2==0)
    sumEven+=v[i];
cigien
  • 57,834
  • 11
  • 73
  • 112
Charbelalam
  • 104
  • 7
0

Range-based for loops

A range-based for loop is arguably always a valid alternative to the STL algos, particularly in cases where the operators for the algos are non-trivial.

In C++14 and C++17

E.g. wrapping a range-based even-only accumulating for loop in an immediately-executed mutable lambda:

#include <iostream>
#include <vector>

int main() {
    // C++17: omit <int> and rely on CTAD.
    const std::vector<int> v{1, 10, 2, 7, 4, 5, 8, 13, 18, 19};
    const auto sum_of_even_values = [sum = 0, &v]() mutable {
        for (auto val : v) { 
            if (val % 2 == 0) { sum += val; }
        }
        return sum;
    }();
    
    std::cout << sum_of_even_values; // 42
}

In C++20

As of C++20, you may use initialization statements in the range-based for loops, as well as the ranges library, allowing you to declare a binary comparator in the initialization statement of the range-based for loop, and subsequently apply it the range-expression of the loop, together with the std::ranges::filter_view adaptor:

#include <iostream>
#include <vector>
#include <ranges>

int main() {
    const std::vector v{1, 10, 2, 7, 4, 5, 8, 13, 18, 19};

    const auto sum_of_even_values = [sum = 0, &v]() mutable {
        for (auto is_even = [](int i) { return i % 2 == 0; };
             auto val : v | std::ranges::views::filter(is_even)) { 
            sum += val;
        }
        return sum;
    }();
    
    std::cout << sum_of_even_values; // 42
}
dfrib
  • 70,367
  • 12
  • 127
  • 192
0

Similar to answers above, but if you want to keep the vector of even numbers as well, here are two approaches.

#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

int main() {

    std::vector<int> vec = {1,2,3,4,5,6,7,8,9,10};

    // Hold onto what we know is the right answer.
    int known_sum = 2+4+6+8+10;

    // Copy only even values into another vector
    std::vector<int> even_values;
    std::copy_if(vec.begin(), vec.end(),
                std::back_inserter(even_values),
                [](int val){ return val%2==0; });

    // Compute sum from even values vector
    int even_value_sum = std::accumulate(even_values.begin(), even_values.end(), 0);

    // Compute sum from original vector
    int even_value_second = std::accumulate(vec.begin(), vec.end(), 0, 
        [](int current_sum, int new_value) {
            return new_value%2==0 ? current_sum + new_value:current_sum;
        }
    );

    // These should all be the same.
    std::cout << "Sum from only even vector: " << even_value_sum << std::endl;
    std::cout << "Sum from binary op in std accumulate: " << even_value_second << std::endl;
    std::cout << "Known Sum: " << known_sum << std::endl;

}