0

I've been writing this c++ lotto simulator and im trying to get it to display the users lotto numbers (userNums array), the winning numbers that are randomly generated and inserted into an array (pBallDrawing) and then your winnings but when i try to output the two arrays using a for loop i just get garbage values (-84792048 that kind of thing) or the last value of the array.

I believe it goes wrong around the duplicate tests for both arrays but i dont know how exactly. I've tried mixing it around but then it just displays the last inputted value.

EDIT: ok so ive narrowed down the problem to these functions. I have these functions set in a loop inside main. Thank you for the suggestions about using things like std::shuffle and shoring up my output but im in a beginners class and my professor hasn't taught use that so im pretty sure i'd get knocked off points for using 'shortcuts' like shuffle.

void userPBInput(int &num) {
    cout << "Please enter 5 unique numbers you would like to use for the lottery--> ";
    cin >> num;
}

//*************userPBInputTest********************************
//Description: tests the userNums to make sure they are destinct and within range.
//Pre: recives the userNums array and num cin value from the preveious function. 
//Post: will test the array and then pass it back to userPBInput.
//************************************************************

void userPBInputTest(int num, int userNums[BALLCNT]) {

    for (int r = 0; r < BALLCNT - 2; r++) {
        while (num<MIN || num>MAX) {
            cout << "Error. Please enter a number within 1 and 69 --> ";
            cin >> num;
        }

        while (num == userNums[r]) {
            cout << "Error. Please enter a new number that you haven't entered already--> ";
            cin >> num;
        }

        userNums[r] = num;
    }
}
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;

const int BALLCNT = 6;
const int REDBALL = 5;
const int MAX = 69;
const int MIN = 1;
const int RMAX = 26;

void userPBInput (int &num);
void userPBInputTest(int num, int userNums[BALLCNT]);
void redBall(int userNums[BALLCNT]);
void rngPBall(int drawing);
void rngPBallTest(int drawing, int ballDrawing[BALLCNT]);
void redRngPBall(int ballDrawing[BALLCNT]);

void matchCounter(int userNums[BALLCNT], int ballDrawing[BALLCNT]);
void winnings(int match, bool redMatch);



int main() {
    srand(time(NULL));
    int userNums[BALLCNT];                  //users lotto numbers
    int ballDrawing[BALLCNT];               // the winning numbers
    int num = 0;                            // secondary value to validate users numbers for range and duplicates 
    int drawing = 0;                        // same as previous but with the winning numbers (duplicate only not range)
    int match = 0;                          //will count how many white ball matches between the winning and the users numbers 
    bool redMatch = false;  //tracks if you get a match with the red lotto ball.

    for (int k = 0; k < BALLCNT - 1; k++) {         //puts the functions into loop so you can enter 5 numbers and have them tested
        userPBInput(num);
        userPBInputTest(num, userNums);
    }
    redBall(userNums);                              //allows you to enter the redball number in the 6th element of the array 
    for (int g = 0; g < BALLCNT - 1; g++) {         //loop to generate and test 5 numbers 
        rngPBall(drawing);                          //Where the user inputs their lotto numbers 
        rngPBallTest(drawing, ballDrawing);         // the teest 
    }
    redRngPBall(ballDrawing);
    matchCounter(userNums, ballDrawing);
    winnings(match, redMatch);
}

//*******************userPBInput*****************************
//Description: Will accept 5 numbers and the 6th red number from the user. 
//Pre: receives num value for comparison in
//post: will be filled with numbers as the userPBInputTest tests to make sure that they are within range and are distinct and then passed to the decideWinnings function.
//****************************************************

void userPBInput(int &num) {
    cout << "Please enter 5 unique numbers you would like to use for the lottery--> ";
    cin >> num;
}

//*************userPBInputTest********************************
//Description: tests the userNums to make sure they are destinct and within range.
//Pre: recives the userNums array and num cin value from the preveious function. 
//Post: will test the array and then pass it back to userPBInput.
//************************************************************

void userPBInputTest(int num, int userNums[BALLCNT] ){

    for (int r = 0; r < BALLCNT - 1; r++) {
        while (num<MIN || num>MAX) {
            cout << "Error. Please enter a number within 1 and 69 --> ";
            cin >> num;
        }

        while (num == userNums[r]) {
            cout << "Error. Please enter a new number that you haven't entered already--> ";
            cin >> num;
        }

            userNums[r] = num;
    }
}
//*************redBall*********************
//Description: Asks the user for what value they'd like for their red powerball
//Pre: recieves empty int redB value 
//post: will pass redB on to the winnings decision function to be compared with the
//randomly generated red ball value
//**************************************
void redBall(int userNums[BALLCNT]) {
    cout << " And what would you like for your powerball? (aka the redball)-->";
    cin >> userNums[REDBALL];

    while ( userNums[REDBALL]> MAX || userNums[REDBALL] < MIN) {
        cout << " The red ball need to be within 1 and 26. Try again--> ";
        cin >> userNums[REDBALL];
    }


}
//**********rngPBall******************************
//Description: Will generate 5 random numbers for the simulated ball drawing and one value for the redBall 
//Pre: Will recieve the array meant for the lotto drawing 
//Post: will be passed to the test function to make sure they are unique and within range and then passed to the winnings calculator 
//*************************************************
void rngPBall(int drawing) {

        drawing = MIN + rand() % MAX;                                               

}
//**********rngPBallTest********************
//Description: will test the randomly generated numbers for duplicates and make a new number if so 
//Pre: Recieves drawing value with RNG number and the winning numbers array 
//post: will pass on fully tested array to main and to the winnings calculator 
//******************************************
void rngPBallTest(int drawing, int ballDrawing[BALLCNT]) {

    for (int e = 0; e < BALLCNT - 1; e++) {                                                                 //to test the winning numbers for duplicates
        while (drawing == ballDrawing[e]) 
            drawing = MIN + rand() % MAX;




            ballDrawing[e] = drawing;                                                                       //assigns the value of drawing to its place in the ballDrawing Array

    }

}
//***********redRngPBall********************************************
// Description: to generate a winning number for the last value in the array, to represent the red ball
//Pre: recieves ballDrawing Array and fills the last element with the red ball drawing
//Post: will pass full array to winnings calculator
//******************************************************************

void redRngPBall(int ballDrawing[BALLCNT]){
    ballDrawing[REDBALL] = MIN + rand() % RMAX;                     //Generates a number for the element #6 
}
//**************matchCounter***************************************
// Description: will test each element of both arrays against eachother and track the amount of matches you have and if the 
// red number matches.  
//Pre: Recieves both users array and the randomly generated array .
//Post: will pass the match/redmatch ints to int winnings. 


void matchCounter(int userNums[BALLCNT], int ballDrawing[BALLCNT]) {
    int match = 0;                                                      //tracks how many matches you get 
    bool redMatch = false;                                              //since you either have a match or you dont, made it a bool

    for (int v = 0; v < BALLCNT - 1; v++)                               //user/winning match counting loop 
        while (userNums[v] == ballDrawing[v])                           
            match++;


    if (userNums[6] == ballDrawing[6])                                  //boolean decision. 
        redMatch = true;

}
//***************winnings********************************************
//Description: Will decide what your winnings are based on if the red powerball matches or not and how many white matches you get 
//Pre: recieves the match int and redMatch bool 
//post: will cout and return your winnings
//********************************************************************
void winnings(int match, bool redMatch) {
    int winnings = 0


        ; switch (match) {                                              //will decide what you win based on how many matches you get . 
    case 5: if (redMatch == true)
        cout << "YOUVE JUST WON THE JACKPOT";
            else 
        winnings = 1000000;
        break;
    case 4: if (redMatch == true) 
        winnings = 50000;
    else 
        winnings = 100;
        break;
    case 3: if (redMatch == true)
        winnings = 100; 
            else
        winnings = 7;
        break;
    case 2:if (redMatch == true)
        winnings = 7;
        break;
    case 1: if (redMatch == true)
        winnings = 4;
        break;
    default: winnings = 4;


    }


    cout << " You win $" << winnings<<".";                      //displays what you won.

}

I need it to be able to display the 6 numbers of both arrays, but just get garbage values apologies if this is too much code but i didn't want to leave out any context.

gvanderlee
  • 19
  • 3
  • As a very basic level of debugging, you should place debug output to examine variables at certain points. Learning how to debug is a *far* better strategy than relying on SO :-) – paxdiablo May 09 '19 at 00:51
  • 1
    This is too much code for such a simple question. When you write code, you should try to develop new functionality *in isolation* as much as possible. And when you encounter a problem, you ought to reduce it to a [minimal complete example](https://stackoverflow.com/help/mcve); that way you will probably find the bug yourself, and when you post the question we will have an easier time helping you. – Beta May 09 '19 at 00:53
  • This is a *perfect* time to use your *debugger*. And frankly, I'd start by shoring up *all* your input/output, literally none of which is being checked for read-time validation. I'd also seriously consider revamping the random-draw It doesn't have to be that complicated: 1. Take the pool of possible numbers, 2. Shuffle it using `std::shuffle`, 3. take the first five numbers from the shuffled sequence. 4. Shuffle the entire sequence *again*, and finally 5. Take the first number as your random red ball. – WhozCraig May 09 '19 at 00:54
  • Helpful reading: [What's the difference between passing by reference vs. passing by value?](https://stackoverflow.com/questions/373419/whats-the-difference-between-passing-by-reference-vs-passing-by-value). That said, in this case consider returning a value instead. – user4581301 May 09 '19 at 00:58

1 Answers1

3

You're accessing out of range on line 151

    if (userNums[6] == ballDrawing[6])                                 

BALLCNT is 6 which means that index 5 is highest numbered index that is valid

Here's the output when compiling with -fsanitize=address in clang - it tells you exactly where the problem is and what the problem is:

==27179==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffee1d64a58 at pc 0x00010de9d2ea bp 0x7ffee1d649a0 sp 0x7ffee1d64998
READ of size 4 at 0x7ffee1d64a58 thread T0
    #0 0x10de9d2e9 in matchCounter(int*, int*) deleteme.cpp:151
    #1 0x10de9c863 in main deleteme.cpp:43
    #2 0x7fff6707f014 in start (libdyld.dylib:x86_64+0x1014)

Address 0x7ffee1d64a58 is located in stack of thread T0 at offset 56 in frame
    #0 0x10de9c5ef in main deleteme.cpp:24

  This frame has 3 object(s):
    [32, 56) 'userNums' (line 26) <== Memory access at offset 56 overflows this variable
    [96, 120) 'ballDrawing' (line 27)
    [160, 164) 'num' (line 28)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow deleteme.cpp:151 in matchCounter(int*, int*)
Shadow bytes around the buggy address:
  0x1fffdc3ac8f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1fffdc3ac900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1fffdc3ac910: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1fffdc3ac920: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1fffdc3ac930: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x1fffdc3ac940: 00 00 00 00 f1 f1 f1 f1 00 00 00[f2]f2 f2 f2 f2
  0x1fffdc3ac950: 00 00 00 f2 f2 f2 f2 f2 04 f3 f3 f3 00 00 00 00
  0x1fffdc3ac960: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1fffdc3ac970: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1fffdc3ac980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1fffdc3ac990: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==27179==ABORTING
Abort trap: 6
xaxxon
  • 19,189
  • 5
  • 50
  • 80