program crashes for unknown reasons

when option 2 is run the program crashes.

option 2 is designed to generate a set of 23 number, sort them in order from smallest to largest and check for a depulcate number only until it finds one. repeated 1000 times. then it displays the percentage of how many sets had at least one duplicate in them.

I've looked it over and over again without being able to find anything wrong with it (i am still fairly new to programming in general). can someone please help me see where i went wrong?

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include <iostream>
#include <stdlib.h>
#include <iomanip>
using namespace std;

void Menu ();
void Explain();
void Verify (int Bday[]);
void GenerateSet (int Bday[]);
void SelectionSort (int Bday[], int  Last);
void Display (int Bday[], char Months[]);
int DaysInMonth(int Mon);
inline void Swap (int &A, int &B);

const int SETS=1000;

int main()
{
	char Ch;
	int Bday [24];//={0, 12, 13, 234, 234, 34, 5, 2, 5, 22, 35, 199, 350, 1, 356, 140, 3, 4, 6, 7, 8, 9, 10, 11};
	char Months[13][11]={"nada", "January", "Febuary", "March", "April", "May", "June", "July",
						"August", "September", "October", "November", "December"};
	srand(time(NULL));

	do
	{
		Menu();
		cin.get(Ch);
		switch (Ch)
		{
			case '1': Explain();
					break;
			case '2': Verify(Bday);
					break;
			case '3': Display(Bday, *Months);
					break;
			case 'E':
			case 'e': break;
			default: cout<<"Invalid input, please enter again."<<endl;
		}
	}
		while (Ch!='E'||Ch!='e');
	return 0;
}

void Menu()
{
	cout<<"\n1) Explain birthday paradox."<<endl;
	cout<<"2) Verify Birthday paradox by generating 1000 sets of birthdays."<<endl;
	cout<<"3) Display Results of one set of 23 birthdays."<<endl;
	cout<<"E) exit."<<endl;
}

void Explain ()
{
	cout<<"If 23 persons are chosen at random, chances are more than 50%"<<endl;
	cout<<"that two of them will have the same birthday."<<endl<<endl;
	cin.ignore(100, '\n');
}

void Verify (int Bday[])
{
	int Match=0, i, Temp;
	
	cout<<"Generating 1000 sets of 23 birthdays and checking for matches..."<<endl;
	for(int k=1;k<=SETS;++k)
	{
		GenerateSet(Bday);
		SelectionSort(Bday, 23);
		Temp=Match;
		i=1;
		while (Match<=Temp&&i!=23)
		{
			if (Bday[i]==Bday[i+1])
				++Match;
			++i;
		}	
	}
	cout<<"Results: "<<Match<<" out of 1000 ("<<(float(Match)/SETS)*100<<"%) sets of birthdays had at least one match."<<endl;
	cin.ignore(100, '\n');
}


void GenerateSet (int Bday[])
{
	for(int i=1;i<=23;++i)
		Bday[i]=1+rand()%365;
}

void SelectionSort (int Bday[], int  Last)
{
  int i, Start, SubSmall;

  for ( Start = 1; Start < Last; ++Start )   // Sort items 1..Last
    {
    SubSmall = Start;                        //  subscript of smallest elt.

    for ( i = Start + 1; i <= Last; i++ )    //  Find subscript of smallest
      if ( Bday[i] < Bday[SubSmall] )        //   elt. in tail end of array
        SubSmall= i;

    Swap(Bday[SubSmall],  Bday[Start]);      // Place in correct position
    }
}

inline void Swap (int &A, int &B)
{
  int Temp= A;
  A = B;
  B = Temp;
}

void Display (int Bday[], char Months[])
{
	int Month, Line=0, Repeat;

	cout<<"Here are the results of generating a set of 23 birthdays:"<<endl;
	cout<<"==========================================================="<<endl;
	GenerateSet(Bday);
	SelectionSort(Bday, 23);
	for (int i=1;i<=23;++i)
	{
		Month=1;
		Repeat=1;
		if (i==23)                   //Stops unindexed references
			break;
		else if (Bday[i]==Bday[i+1])  //this checks for repeated birthdays
			++Repeat;
		while (Bday[i]>DaysInMonth(Month)) //this loop turns the day of year number into
		{                                  //day of month, and sets the month.
			Bday[i]-=DaysInMonth(Month);
			++Month;
		}
		if (Repeat>1)
			cout<<"("<<Repeat<<") ";		// this makes the repeat show,
		else                                //if there is a repeat.
			cout<<"    ";
		cout<<Months[1]<<"   "<<setw(2)<<Bday[i]<<"    ";
		++Line;                              //this varriable is for formatting,
		if (Line%3==0)                       //every thrid print adds a \n
			cout<<endl;
	}
	cin.ignore(100, '\n');
	cout<<Months[1]<<endl<<Months[2]<<endl<<Months[3];;

}

int DaysInMonth(int Mon)
{
	switch (Mon)
	{
		case 2: return 28;
		case 4:
		case 6:
		case 9:
		case 11: return 30;
		default: return 31;
	}
}
Last edited on
Your problem is between the line 71-77. You're basically acessing invalid index's.


The variable "i" will assume bigger values than the size of "Bday", and if there is no match, it will increase forever, since your "while" condition is "Match<=Temp" and both are equal to 0.
Last edited on
ok, unfortunately i dont know what you mean by invalid index's, could you explain please?

ahh, i think i see now, so i need to put in an escape for the instance of there not being a match, which is statically going to happen every other time GenerateSet is called. thank you very much for your help.
would putting an if statement like so at the end of the while loop work?
1
2
3
4
5
6
7
8
while (Match<=Temp)
{
	if (Bday[i]==Bday[i+1])
		++Match;
	++i;
	if (i==23)
		break;
}
Last edited on
Here is example.

1
2
int array[20]{0};
array[21] = 1;



I'm accessing an index that doesn't exist, which is 21.


-----

This "while" loop is quite useless. At the current state, both variables are equal to 0, and when "Match" increases by one, it will stop. By the way, why are you starting your array by the index 1 at the "generateset"?
Last edited on
ok, so the crash is happening when it attempts to compare Bday[23] to Bday[24], which is unindexed?

the sorting function provided by my professor ignores the array[0] position, and actually i added an "||i==22" to the while loop and the crashing stopped. new problems have arisen though, for instance Match is getting increased every time for some reason.

I want the while loop to stop as soon as match is increased, what's why i used a while loop instead of a for loop.

I finally saw a blaring error in generateset now as well, the for loop was ...;Bday[i]<=23;... should just be i<=23.
Last edited on
Your problem is not just on lines 71-77, but you have the same problem everywhere you use a for loop. You are attempting to access memory that doesn't belong to the array.

Keep in mind that the first element of an array is located at index position zero.

For example:

1
2
3
4
5
6
int array[4];

array[0] = 123;//first element
array[1] = 234;
array[2] = 345;
array[3] = 456;//last element 
Last edited on
i'm aware that the 0 position is the first, i have been intentionally skipping or leaving it blank because my the sorting function my professor provided needs the array to be that way.

I have since fixed the loops that were causing the issue, but now new issues are coming up, for instance match is increasing every time when it should only be increasing about 50% of the time.
--------
i figured my new problem out, i had forgotten to reinitialize i every time i started a new set of numbers, fixing that also seemed to fix the crashes.

the only problem I'm having now is calling the 2D array.
this is the way i tried to set it up:
Months
- 0 1 2 3 4 5 6 7 8 9 10 11
0 n a d a \n
1 J a n u a r y \n
2 F e b u a r y \n
3 M a r c h \n
etc.
the was i was taught, calling cout<<Months[1] would display "January" instead i'm getting 8 spaces then "Jan"
Last edited on
I've translated your problem into c++. Why? I'm bored and it is more readable. Anyway, Look at what i've done at the function "Display"(line 68). This way is more simple and easy to understand.




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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <iostream>
#include <string>
#include <random>
#include <algorithm>



#define SETS 1000




const short endmonth[13] = {1,31,59,90,120,151,181,212,243,273,304,334,365};
const std::string months[12]={"January", "Febuary", "March", "April", "May", "June", "July",
                           "August", "September", "October", "November", "December"};

class BdayProblem
{
public:
    void Menu()
    {
        std::cout <<"\n1) Explain birthday paradox." << std::endl;
        std::cout <<"2) Verify Birthday paradox by generating 1000 sets of birthdays." << std::endl;
        std::cout <<"3) Display Results of one set of 23 birthdays." << std::endl;
        std::cout <<"E) exit." << std::endl;
    }

    void Explain()
    {
        std::cout <<"If 23 persons are chosen at random, chances are more than 50%" << std::endl;
        std::cout <<"that two of them will have the same birthday." << std::endl;
    }
    void Set(int *persons,std::size_t size);
    void Verify(int *persons,std::size_t size);
    void Display(int *persons,std::size_t size);


};
void BdayProblem::Set(int *persons, std::size_t size)
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(1, 365);

    for(std::size_t i = 0; i < size; ++i)
    {
        persons[i] = dis(gen);
    }
    std::sort(persons,persons + size,[](int i, int j){return i < j;});
}
void BdayProblem::Verify(int *persons,std::size_t size)
{
    int match = 0;

    for(int i = 0; i < SETS; ++i)
    {
        this->Set(persons,size);

        for(std::size_t k = 0; k < size - 1; ++k)
        {
            if (persons[k] == persons[k+1])
                ++match;
        }
    }
    std::cout<<"Results: "<< match<<" out of 1000 ("<<(double(match)/SETS)*100<<"%) sets of birthdays had at least one match."<<std::endl;
}

void BdayProblem::Display(int *persons, std::size_t size)
{

    this->Set(persons,size);
    for(std::size_t k = 0; k < size; ++k)
    {
        for(int i = 0; i < 12; ++i)
        {
            if(persons[k] >= endmonth[i] && persons[k] <= endmonth[i + 1])
            {
                std::cout << "Person[" << k + 1 << "]" << " was born on " << months[i] << " " << endmonth[i + 1] - persons[k]  << std::endl;
                break;
            }
        }
    }
}



int main()
{
    char ch = 0;
    int Person_Day[24]{0};

    BdayProblem p;


    do
    {
        p.Menu();
        std::cin.get(ch);
        switch(ch)
        {
        case '1': p.Explain();
            break;
        case '2': p.Verify(Person_Day,sizeof(Person_Day)/sizeof(Person_Day[0]));
            break;
        case '3': p.Display(Person_Day,sizeof(Person_Day)/sizeof(Person_Day[0]));
            break;
        case 'E':
        {
            std::locale loc;
            std::tolower(ch,loc);
            break;
        }
        case 'e':
            break;
        default:
            std::cout << "Invalid input, please enter again." << std::endl;
        }
       
        std::cin.clear();
        std::cin.ignore(999999,'\n');
    }
    while(ch != 'e');
    std::cout << "end" << std::endl;
    return 0;
}

Last edited on
> I've translated your problem into c++.
the original code was valid c++

> BdayProblem p;
useless stateless object

> std::sort(persons,persons + size,[](int i, int j){return i < j;});
http://www.cplusplus.com/reference/algorithm/sort/
`The elements are compared using operator< '


1
2
3
4
void BdayProblem::Display(int *persons, std::size_t size)
{

    this->Set(persons,size); //¿what is this doing here? 



> std::cout <<"If 23 persons are chosen at random, chances are more than 50%" << std::endl;
> int Person_Day[24]{0};
¿which one?
Topic archived. No new replies allowed.