Replacing letters in a do-while loop

I need help with a fairly simple C++ program I'm working on (hangman). I'm using two different cases; the first case is where the word is defined by the person running the program and the second case is where the word is guessed.

In the second case, there's just something that goes wrong in the do-while loop where the word is guessed. It doesn't replace the question marks with any correctly guessed letters, and it's impossible to guess the right word. I can't figure out what's wrong. Help would be much appreciated!

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
#include <iostream>
#include <string>

using namespace std;


	int main()
	{

		string word = "MONKEY";
		string secretword;
		char guess;
		int b;
                b = word.length();
		for (int w = 0;w < b;w++)
		{
			secretword.push_back('?');
		}
		do{
		cout << "Word: " << secretword << endl << endl;
		cout << "Guess a letter! " << endl << endl;  
		cin >> guess;
		for(int i = 0; i++; i < b)
		{
			if (guess == word[i]) 
			{
				secretword[i] = guess;
			}
		}
		system("cls");
		}
		while(secretword != word);  
		cout << "Congratulations! You have correctly guessed the word " << secretword <<"! " << endl << endl;
		system("pause");
		system("cls");
		}




In the code attached, I only included the second case, and I already defined the word (MONKEY) for simplicity. I didn't bother to limit the amount of guesses until I get the other things working.

Note: We haven't studied functions yet, so I'm not supposed to use those. But if that's the only way to solve the problem, then that's fine as it's a pretty important assignment.
I just took 10 minutes to figure this out. Even copied your code to my IDE to run it.

I'm not going to give you the answer, but you only need to change something around to make it work.
Have a look at your loops (:
Just a suggestion:

For lines 13 to 18, you can simply replace all these lines on 11 with a constructor:
std::string secretword(word.length(), '?');
That will construct the same string as lines 13 to 18.
Lynx876:
Thank you for taking the time to look at it. I figured the error would have to do with the loop, but I don't know what's wrong to be honest. Could you give me a clue about what's wrong with the program?

wolfgang:
Thanks for the tip! Although, I will need to keep the 'b' integer as that's used in the loop.
Hint: Your problem is on this line specifically:

for(int i = 0; i++; i < b)
I had this written down, but sommeone called my phone and I never posted it:

You don't actually need the 'b' variable. You can do the following:
for ( int w = 0; w < word.size(); w++ )

And for loops work like this:
1
2
for( initialization;  condition;          statement )
for( int i = 0;      i < word.size();    ++i )


You haven't done this!
Last edited on
ReedTompkins:
Thank you, I figured it out! I actually had no idea that the i<b had to be put before the i++. Well, it does make sense.

I hate it when your program doesn't work because of something so simple. Thank you again, and to the others who tried to help. :)

Lynx876:
I figured it out just before you posted. Thanks for the tip.
Last edited on
Yeah, I was about to post about 3 minutes after you had posted, but I got a phone call, ahaha
Okay guys, I have another problem. I've done a lot more work on other parts and the program is basically done, there's just one thing I can't get working. Storing incorrect guesses. I'll only be posting the important part of the code, once again.

All of this is part of a larger for-loop that runs up to the maximum amount of attempts (a). The 'a' integer is the number of attempts, the maximum limit is 13. So please disregard that it isn't declared in the code below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
string test;
string characters;
test.clear();

cout << "Failed characters: " << characters;

for(int i = 0; i++; i < word.length())
		{
			if (guess == word[i]) 
			{
				secretword[i] = guess[0];
                                test=1;
			}
		}
if(test.length() != 0)
{
a = a-1;
}

else
{
characters[a] = guess[0];
}


The first if statement after the for-loop is something I use so that the displayed number of remaining attempts (I did not attach that part of the code) doesn't change if the user guessed correctly. That part actually works perfectly.

This makes it difficult for me to understand why the else statement causes a "string subscript out of range" error. Does anyone know why?

I hope the fact that I didn't include the rest of the code doesn't make it difficult to understand. I've written 200 lines so I figured that would be too much. If you want me to clarify anything, then just ask.


EDIT: I've tried several different ideas, and I always get the subscript out of range error.
Last edited on
1
2
3
string characters; //Characters declared as a single string. 

characters[a] /*But then used as an array of strings?*/ = guess[0];


That is your problem.
Mats:

I think I might be misunderstanding how strings are used, I still can't get it to work. If I do this:

1
2
3
4
5
string characters; 

cout << characters;

characters[0][a] = guess[0];

It says int a "must have pointer-to-object type".

If I do this:
1
2
3
4
5
string characters[1]; 

cout << characters[0];

characters[0][a] = guess[0];

it goes out of range again.
It would help to see the code. Why are you trying to put the [a] after characters? Btw, the problem here is:
1
2
3
4
5
string characters[1]; //One dimensional array

cout << characters[0];

characters[0][a] //Two dimensional array 
I'm putting the [a] after characters so that each character will be saved in different parts of the string, in the order they are guessed. It was the only way I could think of to get that working. If you know of a better way, I would be more than willing to use a different method. :)

I just made both of them two dimensional.

1
2
3
4
5
string characters[1][13];

cout << characters[0]

characters[0][a] = guess[0]


I no longer get the out of range error. But it's not working the way it's supposed to, still. When I enter an incorrect letter, the printed string looks something like "0023F998", for example, rather than printing the incorrect letter.
This code does what you want to do. Take a look at it and apply it to your situation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <string>
#include <sstream> //You will need to add this library to your project.

int main()
{
    int a = 0, n = 0;
    std::ostringstream x;
    while(a < 15) 
    {
        std::cout << "Enter number: ";
        std::cin >> n;
        x << n << " "; //Add the number to our string stream, with a space.
        ++a;
    }
    std::cout << "String is: " << x.str() << "\n"; //This will output contents of the stringstream x.
    return 0;
}


I do not think a 2d array is what you are looking for, or any kind of array for that matter.
Last edited on
I did it a different way. Just posting for variation.

Here's how the strings are defined:
1
2
3
4
5
//create a copy of the word
std::string wordCopy = word;

//change the word in to *'s
wordCopy = createWordCopy( wordCopy );



Then, create a copy of the word, but in *'s:
1
2
3
4
5
6
7
8
9
10
11
12
std::string createWordCopy( std::string wc )
{
	for( unsigned int letter = 0; letter < wc.length();  ++letter )
	{
		// if the current letter is NOT a space,
		// or the NULL character change the letter to a *
		if( ( wc[ letter ] != ' ' ) && ( wc[ letter ] != '\0' ) )
			wc[ letter ] = '*';
	}

	return wc;
}


This function takes the word to be guessed, the word copy and the key that was entered:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
bool checkKey( const std::string w, std::string &wc, const char key )
{
	int found = 0;

	for( unsigned int letter = 0; letter < w.size();  ++letter )
	{
		//if the key pressed matches a letter in the
		//word to be guessed...
		if( w[ letter ] == key )
		{
			//the wordCopy( which is *'s )
			//copy in to the *'s the actual letter
			wc[ letter ] = w[ letter ];
			++found;
		}
	}

	//if a letter is found/not found, return accordingly
	if( found > 0 )
		return true;
	else
		return false;
}
Wow thanks guys, really appreciate it. I did what Mats suggested using a single string and I've got it working now.

However, I have one minor problem. When the game is finished and I return to the main menu to play the game once more, all of the incorrect letters from the previous game show up.

This is despite the fact that I have placed characters.clear() where I should, in order to clear the string before a new game. Is there a different method that should be used to clear the string?
Last edited on
This will clear you string:
1
2
stringstream x; 
x.str(""); //clears it 
Can't thank you enough. This noob is very grateful!
Topic archived. No new replies allowed.