有时候C ++异常std :: length_error?

时间:2017-10-15 10:53:52

标签: c++ exception

我正在尝试用C ++编写一个简单的Hangman游戏。游戏大多数工作,但有时当我调试它时,我得到异常std :: length_error。通常在用户输入选择之后。由于Stack Overflow说我的大多数帖子都是代码,所以我在这里编写了相关的代码。但如果需要,我会提供其余的。主要代码,变量和函数声明:

#include "stdafx.h"
#include <iostream>
#include <string>
#include <ctime>
#include <stdlib.h>

using namespace std;

void game(int choice);
void check(char letter, string word);
bool check_win(string word);

char guessed[30];
int guessCount = 0, tries = 0;

int main()
{
    int choice, sentinel;

    cout << "Welcome to Phobez's Hangman game!" << endl;
    cout << "=================================" << endl;
    cout << "Guess a word which is represented by a row of dashes, representing each letter of the word." << endl;
    cout << "Pick a Topic" << endl;
    cout << "1. Animals\n2. Colours\n3. Days of the Week\n4. Months\n5. Body Parts\n6. Numbers" << endl;
    cout << "Choice: ";
    cin >> choice;

    game(choice);

    system("pause");

    return 0;
}

然后game()函数负责设置和运行游戏的大部分内容:

void game(int choice) {
    string word;
    const int MAX_TRIES = 6;
    char letter;

    string animal[] = { "cat", "dog", "horse", "elephant", "duck", "turtle", "bird", "crab", "spider", "bear", "pig", "penguin", "mouse", "rabbit", "lion", "monkey", "bull"};
    string colour[] = { "black", "white", "red", "yellow", "purple", "green", "blue" };
    string day[] = { "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday" };
    string month[] = { "january", "february", "may", "march", "april", "june", "july", "august", "september", "october", "november", "december" };
    string bodPart[] = { "head", "shoulder", "knee", "forehead", "eyebrow", "ear", "eye", "nose", "chest", "mouth", "arm", "stomach", "hand", "leg", "foot", "toe" };
    string nums[] = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "zero" };

    srand(time(0));

    switch (choice) {
        case 1:
            word = animal[(rand() % 17) - 1];
            break;
        case 2:
            word = colour[(rand() % 7) - 1];
            break;
        case 3:
            word = day[(rand() % 7) - 1];
            break;
        case 4:
            word = month[(rand() % 12) - 1];
            break;
        case 5:
            word = bodPart[(rand() % 16) - 1];
            break;
        case 6:
            word = nums[(rand() % 10) - 1];
            break;
        default:
            word = animal[(rand() % 18) - 1];
    }

    do {
        cout << "Word: ";

        for (int i = 0; i < strlen(word.c_str()); i++) {
            bool isPrinted = 0;

            for (int j = 0; j < strlen(word.c_str()); j++) {
                if (word[i] == guessed[j]) {
                    cout << word[i];
                    isPrinted = 1;
                    break;
                }
            }

            if (isPrinted) {
                continue;
            }
            else {
                cout << "_";
            }
        }

        cout << endl;
        cout << "Misses: " << tries << endl;
        cout << "Guess: ";
        cin >> letter;

        check(letter, word);

        if (check_win(word)) {
            cout << word << endl;
            cout << "You won!" << endl;
            break;
        }
        else {
            continue;
        }

    } while (tries < MAX_TRIES);

    if (tries >= MAX_TRIES) {
        cout << "You lost!" << endl;
    }
}

我已经尝试搜索Google和Stack Overflow以获取有关此问题的帮助,但我找不到可以向我解释我的代码有什么问题。

错误有时会弹出。大部分时间都有效。我认为这是我的开关案例中的错误(随机整数生成器限制),但我尝试将它们更改几次,但没有区别。有人可以帮忙吗?这是我面临的唯一错误。提前谢谢!

2 个答案:

答案 0 :(得分:0)

if (word[i] == guessed[j]) j索引可能超出范围,因为它的上限为j < strlen(word.c_str());而不是guessed长度。同样值得将guessed类型更改为::std::string。因此,循环条件需要更改为

for
(
    ::std::string::size_type guessed_symbol_index = 0;
    guessed.length() != guessed_symbol_index;
    ++guessed_symbol_index
) 
...
if (word[i] == guessed[guessed_symbol_index]) {

所有切换案例都填充了可能导致越界访问的行,例如animal[(rand() % 17) - 1];如果rand返回17.此外,您可能会意外地设置错误的数组大小(使用魔术数字很糟糕) 。您应该将这些数组重新定义为

::std::array<::std::string, 7> day = { "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday" };

然后正确提取长度:

day[static_cast<::std::size_t>(rand()) % day.size()];

答案 1 :(得分:0)

使用调试器它会更快。但这里有演绎方式:

    当尝试超出max_size stringvectorvector对象的实现定义长度限制时,会引发
  1. std::length_error。 (请注意,这不是超出范围的问题,而是存储对象所需大小的问题)。

  2. 您不使用word,而您唯一的字符串是wordRAND_MAX可能超出存储限制的唯一位置是您对其进行分配时。但是限制是如此之大,以至于数组中的小字无法触发。

  3. 因此,这意味着您的数组访问权限不会访问您认为它访问的元素。因此下标必定存在问题。

  4. 此处我们登陆rand(),返回0到rand()之间的值。使用模数,您可以确保上限正常。但是如果-1返回0怎么办?然后,您可以访问元素animal[],这是未定义的行为以及意外崩溃的根本原因。

  5. 如何解决?

    更改下标表达式。例如,在rand() % 17中,您有17个元素,索引从0到16.因此,如果您将下标更改为 <string> animal{ "cat", "dog", "horse", "elephant", "duck", "turtle", "bird", "crab", "spider", "bear", "pig", "penguin", "mouse", "rabbit", "lion", "monkey", "bull"}; ... word = animal[ rand()%animal.size() ]; // asuming that the vector is not empty :-) ,您将得到0到16之间的数字,保证在预期的范围内。

    您也可以使用向量而不是数组,这可以避免手动计算其中的元素:

    strlen(word.c_str())

    P.S:word.size()可以替换为{{1}}