Related
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;
}
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
}
});
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.
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;
}
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;
}
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];
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;
}
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
}
I want to expand a given vector by repeating every entry three times. For example, if the vector is [5,7]. The output vector should be [5 5 5 7 7 7]
#include<iostream.h>
#include<vector.h>
int main(void)
{
std::vector<int> x;
x.push_back(5);
x.push_back(7);
x.insert(x.end(), x.begin(), x.begin() + 1);
return 0;
}
This didnt work out. Any help would be appreciated.
A simple approach is to loop over the vector and create a new one:
std::vector<int> vec{5, 7};
// create a new vector
std::vector<int> new_vec;
new_vec.reserve(vec.size() * 3);
for (auto elem : vec) {
for (std::size_t i = 0; i < 3; ++i) {
new_vec.push_back(elem);
}
}
I don't know how simple code you want, but for example this works.
#include<iostream>
#include<vector>
int main(void)
{
std::vector<int> x;
x.push_back(5);
x.push_back(7);
for (std::vector<int>::iterator it = x.end(); it != x.begin(); )
{
it--;
it = x.insert(it, 2, *it);
}
// print the vector to check
for (size_t i = 0; i < x.size(); i++) std::cout << x[i] << " ";
std::cout << std::endl;
return 0;
}
Maybe something like this could help you achieve that:
#include <iostream>
#include <algorithm>
#include <vector>
template<typename T>
std::vector<T> RepeateEntryNumberOfTimes(std::vector<T> input, std::uint16_t numberOfTimes)
{
std::vector<T> result;
std::for_each(input.begin(), input.end(), [&result, numberOfTimes](T item){
for(std::uint16_t numberOfReps = 0; numberOfReps != numberOfTimes; ++numberOfReps)
{
result.push_back(item);
}
});
return result;
}
See godbolt example: https://godbolt.org/z/ns9o3b
Your code has problem since it inserting elements to same vector.
Modification of vector invalidates old iterators, so your code has undefined behavior.
Even ignoring this error, logic of your code doesn't seem to do what you are expecting.
template<typename In, typename Out>
Out replicate_elements(In b, In e, size_t n, Out o)
{
while(b != e) {
o = std::fill_n(o, n, *b++);
}
return o;
}
std::vector<int> foo(const std::vector<int>& x)
{
std::vector<int> r;
r.reserve(x.size() * 3);
replicate_elements(x.begin(), x.end(), 3, std::back_inserter(r));
return r;
}
https://www.godbolt.org/z/zvE5TG
Instead of typing
array[0] + array[1] //.....(and so on)
is there a way to add up all the numbers in an array? The language I'm using would be c++
I want to be able to do it with less typing than I would if I just typed it all out.
Here is the idiomatic way of doing this in C++:
int a[] = {1, 3, 5, 7, 9};
int total = accumulate(begin(a), end(a), 0, plus<int>());
Note, this example assumes you have somewhere:
#include <numeric>
using namespace std;
Also see: accumulate docs and accumulate demo.
Say you have an int array[N].
You can simply do:
int sum = 0;
for(auto& num : array)
sum += num;
Try this:
int array[] = {3, 2, 1, 4};
int sum = 0;
for (int i = 0; i < 4; i++) {
sum = sum + array[i];
}
std::cout << sum << std::endl;
If you use a valarray, there is a member function sum() for that.
#include <iostream> // std::cout
#include <valarray> // std::valarray
int main () {
std::valarray<int> myvalarray(4);
myvalarray[0] = 0;
myvalarray[1] = 10;
myvalarray[2] = 20;
myvalarray[3] = 30;
std::cout << "The sum is " << myvalarray.sum() << '\n';
return 0;
}
The easiest way I can see to do this is to use a loop. The bonus is that you can use it on any integer array without rewriting much code at all. I use Java more often, so I hope there aren't too many syntax errors, but something like this should work:
int addArray(int[] array, int length){
int sum=0;
for(int count=0;count<length;count++){
sum+=array[count];
}
return sum;
}
In C++17, one could use fold expressions:
template<typename ...Ts>
int sum_impl(Ts&& ...a)
{
return (a + ...);
}
If sum_impl had a constant number of parameters, we could have called it like this:
std::apply(sum_impl, arr);
assuming arr is std::array<int, N>. But since it is variadic, it needs a little push with helpers:
using namespace std;
template <class Array, size_t... I>
int sum_impl(Array&& a, index_sequence<I...>)
{
return sum_impl(get<I>(forward<Array>(a))...);
}
template <class Array>
int sum(Array&& a)
{
return sum_impl(forward<Array>(a),
make_index_sequence<tuple_size_v<decay_t<Array>>>{});
}
Therefore, assuming these helpers are in place, the code will look something like this:
template<typename ...Ts>
int sum_impl(Ts&& ...a)
{
return (a + ...);
}
int main()
{
array<int, 10> arr{0,1,2,3,4,5,6,7,8,9};
cout << sum(arr) << "\n";
return 0;
}
We may use user defined function.
Code Snippet :
#include<bits/stdc++.h>
using namespace std;
int sum(int arr[], int n)
{
int sum=0;
for(int i=0; i<n; i++)
{
sum += arr[i];
}
return sum;
}
int main()
{
int arr[] = {1, 2, 3, 4, 5};
int n = distance(begin(arr), end(arr));
int total = sum(arr,n);
printf("%d", total);
return 0;
}
int Sum;
for(int& S: List) Sum += S;
If your compiler supports c++17, you may use a combination of Parameter pack and fold expression to achieve this. A template parameter pack is a template parameter that accepts zero or more template arguments, and fold reduces the parameter pack over a binary operator. (+ in this case)
#include <iostream>
#include <array>
#include <utility>
/*
* References:
* [1] https://en.cppreference.com/w/cpp/language/fold
* [2] https://en.cppreference.com/w/cpp/language/parameter_pack
*/
template <typename ...T>
auto sum(T ...args)
{
return (args + ...);
}
template <typename T, std::size_t ...Is>
auto sum(T t, std::index_sequence<Is...>)
{
return sum(t[Is]...);
}
int main()
{
std::array<int, 3> a1 = {1, 4, 3};
int a2[5] = {1, 2, 3, 4, 0};
std::cout << "Sum a1 = " << sum(a1, std::make_index_sequence<a1.size()>{}) << "\n";
std::cout << "Sum a2 = " << sum(a2, std::make_index_sequence<5>{}) << "\n";
return 0;
}
Adding one more point regarding std::accumulate usage:
When a C-style array is passed to a function then you should explicitly specify the array start and end(one-past-the-end) addresses when you use the std::accumulate.
Example:
#include <numeric>
void outsideFun(int arr[], int n) {
int sz = sizeof arr / sizeof arr[0]; // 1=decays to a ptr to the 1st element of the arr
// int sum = accumulate(begin(arr), end(arr), 0); // Error:begin/end wouldn't work here
int sum = accumulate(arr, arr + n, 0); // 15 (Method 2 Only works!)
std::cout << sum;
}
int main() {
int arr[] = { 1,2,3,4,5 };
int sz = sizeof arr / sizeof arr[0]; // 5
int sum = accumulate(begin(arr), end(arr), 0); // 15 (Method 1 - works)
int cum = accumulate(arr, arr + sz, 0); // 15 (Method 2 - works)
outsideFun(arr, sz);
}
So I have a function
f(int D[],int A[],int len){
for(int k = 0; k < len; k++)
D[k] = A[k];
and if I output D the numbers are all wrong. The function f is called with D initialised as int* D = new int[100000]; in the main function and A is all good because I output it in the function and it looks ok. So... can't understand where the problem is... I also tried memcpy(D+k,A+k,sizeof(int)); and it doesn't work.
Your loop works perfectly. The problem must be somewhere else in your code.
Here is an example program which copies the data in three different ways: a for loop, memcpy, and std::copy:
#include <algorithm>
#include <cstring>
#include <iostream>
#include <iterator>
void copy1(int D[], int A[], int len) {
for(int k = 0; k < len; k++)
D[k] = A[k];
}
void copy2(int D[], int A[], int len) {
std::memcpy(D, A, len*sizeof(int));
}
void copy3(int D[], int A[], int len) {
std::copy(A, A+len, D);
}
int main () {
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *d = new int[10];
std::ostream_iterator<int> out(std::cout, ",");
// First, print the initial values
std::copy(d, d+10, out);
std::cout << "\n";
// Next do the copies and print the values again
copy1(d, a, 10);
std::copy(d, d+10, out);
std::cout << "\n";
copy2(d, a, 10);
std::copy(d, d+10, out);
std::cout << "\n";
copy3(d, a, 10);
std::copy(d, d+10, out);
std::cout << "\n";
}
The output I get is:
0,0,0,0,0,0,0,0,0,0,
1,2,3,4,5,6,7,8,9,10,
1,2,3,4,5,6,7,8,9,10,
1,2,3,4,5,6,7,8,9,10,
Run your code in debugger and see if you do not have garbage in A[] in the first place (it could go wrong after function call). Also I suggest you pass reference (like int & D[] and const int & A[] — const to prevent altering of A).
Start with a minimal working example such as the following, then integrate your other code into it until something breaks. That’ll be the source of your error. Without more information, this is pretty much all I can tell you; when you encounter wrong values in a C++ program, you’re likely reading from an uninitialised variable. I suggest you try stepping through your program in a debugger such as GDB.
#include <algorithm>
#include <iostream>
#include <iterator>
void f(int D[], const int A[], int len){
for(int k = 0; k < len; k++)
D[k] = A[k];
}
int main(int argc, char** argv) {
int A[] = { 1, 2, 3, 4, 5 };
int D[5];
f(D, A, 5);
std::copy(A, A + 5, std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
std::copy(D, D + 5, std::ostream_iterator<int>(std::cout, " "));
return 0;
}
Unless you have a very good reason to do so, prefer std::vector and std::array over raw arrays. Learning how arrays and pointers work is a good reason to use them, though.
I believe the problem is that you are passing in a pointer to an array
int* D = new int[100000];
however, your function takes two integer arrays, which is not the same as a pointer to an array.
Here's a SSCCE of a snippet that behaves like you want it:
#include <iostream>
using namespace std;
void f(int * d, int * a, int length){
for(int k = 0; k < length; k++){
d[k] = a[k];
}
}
int main() {
int* a = new int[9];
for(int i = 0; i < 9; i++){a[i] = i;}
int* d = new int[9];
f(d, a, 9);
for(int i = 0; i < 9; i++){
cout << d[i] << " ";
}
}
Pseudo Code:
int arr[ 5 ] = { 4, 1, 3, 2, 6 }, x;
x = find(3).arr ;
x would then return 2.
The syntax you have there for your function doesn't make sense (why would the return value have a member called arr?).
To find the index, use std::distance and std::find from the <algorithm> header.
int x = std::distance(arr, std::find(arr, arr + 5, 3));
Or you can make it into a more generic function:
template <typename Iter>
size_t index_of(Iter first, Iter last, typename const std::iterator_traits<Iter>::value_type& x)
{
size_t i = 0;
while (first != last && *first != x)
++first, ++i;
return i;
}
Here, I'm returning the length of the sequence if the value is not found (which is consistent with the way the STL algorithms return the last iterator). Depending on your taste, you may wish to use some other form of failure reporting.
In your case, you would use it like so:
size_t x = index_of(arr, arr + 5, 3);
Here is a very simple way to do it by hand. You could also use the <algorithm>, as Peter suggests.
#include <iostream>
int find(int arr[], int len, int seek)
{
for (int i = 0; i < len; ++i)
{
if (arr[i] == seek) return i;
}
return -1;
}
int main()
{
int arr[ 5 ] = { 4, 1, 3, 2, 6 };
int x = find(arr,5,3);
std::cout << x << std::endl;
}
The fancy answer:
Use std::vector and search with std::find
The simple answer
Use a for loop
If the array is unsorted, you will need to use linear search.
#include <vector>
#include <algorithm>
int main()
{
int arr[5] = {4, 1, 3, 2, 6};
int x = -1;
std::vector<int> testVector(arr, arr + sizeof(arr) / sizeof(int) );
std::vector<int>::iterator it = std::find(testVector.begin(), testVector.end(), 3);
if (it != testVector.end())
{
x = it - testVector.begin();
}
return 0;
}
Or you can just build a vector in a normal way, without creating it from an array of ints and then use the same solution as shown in my example.
int arr[5] = {4, 1, 3, 2, 6};
vector<int> vec;
int i =0;
int no_to_be_found;
cin >> no_to_be_found;
while(i != 4)
{
vec.push_back(arr[i]);
i++;
}
cout << find(vec.begin(),vec.end(),no_to_be_found) - vec.begin();
We here use simply linear search. At first initialize the index equal to -1 . Then search the array , if found the assign the index value in index variable and break. Otherwise, index = -1.
int find(int arr[], int n, int key)
{
int index = -1;
for(int i=0; i<n; i++)
{
if(arr[i]==key)
{
index=i;
break;
}
}
return index;
}
int main()
{
int arr[ 5 ] = { 4, 1, 3, 2, 6 };
int n = sizeof(arr)/sizeof(arr[0]);
int x = find(arr ,n, 3);
cout<<x<<endl;
return 0;
}
You could use the STL algorithm library's find function provided
#include <iostream>
#include <algorithm>
using std::iostream;
using std::find;
int main() {
int length = 10;
int arr[length] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int* found_pos = find(arr, arr + length, 5);
if(found_pos != (arr + length)) {
// found
cout << "Found: " << *found_pos << endl;
}
else {
// not found
cout << "Not Found." << endl;
}
return 0;
}
There is a find(...) function to find an element in an array which returns an iterator to that element. If the element is not found, the iterator point to the end of array.
In case the element is found, we can simply calculate the distance of the iterator from the beginning of the array to get the index of that element.
#include <iterator>
using namespace std;
int arr[ 5 ] = { 4, 1, 3, 2, 6 }
auto it = arr.find(begin(arr), end(arr), 3)
if(it != end(arr))
cerr << "Found at index: " << (it-begin(arr)) << endl;
else
cerr << "Not found\n";