开发者

C++ STL: Trouble with string iterators

开发者 https://www.devze.com 2023-01-01 22:01 出处:网络
I\'m making a simple command line Hangman game. void Hangman::printStatus() { cout << \"Lives remaining: \" << livesRemaining << endl;

I'm making a simple command line Hangman game.

void Hangman::printStatus()
{
    cout << "Lives remaining: " << livesRemaining << endl;
    cout << getFormattedAnswer() << endl;
}

string Hangman::getFormattedAnswer()
{
    return getFormattedAnswerFrom(correctAnswer.begin(), correctAnswer.end());
}

string Hangman::getFormattedAnswerFrom(string::const_iterator begin, string::const_iterator end)
{
    return begin == end? "" : displayChar(*begin) + getFormattedAnswerFrom(++begin, end);
}

char Hangman::displayChar(const char c)
{
    return c;
}

(Eventually, I'll change this so displayChar() displays a - or a character if the user has guessed it, but for simplicity now I'm just returning everything.)

When I build and run this from VS 2010, I get a popup box:

Debug Assertion Failed!

xstring Line: 78

Expression: string iterator not dereferenceable

What am I doing 开发者_如何学编程wrong?


The problem is in the evaluation of:

displayChar(*begin) + getFormattedAnswerFrom(++begin, end)

In executing this statement, it is evident that your compiler is first incrementing begin, returning the "next" begin for use as the first argument to getFormattedAnswerFrom, and then dereferencing begin for the argument to displayChar.

When begin is one behind end, then begin != end so displayChar(*begin) + getFormattedAnswerFrom(++begin, end) will run. Your compiler increments begin, so now begin == end, and the dereference of begin is invalid.

See also: Order of evaluation in C++ function parameters


If correctAnswer is empty, correctAnswer.begin() will be the same as correctAnswer.end() and not be dereferenceable.


It seems fine to me. However, remember any heap or stack corruption could produce this error. You need to grab the stack trace and look inside correctAnswer, and ensure that both it and the instance of Hangman in question are valid objects.

Also, I'm just flat out a little concerned about your functions here. They seem very strange. Why not just replace with std::for_each?

Edit@comment:
If you have C++0x, you can just do

std::for_each(correctAnswer.begin(), correctAnswer.end(), [this](const char& ref) {
    std::cout << this->displayChar(ref);
});

Else, you will have to do something that looks a little like this:

struct helper {
    Hangman* ptr;
    void operator()(const char& ref) {
        std::cout << ptr->displayChar(ref);
    }
};
helper Helper;
Helper.ptr = this;
std::for_each(correctAnswer.begin(), correctAnswer.end(), Helper);
0

精彩评论

暂无评论...
验证码 换一张
取 消