C ++ STL: проблема со строковыми итераторами - PullRequest
1 голос
/ 28 мая 2010

Я делаю простую игру Hangman для командной строки.

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;
}

(В конце концов, я изменю это так, чтобы displayChar() отображал - или символ, если пользователь угадал его, но для простоты сейчас я просто все возвращаю.)

Когда я собираю и запускаю это из VS 2010, я получаю всплывающее окно:

Ошибка отладочного подтверждения!

строка xstring: 78

Выражение: итератор строки не разыменовываемое

Что я делаю не так?

Ответы [ 3 ]

8 голосов
/ 28 мая 2010

Проблема в оценке:

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

При выполнении этого оператора очевидно, что ваш компилятор сначала увеличивает begin, возвращая "next" begin для использования в качестве первого аргумента для getFormattedAnswerFrom и затем разыменование begin для аргумента displayChar.

Когда begin отстает от end, тогда begin != end, так что displayChar(*begin) + getFormattedAnswerFrom(++begin, end) будет работать. Ваш компилятор увеличивает begin, поэтому теперь begin == end, а разыменование begin недопустимо.

См. Также: Порядок вычисления в параметрах функции C ++

0 голосов
/ 28 мая 2010

Мне кажется, это нормально. Однако помните, что любое повреждение кучи или стека может привести к этой ошибке. Вам нужно захватить трассировку стека и заглянуть внутрь correctAnswer и убедиться, что и он, и рассматриваемый экземпляр Hangman являются допустимыми объектами.

Кроме того, я просто немного обеспокоен вашими функциями здесь. Они кажутся очень странными. Почему бы просто не заменить на std :: for_each?

Редактировать @ комментарий:
Если у вас есть C ++ 0x, вы можете просто сделать

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

Иначе, вам придется сделать что-то похожее на это:

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 голосов
/ 28 мая 2010

Если correctAnswer пусто, correctAnswer.begin() будет таким же, как correctAnswer.end() и не может быть разыменовано.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...