1

I am trying to split a vector into "almost equal" parts, and create subvectors for those parts.

I have asked the original question here: How to split a vector into n "almost equal" parts but I found a really good solution, what I am trying to use, from here: Best way to extract a subvector from a vector?

I wrote this function for creating integers for start and end values (round is my function which rounds to specified digits.)

void split( double number, double parts )
{
    double loop = number / parts;

    for( int i = 0; i < parts; i++ )
    {
        int start = round( i * loop, 0 );
        int end = round( ( i + 1 ) * loop - 1, 0 );
        cout << start << " " << end << endl;
    }
}

This function so far works OK, but my problem is that when I try to run this:

vector<some> dest( &source[start], &source[end] );

Then it creates one LESS element, then required. I mean for example if I call it with

vector<some> dest( &source[0], &source[99] ); 

then it will have 99 elements, instead of 100. Why is this happening?

How can I fix it? If I use [end+1], then it terminates at the last vector, with "subscript out of range."

Community
  • 1
  • 1
hyperknot
  • 13,454
  • 24
  • 98
  • 153

2 Answers2

4

The vector constructor (and all STL constructors that accept pointer ranges, for that matter) are designed to take in a range of STL-style iterators. When using iterators, you specify a range by providing a pointer to the first- and the past-the-end elements, not the first and last elements. If you wanted to create a vector as a copy of the subrange (0, 99) out of another vector, you could write

vector<some> dest(source.begin(), source.begin() + 100);

Note that this uses vector iterators to specify the slice of the first 100 elements rather than operator[], which has undefined behavior when the provided index is out of bounds. In your case, this undefined behavior is manifesting as a runtime debug error. Iterators don't have this problem, since they're specifically designed to be used this way.

If you want to use raw C++ arrays as input to the vector constructor, you could do it like this:

vector<some> dest(source, source + 100);

Hope this helps!

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • OK, I understand. So for my function, the proper call is this? vector dest( source.begin() + start, source.begin() + end + 1 ); – hyperknot Jul 28 '11 at 19:19
  • Assuming that `end` is the index of the last element that you want, yes, that's correct. Typically, though, the name `end` is used with respect to C++ containers to indicate one-past-the-end rather than the actual last element, so you might want to rename it to something like `last`. – templatetypedef Jul 28 '11 at 19:20
  • Thanks! Its called 'last' now – hyperknot Jul 28 '11 at 19:25
0

While it's not legal to use &v[n] if v is an std::vector with n elements you can use instead

vector<some> dest(v.begin()+first, v.begin()+last+1);

even if last+1 == n.

6502
  • 112,025
  • 15
  • 165
  • 265