Intermittent Error in Function


I've spent the last 6 hours trying to trace down the problem here, with no luck. This is for an "Intro to C++" class. The function randomly selects a quote from a Godfather movie, and asks the user to identify the character that used the quote. There is then an option to continue playing, and if the user chooses to continue, a second question is asked.

This is where the problem occurs. The second question sometimes appears completely blank. The cout text is there ["Who said: 1) 2) 3)"], but the quote and the three options for the answer are not there. Both the first and second questions pull the quote and the options for the answer from the same file, so the files containing the quotes are not the problem. Something is going wrong when the second question is asked.

I know some may feel that some parts (such as variable array initialization) could have been more efficient, but the professor is very specific about how she wants things done. Also, I have tried removing the cin.ignore, but that didn't change anything. I identified the suspected problem area with bold type comments.

Thank you
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217

bool GetQuote(int &userScore) 
{ 
	// declare and initialize variables    
	int myr = 0, myt = 0, answerQuit = 0, answerA = 0, answerB = 0, randFile = 0, randSize = 0;   
	bool correctA = 0, correctB = 0; 

	// Pseudo RNG seems to favor lower numbers. Creating two quote files, with quotes from near the bottom of the first file, placed near the top of the second file. 
	// This will increase the randomness of quotes, and lessen the chance of repeating the top few quotes every time the game is played.   
	// Seed RNG, get random number  (for selection of quote file 1 or quote file 2) 
	srand(time(NULL));  	
	randFile = rand() % 2 + 1; // (1 - 2)		

	// seed RNG, get random number (for selection of line number in quote file) 
	srand(time(NULL));  	
	randSize = rand() % 25 + 1;	// (1 - 25) (if randSize = 0, loop fails, function reports initialized values of "" (nothing)  	

	// declare fstream variable and open file for reading 
	ifstream infile; 
	if (randFile == 1) 
		infile.open("quotes1.txt"); 
	else 
		infile.open("quotes2.txt");  

	// declare and initialize parallel array for selecting line in quote file  
	// To save memory and cpu time, I was only initializing to randSize, instead of always initializing to max number of lines (25) 
	// However, that approach was creating random program crashes. 
	string quoteArr [25], correctArr [25], option1Arr [25], option2Arr [25], option3Arr [25]; 
	for (int q = 0; q < 25; q++)
	{
		quoteArr[q] = "";  
		correctArr[q] = ""; 
		option1Arr[q] = "";
		option2Arr[q] = "";
		option3Arr[q] = ""; 
	}

	// select a random line containing quote, correctA answerA, and three possible answers, from text file.  
 	// semicolon is being used as deliminator 
	for (int r = 0; r < randSize; r++)  
	{

		getline(infile, quoteArr[r], ';');  
		getline(infile, correctArr[r], ';');
		getline(infile, option1Arr[r], ';');
		getline(infile, option2Arr[r], ';');
		getline(infile, option3Arr[r], ';'); 
		myr = r; 
	} 
	
	cout << "Beginning Level 2. You will have to correctly answer a trivia question from" << endl; 
	cout << "The Godfather movies." << endl << endl;    

	
	// Prompt random question and input answer  
	cout << "WHO SAID: \n\n" << quoteArr[myr] << endl << endl; 
	cout << "1) " << option1Arr[myr] << endl; 
	cout << "2) " << option2Arr[myr] << endl; 
	cout << "3) " << option3Arr[myr] << endl << endl;    
	do
	{
		cout << "Select 1, 2, or 3: "; 
		cin >> answerA; 
			if (answerA < 1 || answerA > 3) 
				cout << "Input error. Please choose 1, 2, or 3." << endl << endl;   
		cout << endl; 
	} 
	while (answerA < 1 || answerA > 3);  

	// Check to see if answer is correct 
	if (answerA == 1) 
		if (option1Arr [myr] == correctArr [myr]) 
		correctA = 1;
	else 
		correctA = 0;  		
	
	if (answerA == 2) 
		if (option2Arr [myr] == correctArr [myr]) 
		correctA = 1;
	else 
		correctA = 0;  		
	
	if (answerA == 3) 
		if (option3Arr [myr] == correctArr [myr]) 
		correctA = 1;
	else 
		correctA = 0;  		

	//Update score 
	if (correctA == 1) 
	{
		cout << "CORRECT !!  YOU'VE EARNED 100 BONUS POINTS." << endl << endl; 
		userScore += 100; 
		cout << "Your score is now " << userScore << endl << endl; 
	}
	else 
  	{ 
		cout << "INCORRECT !!  YOU'VE LOST 100 POINTS." << endl; 
		userScore -= 100; 
		cout << "Your score is now " << userScore << endl << endl; 
	}
	
	// If player dies, end game.    
	if (userScore <= 0) 
		return 0; 
//Problem starts somewhere after this point
	// If player is still alive, offer a shot at double or nothing
	cout << "You can be weak, like Johnny Fontane, and quit now; or be strong, like" << endl; 
	cout << "Lucca Brazzi, and play for double or nothing. What would you like to do?" << endl << endl; 
	do 
	{
		cout << "1) Quit now. " << endl; 
		cout << "2) Play one more round for double or nothing. " << endl; 
		cin >> answerQuit;     
		cout << endl; 
		if (answerQuit < 1 || answerQuit > 2) 
			cout << "Input error. You must select 1 or 2." << endl << endl; 	

	} 
	while (answerQuit < 1 || answerQuit > 2);  

	// if player quits: 
	if (answerQuit == 1)
		{
		cout << "QUITTER !! Your score is now " << userScore << "If you had continued, your score" << endl; 
		cout << "could have been " << userScore * 2 << "." << endl << endl;    
		return 1; 
		} 	
	
	// if player plays double or nothing: 
	// Selecting a random line in quotes file could ask user the same question as last time. Select the next question in quotes file. 
	randSize += 1; 	
	// if already on the last line in quotes file, ask quesiton in the first line. 
	if (randSize == 26)
		randSize = 1;  
	
	// initialize array for double or nothing question 
	string quoteArr1 [25], correctArr1 [25], option1Arr1 [25], option2Arr1 [25], option3Arr1 [25]; 
	for (int s = 0; s < 25; s++)
	{
		quoteArr1[s] = "";  
		correctArr1[s] = ""; 
		option1Arr1[s] = "";
		option2Arr1[s] = "";
		option3Arr1[s] = ""; 
	}

	// remove cin endline from keyboard buffer
	cin.ignore(); 	
	// get double or nothing question 
	for (int t = 0; t < randSize; t++)  
	{
		getline(infile, quoteArr1[t], ';');  
		getline(infile, correctArr1[t], ';');
		getline(infile, option1Arr1[t], ';');
		getline(infile, option2Arr1[t], ';');
		getline(infile, option3Arr1[t], ';'); 
		myt = t; 
	} 

//This is the part where the cout text appears but the variables (quoteArr1[myt], option1Arr1[myt], option2Arr1[myt], option3Arr1[myt]) sometimes do not appear).
     	
	// Prompt next question and input answer  
	cout << "Who said: \n\n" << quoteArr1[myt] << endl << endl; 
	cout << "1) " << option1Arr1[myt] << endl; 
	cout << "2) " << option2Arr1[myt] << endl; 
	cout << "3) " << option3Arr1[myt] << endl << endl;    
	do
	{
		cout << "Select 1, 2, or 3: "; 
		cin >> answerB; 
			if (answerB < 1 || answerB > 3) 
				cout << "Input error. Please choose 1, 2, or 3." << endl << endl;   
		cout << endl; 
	} 
	while (answerB < 1 || answerB > 3);  

	// Check to see if answer is correct 
	if (answerB == 1) 
		if (option1Arr1 [myt] == correctArr1 [myt]) 
		correctB = 1;
	else 
		correctB = 0;  		
	
	if (answerB == 2) 
		if (option2Arr1 [myt] == correctArr1 [myt]) 
		correctB = 1;
	else 
		correctB = 0;  		
	
	if (answerB == 3) 
		if (option3Arr1 [myt] == correctArr1 [myt]) 
		correctB = 1;
	else 
		correctB = 0;  		

	// Update score  
	if (correctB == 1) 
	{
		cout << "CORRECT !!  YOU'VE DOUBLED YOUR POINTS !! " << endl << endl; 
		userScore *= 2; 
		cout << "Your score is now " << userScore << endl << endl; 
		return 1; 
	}
	else 
  	{ 
		cout << "INCORRECT !! " << endl; 
		userScore = 0; 
		cout << "Your score is now 0" << endl << endl;
		return 0;  
	}

	// Close quotes file 
	infile.close(); 
} 		



I know, a lot of reading, thanks again.
Last edited on
At first glance, I'd suspect that somehow your array index is out of bounds. Kind of hard to say, since I can't debug it here.

And, just as an FYI, you'll do yourself (and others) a favor by keeping your code "narrower." People shouldn't need to scroll left to right to read a line. I keep mine narrow enough to print on a letter-sized page without wrapping. That's a bit extreme, but your code would be more readable if you brought it in a bit.
And, just as an FYI, you'll do yourself (and others) a favor by keeping your code "narrower."


mzimmers, I hadn't even thought of that, thank you for pointing it out.

I think I have it resolved. I've been looking at the array for hours and hours, and I tried many variations on the cin.ignore() as well. When I walked away from it for about an hour, it occurred to me that if the first for loop is placing the cursor near the end of the quotes file, the second for loop may be pushing it beyond the end. I'm now opening infile1, using infile1 on the first for loop, closing infile1, and then using infile2 on the second for loop.

The reason the problem was intermittent: If the random number in the first for loop, and the random number in the second for loop add up to less than 25 (the number of lines in the quotes file) the problem won't occur. So you had the right idea when you mentioned the array being out of bounds.

On the issue of debugging, what do you use? dev-cpp kept crashing on me when the problem came up. When it did work, it was reporting different variable results than the executable was showing. I have VS 6, but I can't follow it when it starts diving into the header files (dev-cpp doesn't do that).

Thanks very much for your input.
Good to hear you may have the problem resolved.

For debugging, I use gdb (gnu debugger), but I run it through the Qt IDE. Over the last year, I've become a big fan of Qt, even though I don't make heavy use of their graphics library. I recommend you check it out. Their help forums are also fantastic, though discussion is generally contained to Qt issues (no general C++ forum).
Yes, the problem is fixed, it was the array intermittently getting pushed out of bounds by the second for loop. So now I'm closing infile1 and opening infile2 to run the second for loop. That way, the arrays BOTH start at the beginning of the file, and don't get pushed out of bounds. It's working fine. :)

I'll check out gdb and Qt IDE, thank you. Can I just Google, or is there a special link I should check out?

Thanks again.
Here's a link to the main site:

http://qt.nokia.com/

Qt is owned and maintained by Nokia. Their graphics library contains a lot of support for mobile devices, but is entirely appropriate for desktop applications as well. Learning the graphics stuff can take some time (I'd like to take a class in it someday), but Creator (their IDE) is quite simple to understand and use, and again, their forums provide excellent support.

If you're just beginning in your programming career, knowing Qt will likely open some doors for you, too. Have fun with it.

I'm looking forward to trying it, thanks.
Topic archived. No new replies allowed.