1

I have multiple arrays of various lenghts defined:

    int arr1[] = {1, 2, 3, 4};
    int arr2[] = {1, 3, 5, 7, 9};
    int arr3[] = {6, 8, 11, 5, 2, 3, 6};

I'm passing these to a function that will do something with each element inside of the array:

    void procesArr(int* array, int arrayLen) {
        for (int i = 0; i < arrayLen; i++) {
            // Do something, like print the value
            cout << "array[" << i << "]: " << array[i] << endl;
        }
    }

Then I can do:

    processArr(arr1);

Which results in:

    array[0]: 1
    array[1]: 2
    array[2]: 3
    array[3]: 4

But now I want to build a sequence of those individual arrays (the length of the sequence is not constant, can be from 2 to 5 individual arrays):

    int seq1[] = {*arr1, *arr2, ..., *arrN};

... and be able to pass that to a function that would do the same. However, without each array's length, a for loop would have no idea what the upper bound of each array is.

The end result I'd like is a function that will take the sequence as argument, then separate and process each individual array, separately. Essentially something like this:

    processSequence(seq1) {  // I think I need to include sizeof(seq1) here
        for (int s = 1; s < [length of seq1]; s++;) {
            // process each individual array
            for (int a = 1; a < [length of individual array]; a++) {
                cout << "seq1[" << s << "][" << a << "]: " << seq[s][a] << endl;
            }
        }
    }

And it would then produce something like:

    // First array
    seq1[0][0] = 1
    seq1[0][1] = 2
    seq1[0][2] = 3
    seq1[0][3] = 4
    // Second array
    seq1[1][0] = 1
    seq1[1][1] = 3
    seq1[1][2] = 5
    seq1[1][3] = 7
    seq1[1][4] = 9

This is where my lack of programming knowledge shows because I can't figure out how to do this.

2 Answers 2

2
(int* array, int arrayLen)

So we have three arrays of ints:

int arr1[] = {1, 2, 3, 4};
int arr2[] = {1, 3, 5, 7, 9};
int arr3[] = {6, 8, 11, 5, 2, 3, 6};

Then we can:

// Create an array of pointers to these arrays
// "Array of type" is implicitly converted to "pointer to type"
// Type `int[X]` is implicitly converted to `int*`
int *arrs[] = { arr1, arr2, arr3, };

// Create an array of lengths of the arrays inside
size_t arrslenin[] = { 4, 5, 7 };

// And we have the array of pointers has the length itself
size_t arrslen = 3;

Then we can pass it all to our function:

void processSequences1(int **arrs, size_t *arrslenin, size_t arrslen) {
    // iterate over elements in arrs
    for (size_t i = 0; i < arrslen; ++i) {
        // iterate over elements of the arrays inside arrs
        for (size_t j = 0; j < arrslenin[i]; ++j) {
            // print
            std::cout << "seq1[" << i << "][" << j << "]: " << arrs[i][j] << std::endl;
         }
     }
}

// call
processSequences(arrs, arrslenin, arrslen)

We can do the same with different structure - ie store the pointer with length together, in an object. Then pass array of these objects to our function. Ex. we can declare a "span" object that represents a span, a region in memory:

// it begs to write template<typename T> here
struct span {
    int *pnt;
    size_t len;

    // get size from type
    template<size_t N>
    span(int (&p)[N]) : pnt(p), len(N) {}

    // accessors
    size_t size() const { return len; }
    int* data() { return pnt; }
    int& operator[](size_t x) { return pnt[x]; }
};

Then create an array of spans:

span spans[3] = { span(arr1), span(arr2), span(arr3), };
size_t spanscnt = 3;

And pass it to our function:

void processSequences2(span *spans, size_t spanscnt) {
     // iterate over elements in spans array
     for (size_t i = 0; i < spanscnt; ++i) {
        // iterate over elements in the array inside spans[i]
        for (size_t j = 0; j < spans[i].size(); ++j) {
            // print
            std::cout << "seq1[" << i << "][" << j << "]: " << spans[i][j] << std::endl;
         }
     }
}

// call
processSequences(spans, spanscnt);

Or use STL and create ex. vector of vectors of ints (or use std::span from C++20, if available and use vector of spans). Below I use vector of vectors:

void processSequences3(std::vector<std::vector<int>> &v) {
     for (size_t i = 0; i < v.size(); ++i) {
        for (size_t j = 0; j < v[i].size(); ++j) {
            std::cout << "seq1[" << i << "][" << j << "]: " << v[i][j] << std::endl;
         }
     }
}

void f() {
    // note that values inside the arrays will be copied to vector
    std::vector<std::vector<int>> v = {
        std::vector<int>(arr1, arr1 + 4),
        std::vector<int>(arr2, arr2 + 5),
        std::vector<int>(arr3, arr3 + 7),
    };
    processSequences3(v);
}

Tested on tutorialspoint.

Sign up to request clarification or add additional context in comments.

2 Comments

Ok, I'm able to get the result I'm expecting from either using method 1 with arrays of pointers, or method 2 using structs. Thank you for giving both examples. This allows me to figure out which style I prefer. But now I'm stuck on the next step (which would be the last step for this project) - randomizing, as in pick one of them randomly (there are hundreds of those arrays/structs.) I'm going to try and figure it out first ... then if I can't figure it out, I'll post a different thread. Thanks again!
Nvm, I'm running out of memory with the large arrays that holds all of the sequences for random() to pick from. This is being done on an ATmega328p which only has 2k of SRAM. Welp, back to square ... uh ... 3? Everything else is working though!
1

In c and c++ you pass an array as a printer to the first element. The callee has no idea of the size. As you have noticed, you have to pass the size along the pointer. Another approach is to pass a special value at the last element of the array. This is how the zero-terminated strings work. Yet another approach is to reserve the first few elements to store the array size. Or embed the array in a structure which also started the size.

In c++ stl this is all solved by the vector class, which wraps the array, managers the size, growing and reducing the size of the array and other concerns.

Therefore, in c++ don't use the naked raw array but use vectors.

3 Comments

Structs ... I was afraid I would need to do that. Special characters ... hrm, maybe. I'll have to do some testing. Thanks!
Is there a special reason you don't want to use vectors? After all using c++without stl kinda defeats the point of using c++ . The only reason I would imagine is that you want to learn the language in details or need to build for some very limited platform. Anyways Kamil Cuk have given a very detailed answer with good examples .
Ah you hit the nail on the head. I do want to learn the language in detail, before I move onto different concepts and what not.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.