PgrAm
PgrAm

Reputation: 701

using only part of an array

I have a dynamically allocated array of float and I need to pass this array as an argument to three different functions but each function need to get a different range of the array. Is there some way I can send the array with elements 0 to 23 to one function, elements 24 to 38 to another, and elements 39 to 64 to a third function.

In some languages(like python I think) you can do something like this:

somefunction(my_array[0:23]);
somefunction(my_array[24:38]);
somefunction(my_array[39:64]);

However I am using c++ and I am not aware of any way to do this in c++.

Does anybody know how to do this?

somefunction(); is a function from an API so I can not modify the arguments it takes.

Upvotes: 18

Views: 54508

Answers (7)

Harsath
Harsath

Reputation: 173

I would return or do something like std::pair<pointer_type, pointer_type> which contains {Begin_Pointer, End_Pointer} so, Let's if we need to slice a raw array(in C/C++ land just a pointer) with specific parts/blocks. I would return take something like

pointer_type element_begin = raw_array+begin;
pointer_type element_end = raw_array+end;
std::pair<pointer_type, pointer_type> = std::make_pair(element_begin, element_end);

I will have a convenient function to which I give those begin and end non-negative values and it will return me a std::pair

Upvotes: 0

Harper Shelby
Harper Shelby

Reputation: 16583

If you write the functions to operate on a pair of forward iterators rather than an array, you could just pass it like so:

somefunction1(my_array, my_array + 24);
somefunciton2(my_array + 24, my_array + 39);
somefunction3(my_array + 39, my_array + 65);

Pointers are forward iterators, and this would allow the functions to be used over parts of vectors, queues, or other STL containers as well.

Upvotes: 15

Al P.
Al P.

Reputation: 643

The python example is making copies. If that's okay for your use case, you could do something like this (I'm swapping out your vanilla arrays for std::vector):

#include <iostream>
#include <vector>

void somefunction(std::vector<int> v) {
    std::cout << "vector has " << v.size() << " elements,"
        << " first value is " << *v.begin() << ","
        << " last value is " << *(v.end()-1) << std::endl;
}

int main() {
    std::vector<int> a;
    for (int i=0; i<65; i++) {
        a.push_back(i);
    }
    somefunction(std::vector<int>(a.begin(),a.begin()+23));
    somefunction(std::vector<int>(a.begin()+24,a.begin()+38));
    somefunction(std::vector<int>(a.begin()+39,a.begin()+65));
}

which outputs:

vector has 23 elements, first value is 0, last value is 22
vector has 15 elements, first value is 23, last value is 37
vector has 27 elements, first value is 38, last value is 64

But it sounds like you can't use std::vector, because somefunction() has a signature you can't change. Luckily, you can do similar gymnastics just manually copying parts of the array, as below:

#include <iostream>
#include <string.h>

void somefunction(int v[], int len) {
    std::cout << "vector has " << len << " elements,"
        << " first value is " << v[0] << ","
        << " last value is " << v[len-1] << std::endl;
}

int main() {
    int a[65];
    for (int i=0; i<65; i++) {
        a[i] = i;
    }
    int b[23];
    memcpy(b, a, 23*sizeof(int));
    somefunction(b, 23);
    int c[15];
    memcpy(c, a+23, 15*sizeof(int));
    somefunction(c, 15);
    int d[27];
    memcpy(d, a+38, 27*sizeof(int));
    somefunction(d, 27);
}

which again outputs:

vector has 23 elements, first value is 0, last value is 22
vector has 15 elements, first value is 23, last value is 37
vector has 27 elements, first value is 38, last value is 64

Upvotes: 9

AusCBloke
AusCBloke

Reputation: 18492

There are two ways you could do it:

void useArray(int array[], size_t len) { ... }
...
useArray(myArray, 24);
useArray(&myArray[24], 15);
useArray(&myArray[39], 26);

OR

void useArray(int *start, int *end) { ... }
...
useArray(myArray, myArray + 24);
useArray(myArray + 24, myArray + 39);
useArray(myArray + 39, myArray + 65);

The first is more of a C way, the second a more C++ way. Note that with the second way, the range is [start, end) - end isn't included in the range as you see a lot in C++.


EDIT: You edited your post to mention that you're using glTexCoordPointer(). In that case pass the start of the array to glTexCoordPointer(), which will be either myArray, myArray + 24 or myArray + 39.

The size of the array still has to be known though, and is passed to functions such as glDrawArrays or glDrawElements(), which will then start reading from the array. If you were using glDrawArrays(), the length of the array is passed as the second argument. Therefore your code could be something like:

glTexCoordPointer(..., ..., ..., my_array);
...
glDrawArrays(..., 0, 24);

glTexCoordPointer(..., ..., ..., my_array + 24);
...
glDrawArrays(..., 0, 15);

glTexCoordPointer(..., ..., ..., my_array + 39);
...
glDrawArrays(..., 0, 26);

Upvotes: 5

xtofl
xtofl

Reputation: 41509

You could refactor your functions to use 'iterators': a pointer to the begin and to the end of the array-range you're interested in:

 void somefunction( int* begin, int* end ) {
    for( int* i=begin; i != end; ++i ) {
       //stuff with *i
    }
 }


 // usage:
 somefunction( my_array+0, my_array+23 );
 somefunction( my_array+24, my_array+38 );
 somefunction( my_array+39, my_array+64 );

Bonus points: if you make your function a template, you can use it with other iterators too:

 template<typename T>
 void somefunction( T begin, T end ) {
    for( T i=begin; i != end; ++i ) {
       //stuff with *i
    }
 }

 vector<int> values(100);
 somefunction( values.begin(), values.end() );
 somefunction( values.rbegin(), values.rend() );

...

Upvotes: 0

Benjamin Lindley
Benjamin Lindley

Reputation: 103713

Your function is going to need some way to determine the size of the array anyway. I suggest you make the function take begin and end iterators, in the style of the standard library algorithms, like so:

template<typename I>
void somefunction(I begin, I end);

Then, you can call it with your array like this:

somefunction(my_array, my_array + 24);
somefunction(my_array + 24, my_array + 39);
somefunction(my_array + 39, my_array + 65);

Upvotes: 7

TJD
TJD

Reputation: 11896

There is no upper bound range checking, so you have to take care of that yourself. But you can pass &my_array[0] to one function, and &my_array[24] to another. Maybe add a len parameter to your function to take care of upper range.

Upvotes: 0

Related Questions