I'm trying to learn to use iterator with vectors in C++ by, for example computing the average of a vector.
Yet this code does not give the proper answer and I cannot figure out why !
double average(vector<double> const &v)
{
vector<double>::size_type taille = v.size();
double sum = 0;
for(vector<double>::const_iterator i = v.begin(); i != v.end(); ++i)
sum += v[*i];
return sum/taille;
}
Can anybody give me a hint ?
Thanks a lot in advance ! Bye :)
In C++, iterators imitate the behaviors of pointers (to some degree). So if it is an iterator to an element, you access the element by dereferencing it as *it.
That means, instead of this:
sum += v[*i];
you should write this:
sum += *i; //just dereference the iterator!
Hope that helps.
Accessing vector items through an iterator is simply *i, not v[*i]. The form you've used requires accessing with index:
for (size_t i = 0; i < v.size(); i++) sum += v[i];
And your code should look like:
for(vector<double>::const_iterator i = v.begin(); i != v.end(); ++i)
sum += *i;
^^^^ note this
The iterator actually points to the object. Proper way to iterate is:
double average(vector<double> const &v)
{
vector<double>::size_type taille = v.size();
double sum = 0;
for(vector<double>::const_iterator i = v.begin(); i != v.end(); ++i)
sum += *it;
return sum/taille;
}
In C++11 you can do this too:
double average(vector<double> const &v)
{
double sum = 0;
for(const double &d : v)
sum += d;
return sum/v.size();
}
Related
I tried to realize factorial using vectors. Result's assumed to append the vector<int> Res
//corrected
vector<int> Res;
vector<int> Fact;
for(int i=1; i!=4; i++)
Fact.push_back(i);
int result=1;
for (auto i = Fact.rbegin(), auto e= Fact.rend(); i != e; ++i)
result *= *i;
Res.push_back(result);
The problem is in iterators. Exception: can't dereference out of range vector iterator.
I can't understand what's iterator out of range? Beg and End was defined after filling the Fact. So, what's the problem? I'm only the beginner, I must have missed some impotrant detail in this topic)
End is iterator to after the last element, you shouldn't dereference it (End-i is End when i is 0):
for (int i = 0; End != Beg; End--, i++)
result *= *(End-i);
I guess you need this:
for (; End != Beg; End--)
result *= *(End-1);
The easiest solution preserving semantics is to use reverse_iterator:
for (auto i = Fact.rbegin(), e = Fact.rend(); i != e; ++i)
result *= *i;
Alternatively, using accumulate:
result = std::accumulate(Fact.rbegin(), Fact.rend(), 0, [](int a, int b) { return a * b; })
Alternatively, with C++20 and ranges:
for (int i : std::ranges::reverse_view{Fact})
result *= i;
Alternatively, since multiplication is commutative, any of the above methods with forward iteration.
Alternatively, since multiplication by 0 yields 0 for any number and you start with 0:
result = 0;
end() returns "one past the last element". In your first pass,
i == 0, so "one past the end minus zero equals kaboom".
If you happen to know that you're dealing with a vector/contiguous memory, you can just someVec[length-n], so long as you know the result is a valid index (n <= 0 or n >= size would both be bad). For this code, I wouldn't use iterators at all.
I want to update vector 'v' so that I can iterate from count 0-100.
I know this is not allowed, but what if I want to do this only?
Is there any way?
int main() {
// your code goes here
vector<int> v;
v.push_back(1);
int count = 0;
for(int elem: v){
if(count<100)
v.push_back(count);
count++;
}
for(int elem: v)
cout << elem << endl;
return 0;
}
The output is:
1
0
As you can see from the definition of the range-based for loop, the end_expr does not update between iterations. Therefore you only have one iteration. push_back invalidates v.end() (which is what end_expr is as described in the linked page), so what you have is actually undefined behaviour.
The arguably simplest way to fill vector with 0..100 would be:
vector<int> v(101);
std::iota(v.begin(), v.end(), 0);
You should use this code instead
int count = 0;
while (v.size() < 100) {
v.push_back(count++)
}
Modifying vector while iterate through it is not allowed
Best efective way for this operation
vector<int> v;
v.resize(100);
for(unsigned int i = 0; i < v.size(); i++)
{
v[i] = i;
}
same as above.
using your code :
for(int elem: v){
if(count<100)
v.push_back(count);
count++;
}
is like using this :
int i = v.size();
for(int j = 0; j < i; j++){
v.push_back(j);
}
I don't really know why... v.size() might be keep in memory for optimization and data protection
Edit after OP comment :
Try this
int i = v.size();
for(int j = 0; j < i; j++){
if(j<100)
i = v.size();
v.push_back(count);
}
A range-based for loop produces code similar to this:
{
auto && __range = range_expression ;
for (auto __begin = begin_expr,__end = end_expr; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
As you can see the range will not be updated as you're iterating over your container.
Additionally you're most likely ending up with undefined behaviour because as you're pushing back values to your vector these iterators will be invalidated in case of a resize.
See #user2079303 for a better way to fill your vector.
I have a problem with initializing an array of double with the size determined in runtime.
MyPoly MyPoly::operator *(const MyPoly& other)
{
int newDegree = this->_degree + other._degree;
double array [newDegree] ;
fillArrayWithZeros(array, this->_degree + other._degree);
PolyRep::iterator it1 = this->_poly->begin();
PolyRep::iterator it2 = other._poly->begin();
for (int i = 0; i <= this->_degree; ++i, ++it1)
{
for (int j = 0; j <= other._degree; ++j, ++it2)
{
array[i + j] += (*it1) * (*it2);
}
it2 = other._poly->begin();
}
return MyPoly(array, this->_degree + other._degree);
}
It's in the second line of the function. If ill put a number say - 10 it works just fine.
There is no compilation error and no runtime error, but when i debug the program i see the array is empty.
The thing is that in the following function the initialization works fine although the size of the array is being determined in runtime as well :
MyPoly MyPoly::operator +(const MyPoly& other)
{
int bigDegree = (this->_poly->getDegree() > other._poly->getDegree()) ?
this->_poly->getDegree() : other._poly->getDegree();
double arr [bigDegree];
PolyRep::iterator it1 = this->_poly->begin();
PolyRep::iterator it2 = other._poly->begin();
for (int i = 0; i <= this->_poly->getDegree(); ++i, ++it1)
{
arr[i] = *it1;
}
for (int i = 0; i <= other._poly->getDegree(); ++i, ++it2)
{
arr[i] += *it2;
}
return MyPoly(arr, bigDegree + 1);
}
Both function are in the same class.
Can someone explain what is the problem
In both codes, you are writing off the end of the array, which can cause arbitrarily bad behavior. You need to use < instead of <= in your loops, or allocate 2 extra slots.
To answer your question, you are otherwise using runtime-sized arrays correctly.
In one code, you're using ->_degree and in the other you're using ->getDegree(). Are those really the same thing?
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Can I declare variables of different types in the initialization of a for loop?
I'd like to have a for loop in c++ which constructs 2 different kinds of vector iterator in the initialisation.
Here is a rough idea of what I would like:
std::vector<double> dubVec;
std::vector<int> intVec;
double result = 0;
dubVec.push_back(3.14);
intVec.push_back(1);
typedef std::vector<int>::iterator intIter;
typedef std::vector<double>::iterator dubIter;
for (intIter i = intVec.begin(), dubIter j = dubVec.begin(); i != intVec.end(); ++i, ++j)
{
result += (*i) * (*j);
}
Anyone know what is the standard to do in this situation?
I can't just use a vector of double for the intVec because I'm looking for a general solution. [i.e. I might have some function f which takes int to double and then calculate f(*i) * (*j)]
You could declare a std::pair with first and second as the iterator types:
for (std::pair<intIter, dubIter> i(intVec.begin(), dubVec.begin());
i.first != intVec.end() /* && i.second != dubVec.end() */;
++i.first, ++i.second)
{
result += (*i.first) * (*i.second);
}
You can't declare variables of different types inside a for loop.
Just declare them outside:
intIter i = intVec.begin();
dubIter j = dubVec.begin();
for (; i != intVec.end(); ++i && ++j)
{
}
Check out the zip iterator. It does exactly what you want: parallel iterate over two or more sequences simultaneously. Using that, I'd write it as:
using namespace boost;
for (auto i=make_zip_iterator(make_tuple(dubVec.begin(), intVec.begin())),
ie=make_zip_iterator(make_tuple(dubVec.end(), intVec.end()));
i!=ie; ++i)
{
// ...
}
Admittedly, this get's a little more complicated if you don't have support for auto or other type inference in your specific case, but it can still be quite nice with a typedef.
For example
intIter i = intVec.begin();
dubIter j = dubVec.begin();
for (; i != intVec.end(); ++i && ++j)
{
result += (*i) * (*j);
}
you can declare several var. only of the same type in the for.
And are you sure with this part
++i && ++j
? I believe you want to write there
++i, ++j
So obviously you must read basics about for loop in C++
The easiest thing to do, at the expense of widening the scope of the iterators, would be to just hoist them up to the containing scope:
intIter i;
dubIter j;
for (i = intVec.begin(), j = dubVec.begin(); i != intVec.end(); ++i && ++j)
{
result += (*i) * (*j);
}
Don't overcomplicate things.
for( size_t i = 0; i < intVec.size(); ++i )
{
result += intVec[i] * dubVec[i];
}
It seems you need an inner_product algorithm.
#include <vector>
#include <functional>
#include <numeric>
#include <iostream>
struct my_plus
{
double operator()(int i, double d)
{
return d + i;
}
};
struct my_multiplies
{
double operator()(int i, double d)
{
return d * i;
}
};
int main()
{
std::vector<double> dubVec;
std::vector<int> intVec;
double result = 0;
dubVec.push_back(3.14);
intVec.push_back(1);
result = std::inner_product(intVec.begin(),
intVec.end(),
dubVec.begin(),
0.0,
my_plus(),
my_multiplies());
std::cout << result << std::endl;
}
I used my own functors, because I suspect the standard multiplies and plus expect both operands to be of similar type, but I might be wrong.
intIter i;
dubIter j;
for (i = intVec.begin(), j = dubVec.begin(); i != intVec.end() && j != dubIter.end(); ++i, ++j)
{
result += (*i) * (*j);
}
Is there a way that I can get the count number for an iterator?
so if at first I had this:
for (int i = 0; iter < agents.size(); ++i)
{
agents[i]->Index(i);
}
bearing in mind that Index() sets an integer, how would I do this with iterators?
for (std::vector<Agent*>::iterator iter = agents.begin(); iter < agents.end(); ++iter)
{
(*iter)->Index(????)
}
You want distance http://www.cplusplus.com/reference/std/iterator/distance/
(*iter)->Index(distance(agents.begin(),iter));
You can substract iterators:
int distance = iter - agents.begin();
EDIT:
Only works for random access iterators. (+1 internet to Let_Me_Be)
Most generally, you can always hack up something yourself:
{
int i = 0;
for (auto it = agents.begin(), end = agents.end(); it != end; ++it, ++i)
{
(*it)->set_int(i);
}
}
If you have random access iterators, you can indeed use std::distance(agents.begin(), it) safely, as has been said already.