【问题标题】:std::out_of_range on static int variable静态 int 变量上的 std::out_of_range
【发布时间】:2018-01-29 00:33:53
【问题描述】:

我在一个基于 DOS 的小型游戏(课程项目)中使用静态变量作为临时计时器。该变量跟踪状态效果消失之前的转数。代码如下:

for (auto &i : v) // <-- code that calls enemyAttack
    enemyAttack(i, p, str, i.attack);
break;

void enemyAttack(Enemy &e, playerObject &p, std::array<std::string, NUM_MESSAGES> &str, void(*a)(playerObject &p, std::array<std::string, NUM_MESSAGES> &str)) {
    int die = rand() % 100 + 1;
    int d = 1;

    a(p, str); // <-- Call function which causes the error

    ...
}

void batAttack(playerObject &p, std::array<std::string, NUM_MESSAGES> &str) {
    static int time = 2;
    static bool bit = false;

    if (rand() % 10 < CHANCE_OF_STATUS_EFFECT && !bit) {
        p.damage /= 2;
        str[STATUS] += "WEAKENED ";
        bit = true;
    }
    else if (time == 0) {
        p.damage *= 2;
        str[STATUS].replace(str[STATUS].find("WEAKENED ", 0), 9, "");

        time = 2;  // <-- error
        bit = false;
    }
    else if (bit) {
        time--;
    }
}

我在第二个条件内的 time = 2; 行收到 std::out_of_range 错误。该函数是通过来自主要攻击函数的函数指针调用的。错误似乎是随机的,MSVS 报告的所有变量都具有错误发生时应具有的值。

【问题讨论】:

  • 什么是STATUSNUM_MESSAGES 是什么?他们的价值观是什么?请尝试创建Minimal, Complete, and Verifiable Example 并展示给我们。
  • 另外,如果str[STATUS].find("WEAKENED ", 0) 没有找到您要查找的字符串,您认为会发生什么?即使某些事情本应“永远不会发生”,但它总是会发生!
  • 您不会碰巧有多个线程同时尝试访问此静态变量吗?
  • 这是一个编程入门课程的课程项目,我们还没有讨论线程。 STATUS 是枚举的一部分,NUM_MESSAGES 是一个 const int,其值是枚举中 STATUS 所属的值的数量。
  • 但是它们的 值是什么? 虽然我宁愿相信是 find 调用失败并且它返回 npos 导致 replace 抛出异常。使用调试器检查str[STATUS]的值,我敢打赌它不包含子字符串"WEAKENED "

标签: c++ c++11 variables static int


【解决方案1】:

线

str[STATUS].replace(str[STATUS].find("WEAKENED ", 0), 9, "");

只是一场等待发生的灾难。先看一下内部find。

str[STATUS].find("WEAKENED ", 0)

如果你在短程序中使用了两次“WEAKENED”值,当你经常这样做时,你会出现拼写错误,因此最好在此处使用命名值,这样就不会出错。

constexpr const char *WeakenedStr = "WEAKENED ";

然后使用

str[STATUS].find(WeakenedStr , 0)

其次,这可能会失败,如果找不到字符串,它会返回“npos”(当前为 -1)。所以我们也需要测试一下

auto pos = str[STATUS].find("WEAKENED ", 0);
if (pos != std::string::npos)
  str[STATUS].replace(pos, 9, "");

接下来是“9”,它是一个幻数,它也应该是一个命名值

constexpr const char *WeakenedStr = "WEAKENED ";
const int WeakenedStrLen = strlen(WeakenedStr); // strlen is sadly not constexpr.

给予

auto pos = str[STATUS].find("WEAKENED ", 0);
if (pos != std::string::npos)
  str[STATUS].replace(pos, WeakenedStrLen, "");

注意:未经测试的代码,会出现错误。

【讨论】:

  • 成功了!!谢谢!我离预产期只有两天了,开始担心了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-13
  • 2019-04-15
  • 1970-01-01
相关资源
最近更新 更多