Sign in to follow this  

Local function error

This topic is 4689 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to do an exercise from the book I’m reading. It involves writing a function to get the player's guess and see if it's the secret word or not. I can't seem to get my function to work properly though. I've tried several ways but none have worked. :( Here's the error I get: error C2601: 'playersGuess' : local function definitions are illegal
// Hangman
// The classic game of hangman

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cctype>

using namespace std;

char playersGuess(char guess);

int main()
{
	const int MAX_WRONG = 8;	// maximum number of incorrect guesses allowed

	vector<string> words;	// collection of possile words to guess
	words.push_back("GUESS");
	words.push_back("HANGMAN");
	words.push_back("DIFFICULT");

	srand(time(0));
	random_shuffle(words.begin(), words.end());
	const string THE_WORD = words[0];	// word to guess
	int wrong = 0;	// number of incorrect guesses
	string soFar(THE_WORD.size(), '-');	// word guessed so far
	string used = "";	// letters already guessed

	cout << "Welcome to Hangman, Good luck!\n";

	// main loop
	while ((wrong < MAX_WRONG) && (soFar != THE_WORD))
	{
		cout << "\n\nYou have " << (MAX_WRONG - wrong) << " incorrect guesses left.\n";
		cout << "\nYou have used the following letters:\n" << used << endl;
		cout << "So far, the word is:\n" << soFar << endl;
		
		char guess;
		used +=guess;

		if (THE_WORD.find(guess) != string::npos)
		{
			cout << "That's right! " << guess << " is in the word.\n";

			// update soFar to include newly guessed letter
			for (int i = 0; i < THE_WORD.length(); ++i)
			{
				if (THE_WORD[i] == guess)
				{
					soFar[i] = guess;
		}
		else
		{
			cout << "Sorry, " << guess << " isn't in the word.\n";
			++wrong;
		}
	}

	// shut down
	if (wrong == MAX_WRONG)
		cout << "\nYou have been hanged!";
	else
		cout << "\nYou guessed it!";

	cout << "\nThe word was " << THE_WORD << endl;

	cin.get();
	return 0;
}

char playersGuess(char guess)
{
		cout << "\n\nEnter your guess: ";
		cin >> guess;
		cin.ignore();
		guess = toupper(guess);	// make uppercase since secret word is in uppercase
		while (used.find(guess) != string::npos)
		{
			cout << "\nYou've already guessed " << guess << endl;
			cout << "Enter your guess: ";
			cin >> guess;
			cin.ignore();
			guess = toupper(guess);
		}
		
		return(guess);
}



Share this post


Link to post
Share on other sites
I commented what I changed

// Hangman
// The classic game of hangman

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cctype>

using namespace std;

string used = "";//made this global
char playersGuess(char guess);

int main()
{
const int MAX_WRONG = 8; // maximum number of incorrect guesses allowed

vector<string> words; // collection of possile words to guess
words.push_back("GUESS");
words.push_back("HANGMAN");
words.push_back("DIFFICULT");

srand(time(0));
random_shuffle(words.begin(), words.end());
const string THE_WORD = words[0]; // word to guess
int wrong = 0; // number of incorrect guesses
string soFar(THE_WORD.size(), '-'); // word guessed so far
// letters already guessed

cout << "Welcome to Hangman, Good luck!\n";

// main loop
while ((wrong < MAX_WRONG) && (soFar != THE_WORD))
{
cout << "\n\nYou have " << (MAX_WRONG - wrong) << " incorrect guesses left.\n";
cout << "\nYou have used the following letters:\n" << used << endl;
cout << "So far, the word is:\n" << soFar << endl;

char guess;
used +=guess;

if (THE_WORD.find(guess) != string::npos)
{
cout << "That's right! " << guess << " is in the word.\n";

// update soFar to include newly guessed letter
for (int i = 0; i < THE_WORD.length(); ++i)
{
if (THE_WORD[i] == guess)
{
soFar[i] = guess;
}
else
{
cout << "Sorry, " << guess << " isn't in the word.\n";
++wrong;
}
}

// shut down
if (wrong == MAX_WRONG)
cout << "\nYou have been hanged!";
else
cout << "\nYou guessed it!";

cout << "\nThe word was " << THE_WORD << endl;

cin.get();
return 0;
}
}
}//added this
char playersGuess(char guess)
{
cout << "\n\nEnter your guess: ";
cin >> guess;
cin.ignore();
guess = toupper(guess); // make uppercase since secret word is in uppercase
while (used.find(guess) != string::npos)
{
cout << "\nYou've already guessed " << guess << endl;
cout << "Enter your guess: ";
cin >> guess;
cin.ignore();
guess = toupper(guess);
}

return guess;
}

Share this post


Link to post
Share on other sites
You're missing a closing curly brace somwhere in main() (I haven't checked where exactly yet, I'll update this post when I do), so the compiler thinks you are defining the playerGuess() function within the main() function. And local functions are illegal in C++.

edit:


if (THE_WORD.find(guess) != string::npos)
{
cout << "That's right! " << guess << " is in the word.\n";

// update soFar to include newly guessed letter
for (int i = 0; i < THE_WORD.length(); ++i)
{
if (THE_WORD[i] == guess)
{
soFar[i] = guess;
// <-------------- MISSING CURLY HERE?
// <------------------- AND HERE?
}



Looks like the problem is right there: two missing curlies.

Share this post


Link to post
Share on other sites
You didn't close your "for" bracket
// update soFar to include newly guessed letter
for (int i = 0; i < THE_WORD.length(); ++i)
{


So, with } missing, the compiler see the definition of playersGuess as been within int main(), and thus tell you that this is illegal.


edit: Damn, you guys are too fast.
I might add that, despite the fact that hothead's solution will make your code compile, it will probably not act as you wanted it to, but Fruny correctly showed where you should add a closing bracket.

Share this post


Link to post
Share on other sites
*bangs head on desk repeatedly
It's always the small things!

Thanks for the help guys. This presented another problem though. It keeps saying 'used' is not defined.

But it is defined:
string used = ""; // letters already guessed

Is it because the function prototype is before the definition of 'used'?
I know that's a stupid question probably...

Share this post


Link to post
Share on other sites
"used" is declared within main() scope, thus it will only be accessible within main(). Declare the variable globally if you want to be able to access it from a different scope (The scope of the function playersGuess in this case).

Or you could also pass the variable "used" as a parameter to playersGuess.. It depends on what you think would suit the best for this situation.


Here is a good lesson on scopes if you are interested:
http://cplus.about.com/od/beginnerctutorial/l/aa101902a.htm

Share this post


Link to post
Share on other sites
Yep. You presumably want to pass 'used' to playersGuess(), since you're making use of it there. (Passing 'guess' isn't really any good; you don't read from that input variable there, so all that accomplishes is making such a variable available in that function. It should have its own 'guess' instead.) Oh, and you might also want to, you know, call playersGuess() :)

Fixing that, putting in the missing curlies, and fixing up a couple other stylistic things, yields:


// Hangman
// The classic game of hangman

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cctype>

using namespace std;

char playersGuess(string& used);
// I'm giving it the same name in the function as it has in main(). You don't
// need to do that, of course, but it's as good of a name as that string is
// ever likely to have :s

// There is nothing wrong with your indentation style, but I am changing it to
// mine anyway. ;P

int main() {
const int MAX_WRONG = 8; // maximum number of incorrect guesses allowed

vector<string> words; // collection of possile words to guess
// Later we will want to read these in from a file.
words.push_back("GUESS");
words.push_back("HANGMAN");
words.push_back("DIFFICULT");

srand(time(0));
// This is ok, but so far we're shuffling the entire array when we're only
// going to want to select one word; that's a bit wasteful... (silly concern
// with 3 elements though ;) )
random_shuffle(words.begin(), words.end());
// If you feel the need to comment variable declarations with the variable
// purposes, you're either a bit too insecure about the whole thing, or you
// should reconsider the names :)
const string wordToGuess = words[0];
int remainingGuesses = MAX_WRONG; // simplified the logic a bit ;)
string wordAsDisplayed(wordToGuess.size(), '-');
string used = ""; // letters already guessed

cout << "Welcome to Hangman, Good luck!\n";

// main loop
while ((remainingGuesses > 0) && (wordAsDisplayed != wordToGuess)) {
cout << "\n\nYou have " << remainingGuesses << " incorrect guesses left.\n"
<< "\nYou have used the following letters:\n" << used
<< "\nSo far, the word is:\n" << soFar << endl;

char guess = playersGuess(used);
// You don't really need a .find() here; since you're writing code to
// iterate manually already, you could add checking logic to the loop
// instead. That's really just an optimization though.
if (wordToGuess.find(guess) != string::npos) {
cout << "That's right! " << guess << " is in the word.\n";
// update display to indicate where the guess appears in the word.
for (int i = 0; i < wordToGuess.length(); ++i) {
if (wordToGuess[i] == guess) {
wordAsDisplayed[i] = guess;
}
}
} else {
cout << "Sorry, " << guess << " isn't in the word.\n";
--remainingGuesses;
}
}

// It's a bit silly to output the word if it was guessed :)
if (remainingGuesses == 0) {
cout << "\nYou have been hanged!\nThe word was " << wordToGuess << endl;
} else {
cout << "\nYou guessed it!" << endl;
}
// I would leave these out, but it's quite debatable if that's a good idea
cin.get();
return 0;
}

char playersGuess(string& used) {
char guess = 'a';
// We use a do-while loop to avoid repetition. However, we need to make sure
// that we don't write "You've already guessed" the first time through.
// Structuring this to avoid the duplication is often tricky, but I've found
// a clever way here: initialize to a *lowercase* letter, since that can't be
// input.
do {
// TODO: add checking for non-letter characters.
if (guess != 'a') cout << "\nYou've already guessed " << guess << endl;
cout << "\nEnter your guess: " << flush;
// "flush" to make sure it appears before we ask for input.
cin >> guess;
cin.ignore();
guess = toupper(guess);
} while (used.find(guess) != string::npos);
// Since valid guesses always get added to the 'used' string, I'm going to
// add it here. Technically we don't need a return value; main() could just
// look at the end of the used vector - but I guess an explicit return is
// clearer.
used += guess;
return guess;
}

Share this post


Link to post
Share on other sites

This topic is 4689 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this