Erasing from vector - c++

I'm tried to erase all elements from a vector. In fact, I wrote that:
#include<iostream>
#include<vector>
std::vector<int> foo(std::vector<int> v)
{
std::vector<int> result;
std::cout << "Initial size = " << v.size() << std::endl;
for(int i = 0; i < v.size(); i++)
{
std::cout << "Size = " << v.size() << std::endl;
v.erase(v.begin() + i);
}
return result;
}
int main()
{
int a[] = {1 ,2, 5, 8, 213, 2};
std::vector<int> v;
v.assign(a, a+6);
foo(v);
}
DEMO
Why does that program prints
Initial size = 6
Size = 6
Size = 5
Size = 4
Where is
Size = 3
Size = 2
Size = 1
?

After third erasure you have i == 3 and v.size() == 3 and for exits

You should learn to use the appropriate loop for what you want to achieve, or simply use them appropriately.
You can use a for loop when you know in advance how many iterations you need to do, but be careful with how you use the index.
What you're doing inside the cycle is changing the size of the vector, so every iteration v.size() becomes smaller. When i == 3, the vector size has been reduced to 3 and the loop ends earlier than you expected.
There are some alternatives to what you want to achieve,
// Store the size of the array so it doesn't change midway in the loop
for(int i = 0, iEnd = v.size(); i < iEnd; i++)
{
std::cout << v.size() << std::endl;
//v.erase( v.begin() );
v.pop_back(); // pop_back is quicker but erases from the end
}
Or
// More appropriate, since you don't even need to know the size
while ( !v.empty() ) {
std::cout << v.size() << std::endl;
v.pop_back();
}
In these loops I assume that you don't care about any specific elements and just want to erase them. If you do care about specific elements other answers already mention that.
But really you should be using
v.clear();
because the STL already does that for you.

To remove all elements from a vector use std::vector::clear
#include <iostream>
#include <vector>
using namespace std;
int main()
{
std::vector<int> v(10);
cout << v.size() << endl;
v.clear();
cout << v.size();
cin.get();
return 0;
}

When the 1st element is deleted v.size() is also updated.So when it reaches size 3 its size is also 3 so it exits the for loop.
Note: try not to use the update condition (the middle condition of for loop ) as something that changes as the loop proceed unless you are sure about doing it.

You can understand the problem easy if you consider this abstract loop
size_t N = v.size();
size_t i = 0;
size_t j = N;
while ( i < j )
{
i++;
j--;
}
Thus you will delete exactly ( N + 1 ) / 2 elements in the vector or more precisely ( v.size() + 1 ) / 2 elements .:)
To remove all elements in the vector you could use member function clear().
if you want to remove elements of the vector selectively you could write
for ( auto it = v.begin(); it != v.end(); )
{
if ( need_to_delete ) it = v.erase( it );
else ++it;
}
where need_to_delete is any condition you want to use.

Because after the 3 erasures (when Size = 4), v.size() is 3 and i is 3, so i < v.size() is no longer true and you break out of the for loop, for(int i = 0; i < v.size(); i++) and return from the function.
If you just want to erase all elements of a vector, try v.clear().

You may be aware of the concept of "iterator invalidation", and you are using size_t i to avoid this. Unfortunately, what you're using is still essentially an iterator and erasing an element from a vector invalidates all iterators not just the ::iterator typed ones :).
invalidate is a carefully chosen term that has subtle nuances. It implies that the iterators didn't stop working, and that you may sometimes find they still work. But you shouldn't trust them to.
So invalidate doesn't mean they are broken or wrong, it means that you should reconsider them. For example, if you have captured vec.begin() and you have caused the vector to relocate it's data, the value of vec.begin() may no-longer be valid. It typically isn't, but you've been warned :)
std::vector is implemented over a simple contiguous array:
[ 0 ][ 1 ][ 2 ][ 3 ]
When you erase an element, the object it contains is destructed and then all of the elements to the right are moved left, physically resituated in memory.
[ 0 ][~~~~~][ 2 ][ 3 ] sz=4
[ 0 ][ 2 << 2 ][ 3 ] sz=4
[ 0 ][ 2 ][ 3 << 3 ] sz=4
[ 0 ][ 2 ][ 3 ][?????] sz=4
Then the vector reduces size by the count of elements removed, in this case 1:
[ 0 ][ 2 ][ 3 ] sz=3
You can see that the overall process of erase(), then, is expensive when the objects are not simple or when the vector is large, but I'll come back to that.
The problem with your implementation is that you increase i, and the size shrinks, so you wind up deleting every second element.
i=0
[ 0 ][ 1 ][ 2 ][ 3 ] sz=4
erase(i);
i=0
[~~~~~][ 1 ][ 2 ][ 3 ] sz=3
[ 1 << 1 ][ 2 ][ 3 ] sz=3
[ 1 ][ 2 << 2 ][ 3 ] sz=3
[ 1 ][ 2 ][ 3 << 3 ] sz=3
[ 1 ][ 2 ][ 3 ][?????] sz=3
[ 1 ][ 2 ][ 3 ] sz=3
i=0
i++;
i=1
[ 1 ][ 2 ][ 3 ] sz=3
erase(i);
i=1
[ 1 ][~~~~~][ 3 ] sz=3
[ 1 ][ 3 << 3 ] sz=3
[ 1 ][ 3 ][?????] sz=3
[ 1 ][ 3 ] sz=2
i=1
i++;
i=2
[ 1 ][ 3 ] sz=2
break;
std::vector provides clear to empty an array, but if you are interested in understanding how to perform such an operation yourself:
Option 1: delete from back
while (!vec.empty())
vec.pop_back();
What this does is destruct the last element and then reduce size. It's very cheap.
[ 0 ][ 1 ][ 2 ][ 3 ] sz=4
pop_back();
[ 0 ][ 1 ][ 2 ][~~~~~] sz=4
[ 0 ][ 1 ][ 2 ] sz=3
Option 2: Erase a range of elements
std::vector<int> vec { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
vec.erase(vec.begin() + 2, vec.begin() + 5);
vec.erase(vec.begin(), vec.end());
Option 3: Shrink the array:
vec.resize(0);
Option 4: Clear
This is the preferred and normal way to empty a vector
vec.clear();

Related

Ways to declare in C++ a 2D Array of pointers

I am struggling to understand the code below, I understand that t is a multidimensional character variable ( 3 row and 3 columns), and p is a pointer or array of pointers, the array of pointers shouldn't be declared as:
int **p[3][3];
p= new int*[3]
instead of *p = (char *)t; Can someone help me to understand the meaning of this declaration?.. thanks in advance
#include <iostream>
using namespace std;
int main() {
char t[3][3], *p = (char *)t;
for(int i = 0; i < 9; i++)
*p++ = 'a' + i;
cout << t[1][1];
return 0;
}
char t[3][3] allocates 9 chars in memory, something like:
1 2 3 4 5 6 7 8 9
[ ][ ][ ][ ][ ][ ][ ][ ][ ]
Next you let the pointer p point to the first allocated char ( *p = (char * )t
1 2 3 4 5 6 7 8 9
[ ][ ][ ][ ][ ][ ][ ][ ][ ]
*p
Knowing there are 9 allocated chars, you can now move the pointer forward with the statement *p++, so after first *p++
1 2 3 4 5 6 7 8 9
[ ][ ][ ][ ][ ][ ][ ][ ][ ]
*p
Then you insert the char 'a'+i into that memory location
1 2 3 4 5 6 7 8 9
[ ][a][ ][ ][ ][ ][ ][ ][ ]
*p
1 2 3 4 5 6 7 8 9
[ ][a][b][ ][ ][ ][ ][ ][ ]
*p
and so on...
Note operator precedence is important, ++ (postfix) has higher precedence than * (inderection), so first the pointer is incremented by one (++), and then the inderection gives 'access' to the allocated memory, if you prefer to be more explicit about it, you can use *(p++) instead.
whats happening is that it's declaring the variable p as having the same pointer as your 2D array t. That way it can access it without requiring nested forloops.
'graphically' the contents would be accessed something like this:
pointer in question.
T
->1 2 3
4 5 6
7 8 9
P
->1 2 3 4 5 6 7 8 9
If you have an array like this
char t[3][3];
then pointer to its first element can be declared like
char ( *p )[3] = t;
That is the pointer p points to an object of type char[3]. If to increase the pointer ++p then the value in p will be increased by the value equal to sizeof( char[3] ) that is p will point to the second "row" of the array.
The value stored in p after this declaration
char ( *p )[3] = t;
is equal to the value of the expression &t[0][0]. The difference is the type of the objects pointed to by these pointers.
Thus you can write for example
char *p2 = reinterpret_cast<char *>( p );
So p2 and p have the same value but increasing the pointer p2 moves it "right" to point to the second character of the array while increasing the pointer p moves it "right" to point at once to the second "row" of the array.
So you can reinterpret the pointer p as a pointer of type chsr * to traverse the array character by character.
You can write either using C casting
char *p2 = (char *)t;
or using C++ casting
char *p2 = reinterpret_cast<char *>( t );

ofStream printing in another function

I have a weird problem going on. I have two functions, which both have an ofstream passed by reference. However when I call the second function, part of the first function is being printed.
Here is the first function:
void GamePlay::dealDominos(ofstream& outStream, int seed){
for(int i = 0; i < 10; ++i)
{
outStream << "random " << rand() << endl;
}
}
My second function is:
void GamePlay::findLongestSeq(ofstream& outStream)
{
outStream << toStringSeq(label, maxSeq) << endl;
}
However, my output looks like this:
NEW MAX [ T 0 8 ]
NEW MAX random [ T 0 8 ][ T 8 1 ]
NEW MAX ndom [ T 0 8 ][ T 8 1 ][ T 1 1 ][ T 1 2 ]
NEW MAX dom [ T 0 8 ][ T 8 1 ][ T 1 1 ][ T 1 2 ][ T 2 11 ]
MAX SEQ FOR: dom [ T 0 8 ][ T 8 1 ][ T 1 1 ][ T 1 2 ][ T 2 11 ]
I don't want the word "random" to be printed between the label and the sequence..
How do I fix this?
It looks like you've got two separate ofstream objects referring to the same underlying file, which is a pretty bad idea unless you're going to do lots of seek operations and flushes on every write, to ensure the file positions get updated for every write.

Copying upper MatrixXd to lower MatrixXd (Eigen3) C++ library

I've got a lower triangular MatrixXd and I want to copy its lower values to the upper side as it'll become a symmetric matrix. How can I do it?
So far I've done:
MatrixXd m(n,n);
.....
//do something with m
for(j=0; j < n; j++)
{
for(i=0; i<j; i++)
{
m(i,j) = m(j,i);
}
}
Is there a fastest way to do it? I was thinking of some internal method that is able to "copy" the lower triangular matrix to the upper.
Say I've got this matrix, we call m:
1 2 3
4 5 6
7 8 9
what I need to obtain in m is :
1 4 7
4 5 8
7 8 9
I also know you can get the upper or the lower part of the matrix to do something:
MatrixXd m1(n,n);
m1 = m.triangularView<Eigen::Upper>();
cout << m1 <<endl;
1 2 3
0 5 6
0 0 9
But I can't yet get what I want...
I assume here that you are referring to working with the Eigen3 c++ library. This is not clear from your question. if not, you should consider it. In any case, within Eigen, there is no need to actually copy the triangular part, to get a selfadjoint matrix. Eigen has the concept of views, and you can use a self adjoint view in order to perform an operation like e.g.
using namespace Eigen;
MatrixXd m(m,n);
...
(generate uppper triangular entries in m)
...
VectorXd r(n), p(n);
r = m.selfadjointView<Upper>() * p;
here is a small example to illustrate using fixed size matrices:
#include <Eigen/Core>
using namespace std;
using namespace Eigen;
int main()
{
Matrix2d m,c;
m << 1, 2,
0, 1;
Vector2d x(0,2), r;
// perform copy operation
c = m.selfadjointView<Upper>();
cout << c << endl;
// directly apply selfadjoint view in matrix operation
// (no entries are copied)
r = m.selfadjointView<Upper>() * x;
}
the output will be
[1, 2,
2, 1].
now, the result in r is the same as if you had used c * x instead. Just that there is no need for copying the values in the original matrix to make it selfadjoint.
In case the selfadjointView is not an option for you, the solution is to use triangularView on the destination matrix:
m.triangularView<Lower>() = m.transpose();
The simplest way I can think of is by copying the upper part of m matrix trasposed on the upper part:
m.triangularView<Upper>() = m.transpose();
For example, the following code:
MatrixXd m(3,3);
m << 1, 2, 3, 4, 5, 6, 7, 8, 9;
m.triangularView<Upper>() = m.transpose();
std::cout << m << std::endl;
Gives the output you asked for:
1 4 7
4 5 8
7 8 9
Regards.
Simply:
m = m.selfadjointView<Upper>();
I think you are doing it the right way. If you knew some details about the memory layout of data in the matrix you could use some low-level optimizations. One of the techniques is loop tiling.
If speed is a big issue, I would not copy anything just decorate/wrap the matrix object with a coordinate inverting object that would flip the (x,y) to (y,x). if you make the () operator an an inline function it will not incur any significant cost when you use it.
This works, you can cut something but you need at least n*m/2 (less something), so only of a 2x
edit: I see that you use this matrixd object... the syntax is different, but the algorithm is this, anyway
#include <stdio.h>
int main ( )
{
int mat [ 4 ] [ 4 ];
int i, j;
mat [ 0 ] [ 0 ] = 0;
mat [ 0 ] [ 1 ] = 1;
mat [ 0 ] [ 2 ] = 2;
mat [ 0 ] [ 3 ] = 3;
mat [ 1 ] [ 0 ] = 4;
mat [ 1 ] [ 1 ] = 5;
mat [ 1 ] [ 2 ] = 6;
mat [ 1 ] [ 3 ] = 7;
mat [ 2 ] [ 0 ] = 8;
mat [ 2 ] [ 1 ] = 9;
mat [ 2 ] [ 2 ] = 10;
mat [ 2 ] [ 3 ] = 11;
mat [ 3 ] [ 0 ] = 12;
mat [ 3 ] [ 1 ] = 13;
mat [ 3 ] [ 2 ] = 14;
mat [ 3 ] [ 3 ] = 15;
for ( i = 0; i < 4; i++ )
{
for ( j = 0; j < 4; j++ )
printf ( "%02d", mat [ i ] [ j ] );
printf ( "\n" );
}
printf ( "\n" );
for ( i = 1; i < 4; i++ )
{
for ( j = 0; j < i; j++ )
mat [ j ] [ i ] = mat [ i ] [ j ];
}
for ( i = 0; i < 4; i++ )
{
for ( j = 0; j < 4; j++ )
printf ( "%02d ", mat [ i ] [ j ] );
printf ( "\n" );
}
printf ( "\n" );
scanf ( "%d", &i );
}

debugging arrays of lists

For code such as this:
std::list<int> a[3][3];
int myNumber = 0;
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
a[i][j].push_back(myNumber);
myNumber++;
}
}
The Local window of the debugger shows:
There is no easy way to go through and see that:
list a[ 0 ][ 0 ] contains 0
list a[ 0 ][ 1 ] contains 1
list a[ 0 ][ 2 ] contains 2
list a[ 1 ][ 0 ] contains 3
etc.
I can only see what lists [ 0 ][ 0 ], [ 1 ][ 0 ], and [ 2 ][ 0 ] contain but I want to see what all the lists contain. How do I go about doing this in Visual Studio 2010?
"There is no easy way to go through and see that list a[0][2] contains 2"
You right click somewhere into code, chose Quick Watch, write there a[0][2] and with Add Watch you put into "Watch 1" so that you can see your list<int> at a[0][2] properly.
When you declare simple list<int> l;, Visual Studio shows it properly. You are able to see all elements.
But when you declare array of lists like this:
std::list<int> l[2];
l[1].push_back(3);
l[1].push_back(4);
then variable l is considered pointer to first std::list<int> so even if you push elements into list at index 1, Visual Studio just shows you that l is empty list: some address [0](). I can see l[1] only if its in Watch:
Possible solution is to replace simple c-style array ([]) with std::vector :
std::vector<std::list<int> > l;
l.resize(2);
l[1].push_back(3);
l[1].push_back(4);
so l is not considered a pointer to first list anymore. Since l is vector Visual Studio displays you all elements properly:

Returning a Pointer to a Multidimensional Array

I'd like to use the following function to return a transposed pointer to a multidimensional array.
Code
float** Matrix3f::Transpose( void )
{
float matrix[MATRIX3_DIMS][MATRIX3_DIMS] =
{
{ mMatrix[ 0 ][ 0 ], mMatrix[ 1 ][ 0 ], mMatrix[ 2 ][ 0 ] },
{ mMatrix[ 0 ][ 1 ], mMatrix[ 1 ][ 1 ], mMatrix[ 2 ][ 1 ] },
{ mMatrix[ 0 ][ 2 ], mMatrix[ 1 ][ 2 ], mMatrix[ 2 ][ 2 ] }
};
float** ret = new float*[ MATRIX3_DIMS ];
for ( int i = 0; i < MATRIX3_DIMS; i++ )
{
for ( int j = 0; j < MATRIX3_DIMS; j++ )
{
( *ret )[ i ][ j ] = matrix[ i ][ j ];
}
}
return ret;
}
Description
As shown, I declare a multidimensional array using initialization syntax(using the class-member matrix - mMatrix - to create a transposed version of the matrix itself. I then assign a multidimensional pointer to an array (ret) and loop through, assigning each member of the local array - matrix - to the ret pointer array.
The error I receive is the following:
error: invalid types ‘float[int]’ for array subscript
Question
What exactly am I doing wrong, and how can I accomplish this task?
ret is a pointer to pointer to float. When you dereference it, like this: (*ret), you get a pointer to float. When you take an index on that, like this: ( *ret )[ i ], that gives you a float. When you take an index on that, like this: ( *ret )[ i ][ j ], well, you're trying to index off of a float. That's not legal.
Putting my disgust for this style of coding aside, the first thing you're doing wrong is you are not allocating the sub-arrays. The compiler error though, refers to the error I illustrated in the first paragraph. Just remove the dereferencing of ret to fix that. You end up with this:
for ( int i = 0; i < MATRIX3_DIMS; i++ )
{
ret[i] = new float[MATRIX3_DIMS];
for ( int j = 0; j < MATRIX3_DIMS; j++ )
{
ret[ i ][ j ] = matrix[ i ][ j ];
}
}
This is totally not exception safe though, and you should be using a class that properly manages memory in an exception safe way, like std::vector.