Program works on my computer but not others?

Hello all. I'm new to C++ having come off Visual Basic, and am a bit confused. I have written a program to make a simple hangman game, and it works just fine off my computer. It reads in all the words from a text file, and then works as one would expect. However, if I move it other to my friend's server (which runs Windows Server 2008, if that's important), I continuously get:

"Unhandled exception at 0x6fc5b6c2 in hangman.exe: 0xC0000005: Access violation reading location 0xfffffffc."

Upon running it. The code is exactly the same and the file is in the same directory in both (I have not specified one, so I've been taught that the program will look for the file within the same directory it is located), so why is this?

The code is as follows:
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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
#include <iostream> //Basic input/output.
#include <string> //Needed for the "string.find()" function to search the answer for the input.
#include <cstdlib> //Needed for the "srand" function.
#include <ctime> //Needed for the "time" function, which is needed for truly random number seeding.
#include <sstream> //Used to convert the input from a 'string' to a 'char'.
#include <fstream> //Used to read the file containing the words.
using namespace std;

//Variable for the lives:
int short lives = 6; //The actual amount of lives the player has left.

//Declaring the function for outputting the hangman picture:
void output(int lives);

int main()
{
	//Variable for the loop:
	int i;
	
	//Varibables needed for the filestream in order to read the words from the input file:
	ifstream reader("words.txt");
	int numberOfWords;
	string line;
	
	//Checks to see if the file exists:
	if (! reader)
	{
		cout << "Error opening words file." << endl; //If it does not, output a message...
		return -1; //...and end the program.
	}
	
	//A loop to count how many words are in the text document:
	for (i = 0; ! reader.eof(); i++)
	{
		getline(reader, line);
		numberOfWords++;
	}
	
	//Sets the file stream back to the beginning:
	reader.clear();
	reader.seekg(0);
	
	//Variables for the word the player will try to guess:
	string words[numberOfWords + 1]; //The maximum size of the array is the number of words in the text file.
	
	//A loop to fill the array with the words in the text file:
	for (i = 0; ! reader.eof(); i++)
	{
		getline(reader, line);
		words[i] = line;
	}
	
	//Variable for the word that the player must guess:
	string currentword;
	
	//Integer for the random number:
	int random;

	//Vairables for the input:
	string input; //The string that the program reads in from the user.
	int inputSize; //An integer variable to store the size of the input.
	stringstream stream; //A string stream used to convert the string to a 'char' after it has passed the size test.
	char inputChar; //A character varibale to use the input within the rest of the program.
	
	//Variable for if the player has won:
	bool isWin;
	
	//Variable for if the player has guessed correctly:
	bool isCorrect;
	
	//Variable needed for the find function used:
	int findemp;
	
	//Seeds the random number generator with the time:
	srand((int) time (0));
	
	//Generates a random number and uses this to select a word:
	random = (rand() % numberOfWords + 1) + 1;
	currentword = words[random];
	
	//Variable for the size of the word:
	int size = currentword.size();
	
	//Variable for the answer and how close the player has got to it:
	string answer[size];
	
	//Variables for storing the player's guesses so they do not repeat any:
	string guesses[26];
	int numberOfGuesses = 1;
	
	for (i = 0; i < size; i++) //A loop to fill the answer array with underscores.
	{
		answer[i] = "_";
	}
	
	cout << "This word has " << size << " letters. Good luck :)" << endl;
	
	//The program runs within a loop so it does not end after the user has had one guess.
	while ((lives > 0) && (isWin != true)) //The loop ends when the player runs out of lives or they win.
	{
		//Used for the 'goto' statement:
		beginning:
		//Resets the boolean variable:
		isCorrect = false;
		
		//Requests and stores the user's input.
		cout << "Input: ";
		cin >> input;
		cout << endl;
		
		//Checks the size of the input.
		inputSize = input.size();
		
		if (inputSize != 1) //If the size is not 1...
		{
			cout << "Invalid input. Please enter one letter only." << endl; //Output a message...
			goto beginning; //...and return to the beginning.
		}
		
		//Loops through the 'guesses' array checking if the player has already used their input:
		for (i = 1; i < numberOfGuesses; i++)
		{
			if (guesses[i] == input)
			{
				cout << "You have already guessed this letter. Please enter a another one." << endl; //If so, output a message...
				goto beginning;//...and return to the beginning.
			}
		}
		
		//Otherwise, the player must have not used their guess, so it is stored for future use:
		guesses[numberOfGuesses] = input;
		numberOfGuesses++;
		
		//Otherwise, the input must be one character, which can be used for the program, so the program converts it to a 'character' variable.
		stream << input;
		stream >> inputChar;
		
		//Searches for the character inputted within the target word.
		for (i = 0 ; i < size ; i++)
		{
			if (currentword.at(i) == inputChar) //Loops through every letter of the string and checks if it matches the input.
			{
				answer[i] = input; //If so, fill the answer array with the inputted character at the correct space.
				isCorrect = true; //Set 'isCorrect' to true, so the player does not lose a life.
			}
		}
		
		if (isCorrect == false) //If the previous loop did not change any words, 'isCorrect' will remain false.
		{
			lives--; //And the player will lose a life.
		}
		
		for (i = 0; i < size; i++) //A loop to check if the player has won.
		{
			findemp = answer[i].find("_"); //Loops through the answer array, and if it finds a "_", the player has not won.
			if (findemp != -1)
			{
				break; //In which case, it exits the loop.
			}
			else
			{
				findemp = 1; //Otherwise, it sets the "findemp" variable to 1 for the following If statement.
			}
		}
		if (findemp == 1) 
		{
			isWin = true; //If the "findemp" variable is 1 (meaning the player has won), set isWin to true.
		}
		else
		{
			isWin = false; //Otherwise, set it to false.
		}
		
		if (isWin) //If the player has won...
		{
			cout << "You win, the word was " << currentword << "." << endl; //Output a message.
		}
		else
		{
			for (i = 0; i < size; i++)
			{
				cout << answer[i]; //Output the players current guess.
			}
			cout << endl; //New line
			if (isCorrect) //If the input is found within the word.
			{
				cout << endl << "Correct!" << endl; //Output a 'correct' message.
			}
			else
			{
				cout << endl << "Wrong!" << endl; //Otherwise, output an 'incorrect' message.
			}
			output(lives); //Output the hangman picture.
		}
	
		if (lives == 0) //If the player is out of lives (and has hence lost)...
		{
			cout << "You lose, the word was " << currentword << endl; //Output the correct word.
		}
	} //End while loop.
	//End of function.
	return 0;
}

//Defining the "output" function:
void output(int lives)
{
	cout << "-----" << endl; //Top line.
	cout << "|   |" << endl; //Left line and rope.
	
	if (lives < 6) //If lives left are 0-5...
	{
		cout << "|   O" << endl; //Output the head and the left line.
	} 
	else
	{
		cout << "|    " << endl; //Otherwise, output just the left line.
	}

	if (lives < 3) //If lives left is 0-2...
	{
		cout << "|  -|-" << endl; //Output left line and body and both arms.
	} 
	else
	if (lives < 4) //Otherwise, is lives left 0-3...
	{
		cout << "|  -| " << endl; //Output left line, body and left arm.
	}
	else
	if (lives < 5) //Otherwise, is lives left 0-4...
	{
		cout << "|   | " << endl; //Output left line and body.
	}

	if (lives < 1) //Is lives left 0...
	{
		cout << "|  / \\" << endl; //If so, output left line and both legs.
	}
	else
	if (lives < 2) //Otherwise, is lives left 0-1...
	{
		cout << "|  /  " << endl; //If so, output left line and left leg.
	}

	cout << "|    " << endl; //Output left line.
	cout << "|    " << endl; //Output left line.
	cout << "|    " << endl; //Output left line.
	cout << "-----" << endl; //Output bottom line.
	
	//End of function.
}


Also, as a side note, I keep reading that "goto"s are bad to use, but I can't think of another way to replicate what they do within this program.

Thanks.
To answer your side note:

delete beginning: on line 102. Then replace all lines of goto beginning; with continue

That's the easiest way with the minimal changes to your code.

EDIT:
The goto in line 126 is part of an embedded loop. Using a continue here will result in simply going to the next iteration of the for loop.

Do this instead of that block:
1
2
3
4
5
6
7
8
9
10
11
12
		//Loops through the 'guesses' array checking if the player has already used their input:
		bool exit = false;
		for (i = 1; i < numberOfGuesses; i++)
		{
			if (guesses[i] == input)
			{
				cout << "You have already guessed this letter. Please enter a another one." << endl; //If so, output a message...
				exit = true;
				break;//...and return to the beginning.
			}
		}
		if (exit) continue;
Last edited on
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
	int numberOfWords;
	string line;
	
	//Checks to see if the file exists:
	if (! reader)
	{
		cout << "Error opening words file." << endl; //If it does not, output a message...
		return -1; //...and end the program.
	}
	
	//A loop to count how many words are in the text document:
	for (i = 0; ! reader.eof(); i++)
	{
		getline(reader, line);
		numberOfWords++;
	}


numberOfWords is not initialized in the above code and could contain anything when you're done. Checking for eof is the wrong thing to do. What are you doing with the variable i here?



string words[numberOfWords + 1]; //The maximum size of the array is the number of words in the text file.

This is not legal C++. I would guess you're using gcc with the vla extension enabled. Consider using a std::vector. Also, the comment isn't accurate. The size of the array is the number of words in the text file +1.



81
82
83
84
85
86
87
88
	//Variable for the size of the word:
	int size = currentword.size();
	
	//Variable for the answer and how close the player has got to it:
	string answer[size];
	
	//Variables for storing the player's guesses so they do not repeat any:
	string guesses[26]; 


Again, line 85 is illegal. Do you really need an array of strings to hold the answer? Wouldn't one do? Do you really need an array of strings to hold guesses made? Aren't guesses individual chars?

Due to your buggy input code, it's quite possible for size to be 0 here.



while ((lives > 0) && (isWin != true)) //The loop ends when the player runs out of lives or they win.

isWin is not initialized when it is defined and could be anything here.



120
121
		//Loops through the 'guesses' array checking if the player has already used their input:
		for (i = 1; i < numberOfGuesses; i++)


Valid indexes for arrays are 0 to size-1. This code can potentially clobber memory you don't own.




134
135
136
137
		//Otherwise, the input must be one character, so the program converts it to a char
		stream << input;
                stream >> inputChar;
 


This won't work for successive iterations of the loop, but it's overkill anyway.

inputChar = input[0] ;

Or, just use input[0].
Last edited on
Thanks for the help, it works fine now.
Topic archived. No new replies allowed.