How do I return a 2D array from a function

Pages: 12
lol thanks, I just moved the for loop that prints the ticket from Input to main (after the Input function is called and run of course) and the values are there even outside of Input. Again, though, how can I be sure that those values are ONLY changed by player Input, and not accidentally through another function? It's probably as simple as "don't write bad code that would DO that", but if I can lock it so other functions can only read that memory, that would be super useful!
Now I need to be certain that that data remains when Input finishes running


You can do what Kazekan said: use a for loop to check if the array from main() is the same as it were in Input(). If you passed the array from main to Input correctly, there shouldn't be a problem:

1
2
3
4
5
6
7
8
9
10
11
void Input(int Guess[][6], int Lines)
{
    //modify Guess as you please and the values in Guess from main() will change as well
}
//...

int Guess[Lines][6]; //as cire said, not valid C++ but I'm sure your teacher won't mind. Just don't get in the habit of doing it this way, alright :) ?

Input(Guess, Lines);

//...rest of code... 


edit:
how can I be sure that those values are ONLY changed by player Input, and not accidentally through another function?

Without classes and encapsulation, I don't think you can "lock" the variable during run-time.
Last edited on
yep did this and it works, see above, thank you =]

now this isnt a problem per se, but I am curious, I have put that same loop in 4 place to make sure my values are consistent where they should be, and they are, except, immediately after the Ticket function when the user chooses the number of lines (and therefore the length of the array that is the player's ticket) and before the player inputs values TO those lines on their ticket, it prints out all kinds of wacky numbers, they seem to be different each time, per line, and some of them will be very similar, like 52 4 5 5 5, but other lines have things like 4613568 2686460 2686472 4628136 4673728 4649024... why exactly is it doing this? Again, it doesn't matter, because in the next function I SET the values to what I want and then use them later on just fine, I am just curious, I assume something to do with how RAM works?
I have made Lines int constant now, but it functioned before, I'm not sure I get why this is necessary to change? I never change the value of the number of lines mid entry, only after each game. Which raises the question, why is it a constant if I can change it? That would imply to me that once it has a value, that value is constant, and therefore I cannot change the length of the first dimension in my array, but I can do that, with or without declaring Lines as const int...


I perhaps mispoke. In order to define the dimensions of an array, a compile-time constant must be used. Using a constant that is initialized with the return value from a function requesting the size from the user, for instance, would not be legal.

If it is a constant, you cannot change it without casting away the constness and doing so will result in undefined behavior.

1
2
    const int lines = 6 ;
    lines = 7 ;  // won't compile.  lines is constant. 



This following is not legal C++:

1
2
3
4
5
int main()
{
    int array_size = 6 ;
    int array[array_size] ;
}


on a compliant compiler it will fail to compile. You can make yours compliant in this respect by disabling the extension that allows variable length arrays.

If the vla extension is enabled:
1
2
3
4
5
6
7
 int main()
{
    int array_size = 6 ;
    int array[array_size] ;

    array_size = 10 ;
}

will not change the number of elements array can hold.

therefore I cannot change the length of the first dimension in my array, but I can do that, with or without declaring Lines as const int...


You cannot, either way.

[edit: compile-time constant - top of the post.]
Last edited on
whether I set Lines as const or not, it still functions as I had intended, where it takes the user input that defines the ticket length, and thus allows you to only fill the array to that length (and print as such using Length of the ticket as the stop point of my for loops). Whether this CHANGES the size of the array, constant or not, I do not know, but it APPEARS to due to the behaviour of my program, which is fine, it compiles and runs fine and without errors occuring I can only assume this will remain functional. I will post my final source code either here or in a new thread when I finish so people can pick it apart and tell me where I could improve, but in just a couple days I've already gone from extremely limited knowledge, to quite good knowledge and understand but currently lacking in experience, I think I have gotten quite far quite fast and I'm still learning all the time, thanks to you(and everyone here), my friends, and good old fashioned hard work (looking at tutorials also counts).
well this is probably a stupidly simple thing, but my random number generating function only generates one random number and prints it several times... why on earth is this?? lol

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void Generate(int Ball[])
{
    cout << "Lets get those balls rolling...\n\n";

    for(int n=0;n<6;n++)
    {
        do
        {
            srand ( time(NULL) );
            Ball[n] = rand() % 49 + 1;
        }
        while(Ball[n] < BetLow || Ball[n] > BetHigh);

        cout << Ball[n] << "\t";
    }

}
You only have to call the srand() function once, so moving it outside the for loop does the trick.
As goth said, you'll need to put it outside the do-while loop. This is because you only need to seed your random generator once - seeding it more than that will create randomly generated random numbers, and a random random number turns out to not be as random as you'd think. :)
ah awesome thank you, I know random is based on system clock or something so it is only SO random, but I thought re setting the random seed would only make it MORE random, not sure why it is the exact opposite of random...

Anyway, am getting very close I can feel it, but a new problem has arisen. As you most likely know, inputting a character by accident to an int type variable will cause the program to infinitely loop and be useless. I was looking for a way to avoid this, and came accross an interesting method, that takes an input as a string first, then checks to see if it can convert that string into the type required by the variable requested, which for me is of course int, meaning 123 will be valid, xyz will be invalid, 1yz will be valid as 1, and x23 will be invalid.

This works perfectly for me, EXCEPT that the first time this algorithm runs, the first number on the first line of every ticket will feedback once that it is invalid, before the user even inputs any data. The message of invalidity is in the else statement right at the end so why does it come out before I use getline?? I'm sure it's a simple case of ordering things within my loop, but can you guys spot the problem?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
            do
            {
                string input = "0";

                cout << n + 1 << ")\t";
                //Guess[Line][n] = 0;


                getline(cin, input); //cin goes to input string first
                stringstream myStream(input); //puts input string into myStream of type stringstream

                if (myStream >> Guess[Line][n]) //if stringstream detects that myStream can go into the array as an int type variable...
                {                               //loop continues as normal
                    if (Guess[Line][n] < BetLow)    //can't bet below 1
                    {
                        cout <<"Too low, try again! (1-49)\n";
                    }

                    else if (Guess[Line][n] > BetHigh)  //can't bet over 49
                    {
                        cout << "Too high, try again! (1-49)\n";
                    }

                }

                else //else stringstream CAN'T put myStream into the array...
                {
                    cout << "\nInvalid number, please try again" << endl << endl;
                }
            }
            while(Guess[Line][n] < BetLow || Guess[Line][n] > BetHigh);
so does anybody have any idea why my integer input protection system works on all except the first request of the first number of the first line on every ticket? It also means that on any ticket except the first, I can no longer change the value of Guess[1][1], it tells me I have entered an invalid number without me entering any number at all, and when it prints the ticket later, the first value is whatever I assigned to it when I entered the first ticket. Again, all other numbers on all other lines on all tickets works perfectly, EXCEPT the first number on the first line, every time....

also, in addition to that question, there is a new one. Why is this for loop within a for loop within a for loop not doing what it looks like it should do? Basically, it checks each random ball from the machine, with each number on a line, for each line on the ticket, sequentially, as it should do.

So it takes the value of line 1, number 1, and checks if it is equal to ball 1, then ball 2, etc.
Then it takes the value of line 1, number 1, and again checks against all the balls.
And so on in that fashion.

I have an array that stores the score relating to the balls that my ticket matches, which is int Matches [Lines]. When it detects that the number on the ticket matches one of the balls, it adds 10 to the score for that line. and it works.

what it SHOULD do, but doesn't is add 1 when it detects a match between the ticket and the bonus ball. This is so that it is easy to decide how much the player should win. For example, matching 3 balls will give a score of 30, whereas matching 5 balls and the bonus ball will give a score of 51, so it is simply a case of reading that score and paying out the associated prize.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
int Compare(int Lines, int Guess[][6], int Ball[], int BonusBall, int Matches[])
{
    for(int Line = 0; Line < Lines; Line++)
    {
        Matches[Line] = 0; //resets counter per line to avoid winning on a line that you won on last round

        for(int n = 0; n < 6; n++)
        {
            if(Guess[Line][n] == BonusBall) //DOES NOT WORK
            {
                Matches[Line] = Matches[Line] + 1;
                cout << "BONUS GET on line " << Line;
            }

            for(int b = 0; b < 6; b++)
            {
                if(Guess[Line][n] == Ball[b])
                {
                    Matches[Line] = Matches[Line] + 10;
                }
            }
        }


        if(Matches[Line] > 0)
        {
            cout << "\nYou scored " << Matches[Line] << " on line " << Line + 1 << " of " << Lines << "!";
        }
    }
}


Again, this is probably something staring me in the face, but can someone help please? Thanks everybody
For your first question, you probably have a loose character in the input stream (this happens often and it caused me some headache on a recent project). Use cin.ignore(), cin.get() or both of them to catch any unwanted characters. If that doesn't work use this little piece of code
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n')

As for you second question, try debugging and see if the two values are indeed the same. You can use this cout << Guess[Line][n] << " " << BonusBall; cin.get(); to see if they are equal.
I got a guy to help me with it, it turn's out that getline doesn't jive well with cin, simply changing that cin >> input instead fixed problem one. He has also shown me how to allocate the array memory to heap instead of stack, though this confuses me but i just about get it, just about, and it works the same as before, using new ** as the declaration. This, he has told me, creates a memory leak every time you change the size of the array, which isn't too bad as it is under control and part of a small program, but I want to then delete that array as you apparently SHOULD do when creating a dynamic array and no longer need it, which is only a line or two at the end of my main game loop, but I will figure that out later. My scoring system now works as well, it checks the bonus ball and adds 1 to the score to flag a bonus match, I think this was fixed by making the Matches array which holds the score for each line, ALSO dynamic (but only one dimensionally this time). Whatever it was, it works perfectly now.

Now I am just short a few simple features. I will need to close the memory leak by my two size changing arrays, but for now, I absolutely NEED to get a bubble sort on each line working, so you can input your numbers on the line in any order, but the print in ascending order. My bubble sort is below, it runs just before the usual printing thread, so it should re order each line, then print each line, but it doesn't work for some reason. It compiles, it just doesn't DO the bubble sort.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    //---BUBBLE SORT CODE-------------------------------------
    for(int Line = 0; Line < Lines; Line++)
    {
        int flag = 1;

        for(int n = 0; n < 6 && flag; n++)
        {
            flag = 0;//resets flag

            for (int bs = 0; bs < (n - 1); bs++)
            {
                if(Guess[Line][n+1] < Guess[Line][n])     //if the next in the array is less than this one
                {
                    int temp;
                    temp = Guess[Line][n];             //swap elements using temp data storage
                    Guess[Line][n] = Guess[Line][n+1];
                    Guess[Line][n+1] = temp;
                    flag = 1;               //indicates that a swap occurred.
                }
            }
        }
    }


And the second, and I think final, functionality I absolutely, definitely NEED, is to check for and prevent duplicate numbers from appearing A) within each Line and B) From any of the bonus balls. I imagine this will be a simple loop statement but my code is so confusing now I'm not sure where to put it and how it will work, without breaking the rest of the program. I will have a go at it in the meantime, but hopefully someone will be ready to help me with it soon when it inevitably doesn't do what it looks like it should do ;P

in case it helps, I will post the random number generator, and someone can show me how to check for duplicates within that, that would be awesome. I understand that it needs to generate Ball[1], then generate Ball[2], check if it is the same as Ball[1], and if it is, then regenerate Ball[2] until it is not the same as Ball[1]. Then it needs to generate Ball[3], compare it to ball[2], if it is the same, regenerate, if not, compare it to Ball[1], and same deal, and so on in the fashion. I just don't know what type of loop I will need to do this best.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void Generate(int *Ball, int &BonusBall)
{
    cout << "Lets get those balls rolling...\n\n";
    srand ( time(NULL) );

    for(int n = 0; n < 6; n++)
    {
        do
        {
            Ball[n] = rand() % BetHigh + BetLow;
        }
        while(Ball[n] < BetLow || Ball[n] > BetHigh);

        cout << Ball[n] << "\t";
    }

    BonusBall = rand() % BetHigh + BetLow;

    cout << "And the bonus is..... " << BonusBall << endl << endl;

}



(nevermind about the deleting array thing, I think I've got it by simply making a loop asking if the user wants to reuse the same ticket, and if they don't, to delete Guess; and delete Matches; after the loop breaks, before going back up to the top to start from entering number of lines again. I love how clever I've literally gotten over night! Still need help with bubble sort and preventing duplicates from the machine though. once I figure out how to stop dupes coming out the machine, I can apply that to the numbers on each line preeeetty easily, then it's simply a case of changing BetHigh from 10 to 49, and starting the Wallet with 50 instead of 15, and my game will be fully functional! YAY!)

Thanks again everyone here, such a great community, I am a new lover of programming, I wouldn't be as good and I wouldn't enjoy it as much if it wasn't for all the help and support I've been getting from all over the place, and I am grateful for it =]
Topic archived. No new replies allowed.
Pages: 12