C++ for each usable with anonymous collections? [duplicate] - c++

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.

Related

How to initialize a 2d array with -1 globally?

The below is the basic code. I want to make the array globally so that i don't have to call it for every function.Now how do I initialize the 2d array with -1. I tried to use memset(arr,-1,sizeof(arr)) just below line 3, but it didn't worked out, so, can anyone tell me what am I doing wrong??
#include <bits/stdc++.h>
using namespace std;
int arr[10][10];
int func(){
//this function will be using the global arr
// if(arr[x][y]!=-1)
//do something
}
int main(){
//the code
}
I do not know the good way to initialize a built-in array in place without code repetition. I do, however, know a way to initialize std::array:
#include <array>
#include <utility>
#include <cstddef>
template<size_t... Ix>
auto constexpr make1array(int v, std::index_sequence<Ix...>) {
auto populate = [](int v, size_t) { return v; };
std::array<int, 10> a = { populate(v, Ix)... };
return a;
}
template<size_t... Ix1, size_t... Ix2>
auto constexpr make2array(int v, std::index_sequence<Ix1...> seq, std::index_sequence<Ix2...>) {
auto populate = [](auto v, size_t) { return v; };
std::array<std::array<int, 10>, 10> a = { populate(make1array(v, seq), Ix2)... };
return a;
}
std::array<std::array<int, 10>, 10> arr = make2array(-1, std::make_index_sequence<10>{}, std::make_index_sequence<10>{});
This code produces an array pre-populated with -1 as the value at compile time.
The function memset won't work because memset uses bytes and many integers occupy more than one byte.
IMHO, your best source is to use std::fill.
Example:
std::fill(&arr[0][0], &arr[9][9] + 1, -1);
Otherwise, you can always fall back on the nested loop:
for (int r = 0; r < MAX_ROWS; ++r)
{
for (int c = 0; c < MAX_COLUMNS; ++c)
{
arr[r][c] = -1;
}
}
Your best bet is to let the compiler optimize the nested loops.
There may be some micro-optimizations that you could employ, but the compiler probably already has them in its tool chest.
There is no direct way to initialize raw array by values that aren't result of default initialization. One of the reasons is that array cannot be returned from function and cannot be assigned directly from anything that is not a {}-list.
Simplest way (since C++14) is to make it part of class-type with constexpr constructor. In C++111 constructor with non-empty body cannot be constexpr.
#include <iostream>
struct MinusOneArray {
static constexpr int NX = 10;
static constexpr int NY = 10;
int arr[NX][NY];
constexpr MinusOneArray() : arr() {
for(int i = 0; i < NX; ++i)
for(int j = 0; j < NY; ++j)
arr[i][j] = -1;
}
};
int main()
{
MinusOneArray a;
auto &arr = a.arr;
for(auto &line: arr) {
for(auto val: line)
std::cout << val << ",";
std::cout << std::endl;
}
}
Alternative is to use standard structure std::array and initialize it with constexpr function, how SergeyA offered.

How to fix for each loop in C++?

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);
}

How to add all numbers in an array in C++?

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);
}

Find the elements of an array based on minimum sum

I've written a loop in C++ to give me 6 random numbers and store them in an array.
What I would like to do is to sum the elements of the array until I get a value larger than a number, "x", but I would like to do this without necessarily adding all the elements. The objective is to find the first elements which sum to the value of x.
For example, array is [1,2,3,4,5,6], and x = 6, so what I would be looking for are the elements [1,2,3].
I've looked at the standard library and have tried using the sum function from "valarray" but this just gives the sum of all the elements. Any ideas on how to code this successfully would be greatly appreciated.
Write a functor that does the addition.
#include <algorithm>
struct SumToo
{
SumToo(int val):m_val(val),m_sum(0) {}
int m_val;
int m_sum;
bool operator()(int next)
{
m_sum += next;
return m_sum >= m_val;
}
};
int main()
{
int data[] = {1,2,3,4,5,6};
int* find = std::find_if(data,data+6,SumToo(6));
}
I'm assuming you just want the first X elements in the array, up until their sum meets or exceeds a threshold (the question was a little vague there).
If so, I don't know how to do that without your own loop:
int sum = 0;
int i = 0;
for( ; i < len; ++i ) {
sum += array[i];
if( sum >= 6 ) {
break;
}
}
Now "i" contains the index at which the sum met or exceeded your threshold.
Avoid the answers that suggest using find_if with a stateful predicate. Stateful predicates are dangerous as the STL algorithms assume it is safe to copy predicates. In this case, if copies are made of the predicate then each will have a different 'running total' and will not necessarily act on all values, or in the correct order.
Especially avoid the solution that implements its predicate's operator() member as a const member function but labels its members as mutable as this is fooling you into thinking it is not a stateful predicate, which is bad.
I'd suggest using either one of the answers that simply loops to find the answer, or the answer that uses an accumulator, as that is the most correct way to do it (even if the code looks a little unwieldy.
Note that the warnings may well not apply to C arrays and find_if; I just don't want you to learn that stateful predicates are the right way to solve your problem since you may end up using that incorrect solution in a situation where it is dangerous in future.
Reference: C++ Coding Standards: 101 Rules, Guidelines, and Best Practices, Item 87
Here's a slightly more generic version:
#include <iostream>
#include <algorithm>
// return an iterator _Last such that sum
// of all elements in the range [_First, _Last)
// satisfies the predicate Func
template<class InIt,
class Ty,
class Fn> inline
InIt accumulate_if(InIt First, InIt Last, Ty Val, Fn Func)
{
for (; Func(Val) && First != Last; ++First)
Val = Val + *First;
return (First);
}
int main() {
int num[] = {1, 2, 3, 4, 5, 6};
int *last = accumulate_if(num, num + sizeof num / sizeof num[ 0 ],
0, std::bind2nd(std::less<int>(), 6));
std::copy(num, last, std::ostream_iterator<int>(std::cout, "\n"));
return 0;
}
Substract the numbers from x one by one, until you reach 0 or lower.
No additions, as you wished :)
Here's hoping this works:
/* Returns an index i, given array valarray[0,1..n] and number x where i is an index to valarry such that sum over j of valarray[j] for j = 0 to i > x */
int getFirstSum(int *valarray, int n, int x)
{
int i = 0;
int sum = x;
while(sum > x && i < n)
{
i++;
sum -= valarray[i];
}
return i;
}
would be something like:
struct StopAtValue{
StopAtValue(int sum) : m_sum(sum), m_accumulated(0){}
bool operator()(int val){
m_accumulated += val;
return m_accumulated >= sum;
}
int m_sum;
int m_accumulated;
}
int* pos = std::find_if(&array[0], &array[n], StopAtValue(6));
Well, i would use a vector
T addUntil(T array[],size_t len,T thres){
vector<T> vec = vector_from_array(array,len)
T sum;
for (size_t i=0;i< vec.size(),sum<thresh;i++){
sum+= vec[i];
}
return sum;
}
T would need operator+ and operator< to be defined.
You could use std::find_if() along with a functor that maintains a running total, and only returtn true from the functor when you have found the element that puts you at or over the top.
For example:
#include <cstdlib>
#include <algorithm>
#include <functional>
#include <iostream>
#include <string>
using namespace std;
// functor returns true when the running total >= findVal
struct running_total : public unary_function<int, bool>
{
running_total(int findVal) : findVal_(findVal), runningTtl_(0) {};
bool operator()(int rhs) const
{
runningTtl_ += rhs;
if( runningTtl_ >= findVal_ )
return true;
else
return false;
}
private:
mutable int runningTtl_;
const int findVal_;
};
int main()
{
int nums[] = {1, 2, 3, 4, 5, 6};
size_t count = sizeof(nums)/sizeof(nums[0]);
const int scanTtl = 6; // running total to scan to
int * pos = find_if(&nums[0], &nums[0]+count, running_total(scanTtl));
cout << "Elements Totaling " << scanTtl << " : ";
copy(&nums[0], pos+1, ostream_iterator<int>(cout, ", "));
return 0;
}

C++ functor unexpected behavior in for_each

Consider the following example:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class accum
{
public:
int sum;
accum()
{
sum = 0;
}
void operator() (int a)
{
sum += a;
printf("sum=%d\n",sum);
}
};
int main()
{
int ari[] = {2,8,5,9,1};
vector<int> vi(&ari[0], &ari[5]);
accum f;
for_each(vi.begin(), vi.end(), f);
printf("final sum : %d\n", f.sum);
}
I expected the sum to be 25, but it prints 0. Why does f remain unchanged? Can somebody give me a detailed account of what is going on?
That's because std::for_each takes its functor by value, not by reference. It's operating internally on a copy of f and the one you pass in remains unchanged. It does return the functor back to you, so you could just overwrite yours:
accum f = std::for_each(vi.begin(), vi.end(), accum());
Or, sticking with C++03, have accum take a reference:
struct accum {
int& sum;
// rest as before, fixing the constructor
};
int sum = 0;
std::for_each(vi.begin(), vi.end(), accum(sum));
printf("final sum : %d\n", sum);
Although perhaps you might just want std::accumulate:
int sum = std::accumulate(vi.begin(), vi.end(), 0);
Or, in C++11, for_each with a lambda:
int sum = 0;
std::for_each(vi.begin(), vi.end(), [&](int a){ sum += a; });