Program crashed after use of .length()

I started using .length in a basic game that is going to have the user guess a number, but if they enter input too short or too long it will tell them to guess again. Problem is, if they enter a value below what the word can be, the application says an abort had to be called, and if they enter a value longer than what the word can be it doesn't crash, but it seems to skip the code it is intended to tell the user that the input is too long.

#include <iostream>
#include <string>

using namespace std;

void printIntro(int word_length);
string checkLength(string guess, int word_length);
int playAgain();
void guessesLeft(int guesscount);
void getGuessAndPrintGuess(int word_length);

int main()
{
constexpr int WORD_LENGTH = 9;

printIntro(WORD_LENGTH);
for (int guessCount = 0; guessCount < 5; guessCount++)
{
guessesLeft(guessCount);
getGuessAndPrintGuess(WORD_LENGTH);
}
guessesLeft(5);

playAgain();


}

void printIntro(int word_length)
{
cout << "Welcome to Bulls and Cows!\n";
cout << "Can you guess the " << word_length << " letter isogram i'm thinking of? You only get 5 chances!\n";
}

void guessesLeft(int guesscount)
{
int guessesLeft = 5 - guesscount;
if (guessesLeft > 0)
{
cout << "You have " << guessesLeft << " guesses left!\n";
}
else
{
cout << "You are out of guesses.\n";
}
}

int playAgain()
{
cout << "Do you want to play again? Make sure to answer in no caps.\n";
string playAgain = "";
getline(cin, playAgain);
if (playAgain == "yes" || playAgain == "sure")
{
main();
}
else if (playAgain == "no" || playAgain == "no thank you.")
{
return 0;
}
else
{
cout << "Sorry, I didn't understand that. Please try again.\n";
int playAgain();
}
}


void getGuessAndPrintGuess(int word_length)
{
cout << "Enter a guess of the word the bull is thinking of: ";
string guess = "";
getline(cin, guess);
cout << "\n";
string checkLength(guess, word_length);
}

string checkLength(string guess, int word_length)
{
if (guess.length() == 9)
{
cout << "You guessed " << guess;
cout << "\n";
return guess;
}
//This is what is skipped.
else if (guess.length() > 9)
{
cout << "Your guess was too big! You need to enter a different guess that is " << word_length << " letters long!\n";
getGuessAndPrintGuess(word_length);
}
//If the value is not greater than or equal to 9, then it should get here
else
{
cout << "Your guess was too small! You need to enter a different guess that is " << word_length << " letters long!\n";
getGuessAndPrintGuess(word_length);
}
}
Is this it?

 
  string  checkLength(guess, word_length);


Should be

 
  string x = checkLength(guess, word_length);
One of the several issues (other than attempting to call main() which is illegal in standard C++) is in this line:

 
string checkLength(guess, word_length);


That doesn't do what you intended.

Instead it attempts to create a string named checkLength
which is a substring of guess. It starts at position word_length and continues to the end of the string. But what happens if the user types a string shorter than word_length ? Well, the requested start position is outside the string.
See std::string constructor (3).
http://www.cplusplus.com/reference/string/string/string/

What you could have put is either of these:

 
checkLength(guess, word_length);

or
 
string result = checkLength(guess, word_length);


There's a related, though different error inside function playAgain(). The line int playAgain(); is a declaration, it doesn't call the function.

In addition, there's a problem with the recursive function calls, in particular when the function promised it would return a value, but didn't, sooner or later those recursive calls will unwind and the program could crash. If the function should return a value, make sure it always does so. If necessary, add a return ""; or return 0; just before the closing brace (depending on what type the function is returning).

Last edited on
Thanks, I've been going through and adding return values to every function that isn't void, and the errors that were appearing with the checkLength function are gone. Now it's all in the play again function, on lines 63 and 72, and the errors are the same for each: Term does not evaluate to a function taking one arguments, and call of an object of a class type without appropriate operator() or conversion functions to pointer-to-function type
I'm gonna be honest, it's been a while since I've gone on C++, so I may be wrong but the entire time I try to debug it everyone else who runs into this problem is usually using pointers, so is there somewhere in here where I should be declaring or using a pointer?
Well, I'd suggest the entire program is overdue for a redesign - you should not be calling main() in C++. That gives a compiler error for me:
[Error] ISO C++ forbids taking address of function '::main' 


But one of the other problems in function playAgain() is that a string variable is given the name playAgain. The use of the same name for both a function and a string variable is not a good idea, and is a problem here - the compiler sees the string variable being called as a function.

Alternative design using loops instead of recursion:
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
#include <iostream>
#include <string>

using namespace std;

void printIntro(int word_length);
bool checkLength(string guess, unsigned word_length);
bool playAgain();
void guessesLeft(int guesscount);
void getGuessAndPrintGuess(int word_length);

int main()
{
    const int WORD_LENGTH = 9;

    do 
    {
        printIntro(WORD_LENGTH);

        for (int guessCount = 0; guessCount < 5; guessCount++)
        {
            guessesLeft(guessCount);
            getGuessAndPrintGuess(WORD_LENGTH);
        }
        guessesLeft(5);
    } while ( playAgain() );
    
}

void printIntro(int word_length)
{
    cout << "Welcome to Bulls and Cows!\n";
    cout << "Can you guess the " << word_length << " letter isogram i'm thinking of? You only get 5 chances!\n";
}

void guessesLeft(int guesscount)
{
    int guessesLeft = 5 - guesscount;
    if (guessesLeft > 0)
    {
        cout << "You have " << guessesLeft << " guesses left!\n";
    }
    else
    {
        cout << "You are out of guesses.\n";
    }
}

bool playAgain()
{
    while (true) // repeat forever
    {
        cout << "Do you want to play again? Make sure to answer in no caps.\n";
        string again;
        getline(cin, again);
        
        if (again == "yes" || again == "sure")
        {
            return true;
        }
        else if (again == "no" || again == "no thank you.")
        {
            return false;
        }
        else
        {
            cout << "Sorry, I didn't understand that. Please try again.\n";
        }
    }
}

void getGuessAndPrintGuess(int word_length)
{
    string guess;
    do
    {
        cout << "Enter a guess of the word the bull is thinking of: ";
        getline(cin, guess);
        cout << "\n";
    } while ( !checkLength(guess, word_length) );
}

bool checkLength(string guess, unsigned  word_length)
{
    if (guess.length() == word_length)
    {
        cout << "You guessed " << guess;
        cout << "\n";
        return true;
    }
    else if (guess.length() > word_length)
    {
        cout << "Your guess was too big! You need to enter a different guess that is " << word_length << " letters long!\n";
    }
    else
    {
        cout << "Your guess was too small! You need to enter a different guess that is " << word_length << " letters long!\n";
    }
    return false;
} 
Last edited on
Thank you! I probably should work over my logic on these things, as I'm seeing another difference being the use of bools, where I should have put them since the values of some functions are just either a yes or no to the user, so thank you.
Topic archived. No new replies allowed.