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);
}
Related
I have a function:
vector<int> prime(int num, ...) {
vector<int> mas;
va_list args;
va_start(args, num);
for (int i = 0; i < num; i++) {
int v = va_arg(args,int);
if (isPrime(v)){
mas.push_back(v);
}
}
cout << endl;
va_end(args);
return mas;}
It should detected prime numbers.
But when i call it, part of my numbers, don`t get over.
It looks something like this
Input: 5, 7, 10, 15, 20,12, 13,16,19
Numbers what cout returns in the loop: 7,7
Help pls!
First of all Variadic arguments from C are considered a bad practice in C++ and should be avoided.
There are plenty of better C++ solutions which are able to replace this C feature.
Old fashioned std::vector:
std::vector<int> filterPrimes(std::vector<int> a) {
auto end = std::remove_if(a.begin(), a.end(), [](auto x) {
return !isPrime(x)
};
a.remove(end, a.end());
return a;
}
Or std::initializer_list
std::vector<int> filterPrimes(std::initializer_list<int> l) {
std::vector<int> r;
std::copy_if(l.begin(), l.end(), std::back_inserter(r), isPrime);
return r;
}
Or Variadic templates, or template with iterator ranges, or ... .
If the arguments are all of the same type, then just pass them in as, say, a vector.
#include <vector>
#include <iostream>
using namespace std;
void func(const vector<int>& args)
{
for (size_t i = 0; i < args.size(); i++)
cout << args[i] << endl;
}
int main(void)
{
vector<int> v = { 5, 7, 10, 15, 20, 12, 13, 16, 19 };
func(v);
return 0;
}
I have a simple program:
#include <array>
#include <iostream>
#include <functional>
#include <algorithm>
using namespace std;
int main(){
array<int, 5> myArr = {3, 10, 0, 5, 7};
int badNum = 0;
for(int item : myArr){
cout << item << endl;
}
cout << "\n" << endl;
cout << "\n" << endl;
sort(myArr.begin(), myArr.end(), greater<int>());
for(int item : myArr){
cout << item << endl;
}
array<int, 4> goodFour;
for (unsigned int i = 0; i < myArr.size(); i++){
if(myArr[i] != badNum){
// goodThree.append(myArr[i]); <-- This is where I am stuck
}
}
}
I am stuck on trying to assign an element to a std::array. I know in std::vector I can use push_back method, but on a std:array, how to assign to the next (not yet assigned) element? I am coming from Python 3.x where we have the append method for a list. I am not attempting to change the size of the array, instead, I am trying to fill in the allocated spaces with values.
I have looked at:
http://www.cplusplus.com/forum/beginner/67707/
http://www.cplusplus.com/forum/beginner/86394/
http://www.cplusplus.com/forum/beginner/152125/
But these are all for vectors or the primitive int[5] myArr types, not std::array.
If you only want the first three good numbers you would maintain a pointer to the next index to insert at:
for (int i = 0, k = 0; k < 3 && i < myArr.size(); i++) {
if (myArr[i] != badNum) {
goodThree[k++] = myArr[i];
}
}
If you want all the numbers that are good you would use a std::vector and call its push_back method:
std::vector<int> goodThree;
for (int i = 0; i < myArr.size(); i++) {
if (myArr[i] != badNum) {
goodThree.push_back(myArr[i]);
}
}
The size of std::array is fixed at compile time. If you need to append another value at run time, then you have to use std::vector (or something like it). The closest you can get to "appending" to a std::array is if you copy its contents into an array with one more element that contains the "appended" value. You can use some template metaprogramming techniques to make this easier:
template <typename T, std::size_t N, typename X, std::size_t... I>
std::array<T, N + 1> push_back(std::array<T, N> const& a, X&& x, std::index_sequence<I...>) {
return {std::get<I>(a)..., std::forward<X>(x)};
}
template <typename T, std::size_t N, typename X>
std::array<T, N + 1> push_back(std::array<T, N> const& a, X&& x) {
return detail::push_back(a, std::forward<X>(x), std::make_index_sequence<N>());
}
Example of use:
std::array<int, 2> a = {1, 2};
std::array<int, 3> b = push_back(a, 3);
for (int x : b) {
std::cout << x << "\n";
}
The size of a std::array is set at compile time. This means that you cannot "append" values to a std::array at run time. However, you could track how many values your array "contains" by your own program logic. For example:
std::array<int, 5> a = {1, 2, 3, 4, 5};
std::array<int, 4> b;
std::size_t n = 0;
for (int x : a) {
if (x != 2) {
if (n < std::size(a) - 1) {
b[n++] = x;
} else {
throw std::out_of_range("array is full");
}
}
}
I'm currently trying to program a function that would find the average of elements in an array of integers in C++.
I've looked at new c++11 for loop causes: "error: ‘begin’ was not declared in this scope" but I don't quite understand the problem and how to fix it.
double avg(int arr[]) {
double sum = 0;
int size = 0;
for (int i : arr) {
sum += i;
size += 1;
}
return sum / size;
}
It gives me errors that "'begin' was not declared in this scope" and "'end' was not declared in this scope".
Could somebody explain why the error is occurring and possible ways to fix it?
The type int arr[] decays into a raw pointer, and as a result there's no way to get the size of the array it refers to.
Instead of using raw arrays, it'd be better just to use either std::vector:
double avg(std::vector<int> const& v) {
double sum = 0;
for(int i : v)
sum += i;
return sum / v.size();
}
Or std::array, which acts like a C-array but is copyable and doesn't decay into a pointer:
template<size_t N>
double avg(std::array<int, N> const& arr) {
double sum = 0;
for(int i : arr) {
sum += i;
return sum / N;
}
Or, if you really have to use arrays, pass the size as a parameter:
double avg(int arr[], size_t size) {
double sum = 0;
for(int i = 0; i < size; i++) {
sum += arr[i];
}
return sum / size;
}
Leveraging the C++ standard library
The C++ standard library has a lot of useful functions, and one of them, accumulate, does the job perfectly. It takes a begin and end iterator, as well as the initial value, and computes the sum over the range:
#include <numeric>
double avg(std::vector<int> const& v) {
return std::accumulate(v.begin(), v.end(), 0.0) / v.size();
}
double avg(int[] arr, size_t size) {
return std::accumulate(arr + 0, arr + size, 0.0) / size;
}
Functions may not take arrays as parameters. You get a pointer there. Though you can pass a reference to an array to a function as a parameter. Here is an example:
#include <iostream>
template <typename T, auto n>
void print(const T(&arr)[n]) {
for (auto&& t : arr) {
std::cout << t << ' ';
}
std::cout << '\n';
}
int main() {
int arr[]{ 1, 2, 3, 4, 5 };
print(arr);
}
Output:
1 2 3 4 5
If you want to actually pass an array, not switch to using a vector you can do it with a template function parametrized on the size of the array i.e.
template <int N>
double avg(int (&arr)[N] ) {
double sum = 0;
int size = 0;
for (int i : arr) {
sum += i;
size += 1;
}
return sum / size;
}
int main()
{
int ary[] = { 1,2,3,4,5,6 };
std::cout << avg(ary);
}
I need both the minimum and the mean of the values in a vector.
I'm computing them separately with the following:
template <class T>
T Minimum(std::vector<T> & v){ return *min_element(begin(v), end(v)); }
template <class T>
T Mean(std::vector<T> & v)
{
T sum = std::accumulate(v.begin(), v.end(), static_cast<T>(0));
T mean = sum / v.size();
return mean;
}
Both of these have to sweep the vector.
Is there a std efficient way to compute both minimum and mean of a vector sweeping it only once?
Yes, you can accumulate the minimum and the sum in the same call. No, it probably won't be more efficient, nor will it be less efficient.
template <typename T>
std::pair<T, T> MeanAndMin(const std::vector<T> & v)
{
auto zero = std::make_pair(static_cast<T>(0), std::numeric_limits<T>::max());
auto plus = [](auto pair, auto elem) { return std::make_pair(pair.first + elem, std::min(pair.second, elem)); };
auto res = std::accumulate(begin(v), end(v), zero, plus);
res.first /= v.size();
return res;
}
You can use std::accumulate, paired with custom functors:
#include <iostream>
#include <vector>
#include <numeric>
#include <limits>
#include <algorithm>
struct average_and_min {
int sum = 0;
int min = std::numeric_limits<int>::max();
std::size_t num_of_elements = 0;
int get_sum() {
return sum;
}
double get_average() {
return static_cast<double>(sum) / num_of_elements;
}
int get_min() {
return min;
}
};
int main() {
std::vector<int> vec = {1, 2, 5, 4, 4, 2, 4};
auto func_accumulate = [](average_and_min acc, int value) {
return average_and_min{acc.sum + value, std::min(acc.min, value), acc.num_of_elements + 1};
};
auto data = std::accumulate(vec.cbegin(), vec.cend(), average_and_min{}, func_accumulate);
std::cout << "avg: " << data.get_average() << '\n'
<< "min: " << data.get_min() << '\n';
}
EDIT:
As #Caleth suggested in the comments, it might be a good idea not to use lambdas to combine your struct and the value - you can overload operator + inside average_and_min like so:
average_and_min operator + (int value) {
return average_and_min{sum + value, std::min(min, value), num_of_elements + 1};
}
and the line
auto data = std::accumulate(vec.cbegin(), vec.cend(), average_and_min{}, func_accumulate);
can now become
auto data = std::accumulate(vec.cbegin(), vec.cend(), average_and_min{});
This question already has answers here:
for loop : C++ and python
(3 answers)
Closed 8 years ago.
I'm trying to get some Python listcomprehension like syntax into my C++.
I am using Visual Studio 2013.
As an example, suppose I want to emulate (python): for i in [1,5]: sum+=i
Assume sum initialized previously to zero.
The best I could do so far is:
int a[]={1,5}, sum=0;
for each (int i in a) sum+=i;
I would have liked something like:
for each (int i in {1,5}) sum+=i;
But obviously, this does not compile; attempts to insert int or int[] at the {1, 5} do not help as far as I can see.
using the {1,5} to initialize a vector: std::vector<int>{1,5} works, but is a bit windy; and I don't need the overhead of constructing and destroying a vector.
Did I miss something, or is this impossible at C++11 (and mayby C++14)?
You can do something similar with an std::initializer_list. The following code compiles on gcc 4.8.2
#include <iostream>
int main() {
int sum = 0;
for (auto x : {1,5}) sum += x;
std::cout << sum << std::endl;
}
EDIT: If you want to use ranges, instead of hard-coded collections, you can use the following:
template <int L, int H, int... Nums> struct make_seq_impl {
constexpr std::initializer_list<int> operator()() const {
return make_seq_impl<L + 1, H, Nums..., L>{}();
}
};
template <int H, int... Nums> struct make_seq_impl<H, H, Nums...> {
constexpr std::initializer_list<int> operator()() const {
return { Nums..., H };
}
};
template <int L, int H>
inline constexpr std::initializer_list<int> make_seq() {
return make_seq_impl<L, H>{}();
}
int main() {
int sum = 0;
// 1 + 2 + 3 + 4 + 5
for (auto x : make_seq<1, 5>()) sum += x;
}
You can get very similar syntax using a range based for and a braced-init-list
int sum = 0;
for(auto i : {1,2,3,4}) {
sum += i;
}
Or use std::accumulate
auto arr = {1,2,3,4};
auto sum = std::accumulate(std::begin(arr), std::end(arr), 0);
How about this?
#include <iostream>
#include <array>
int main() {
int sum = 0;
for (int x : std::array<int, 2>{1, 5})
sum += x;
}
It retains the longwindedness, but there's very little overhead in creating the array.