1

In order to get more familiar with C++, I have started working on some algebraic problems. Now, I have created an algorithm which generate a combination of numbers, with some constraints, based on an input number:

void abc(const int n) {
    std::vector<int> aOut, bOut, cOut;  // creating vectors to store values (dynamic int arrays)
    for (int a = 9; a <= n - 2; a++) {
        for (int b = a + 1; b <= n - 1; b++) {
            for (int c = b + 1; c <= n; c++) {
                aOut.push_back(a);
                bOut.push_back(b);
                cOut.push_back(c);
                // std::cout << "a = " << a << "    b = " << b << "    c = " << c << std::endl;
        }
    }
}

Now, I need to continue working with these vectors, so I need to return them somehow. I have tried to create an int array of the size: int ABC[N][3], where const int N = cOut.size();. This does not work, as N is not accepted as a constant.

I also tried making a counter in the loop where I generate the vectors, which I then transferred to a string which I then transferred to a constant integer - this did not work either.

I tried making a pointer to a constant int, and using it to change the constant in the loop, which did not work either.

I even found a way to calculate the size based on my loops:

const int n = 20;
const int n1 = n - 10;                    // Manipulating input
const int N = n1*(n1 + 1)*(n1 + 2) / 6;   // Size of vectors

And then passing the value to the function as:

void abc(const int n, const int N) { // same code as before }

But nothing works. I am honestly out of ideas (and losing my head). I have browsed trough the forum and google, but without luck. If someone could point me in the right direction, I would be forever grateful.

Of cause the solution includes changing the void to a function that returns the parameters. I added the void as I would like to check if the values were printed correctly.

bgaard
  • 132
  • 3
  • 13
  • In case it isn't clear: The goal is to change the `void` to an `int` and then extract the data via the `return` command. – bgaard Mar 14 '17 at 19:32
  • 1
    What do you mean with "export"? What does a counter have to do with exporting things? Size of loops also has nothing to do with exporting. Please clarify what you are trying to accomplish. – Rakete1111 Mar 14 '17 at 19:32
  • 1
    Put them in a `std::vector` and return that from the function? – Galik Mar 14 '17 at 19:36
  • @Galik What do you mean? Put the vectors inside a vector? To create a Matrix? Is that possible, and if so, could you clarify the syntax? – bgaard Mar 14 '17 at 19:40
  • @bgaard Galik probably means to merge them together to one vector, and return that. – Rakete1111 Mar 14 '17 at 19:43
  • 1
    Something like this: `std::vector> outs; outs.push_back(aOut); outs.push_back(bOut); outs.push_back(cOut); return outs;` – Galik Mar 14 '17 at 19:44
  • 3
    `std::array, 3> outArray;` is an array containing your three vectors. `outArray[0]` would replace `aOut`, etc. – ssell Mar 14 '17 at 19:44
  • I'll give it a try! Thanks. – bgaard Mar 14 '17 at 19:51
  • @ssell The syntax does not work. I get an error message saying "incomplete type is not allowed". I ran into another problem where I need this. – bgaard Mar 15 '17 at 09:27
  • 1
    @bgaard Do you have both `#include ` and `#include ` ? – ssell Mar 15 '17 at 14:08
  • @ssell I'll just go shoot myself right away (that's a no btw...). – bgaard Mar 15 '17 at 14:27
  • @bgaard No worries, it happens to all of us! – ssell Mar 15 '17 at 14:32

2 Answers2

3

How about creating an element (container) which encapsulates your 3 vectors as a return element?

The problem you're having is that functions (like Mathemematicians want to) return one value, but this can be any value :).

You could use a class or a struct which will has the vectors as attributes:

struct returnElement { // choose an adequate name
  std::vector<int> aOut, bOut, cOut;
};

so now your abc function would return the returnElement struct. It could look something like this:

returnElement abc (const int n) {
    returnElement ret;  // creating vectors to store values (dynamic int arrays)
    for (int a = 9; a <= n - 2; a++) {
        for (int b = a + 1; b <= n - 1; b++) {
            for (int c = b + 1; c <= n; c++) {
                ret.aOut.push_back(a);
                ret.bOut.push_back(b);
                ret.cOut.push_back(c);
        }
    }
    return ret;
}
Santiago Varela
  • 2,199
  • 16
  • 22
  • 1
    Thanks, this is a pretty cool way to do it! One question though. Is there a big difference between using a struct and a class? As I see it, it is easier to use the struct, since I can skip all the "public/private"- and "constructor/destructor"-stuff :) – bgaard Mar 14 '17 at 21:00
  • 3
    Good question. There is really not much difference between structs and classes in C++, except the default visibilty of the members inside the container. C++ struct members are public by default, whereas class members are private by default. They both have inheritance as well. Personally I like to use structs for smaller data were I don't use functions to manipulate their state. Check this answer: http://stackoverflow.com/questions/54585/when-should-you-use-a-class-vs-a-struct-in-c – Santiago Varela Mar 14 '17 at 21:13
1

Why not have an std::array of std::vector?

std::array<std::vector<int>, 3> abc(int const n)
{
    std::array<std::vector<int>, 3> outArray;

    for (int a = 9; a <= n - 2; a++) 
    {
        for (int b = a + 1; b <= n - 1; b++) 
        {
            for (int c = b + 1; c <= n; c++) 
            {
                outArray[0].push_back(a);
                outArray[1].push_back(b);
                outArray[2].push_back(c);
            }
        }
    }

    return outArray;
}

To answer your question concerning array sizes,

I have tried to create an int array of the size: int ABC[N][3], where const int N = cOut.size();. This does not work, as N is not accepted as a constant.

The size of an array (whether raw or std::array) must be compile-time constant. If the size is not known at compile-time you must either create a dynamic array (using new) or use an std::vector.

If you know how large the vector is to be, you can reserve space in it for your elements, like so:

std::vector<int> yourVec;
yourVec.reserve(100);     // reserve space for 100 ints

or

std::vector<int> yourVec;
yourVec.resize(100, 0);   // populates yourVec with 100 ints with value 0

See Choice between vector::resize() and vector::reserve() for the differences between reserve and resize.

Community
  • 1
  • 1
ssell
  • 6,429
  • 2
  • 34
  • 49