range/debug 断言失败的 c++ 字符串下标

c++ string subscript out of range/debug assertion failed

我正在研究翻转一串数字。我在编译时没有收到任何错误或警告,但在我输入数字后,弹出一个错误 window,我可以理解 none 个单词。有人可以帮助我吗?

我的目的is:to看看,在一个数区间中,有多少数转180度后相同? (例如 8888、6699、90088006)

环境: OS: Windows 10, 64 位

IDE:Visual studio 社区 2022

错误window:

代码:

#include <iostream>
#include <string>

using namespace std;

int total = 0;

void numf(int n, string c) {
    if (!(c.find('3') == 0 and c.find('4') == 0 and c.find('7') == 0 and
          c.find('2') == 0 and c.find('5') == 0)) {

        // reverse
        string c2;

        for (int i = 0; i < sizeof(c) / sizeof(c[0]); i++) {
            c2[i] = c[sizeof(c) / sizeof(c[0]) - i - 1];
        }
        for (int i = 0; i < sizeof(c) / sizeof(c[0]); i++) {
            if (c2[i] == '6') {
                c2[i] = '9';
            } else if (c2[i] == '9') {
                c2[i] = '6';
            }
        }
        if (c2 == c) {
            total++;
        }
    }
    return;
}

int main() {
    int num, num2;

    cin >> num >> num2;

    for (int i = num; i <= num2; i++) {
        string newnum = to_string(i);
        numf(i, newnum);
    }
    cout << total;
    return 0;
}

对于初学者来说,这个 if 语句

if (!(c.find('3') == 0 and c.find('4') == 0 and c.find('7') == 0 and
      c.find('2') == 0 and c.find('5') == 0)) {

没有意义。

您似乎在尝试排除包含所列数字之一的号码。

在这种情况下你应该写

if ( c.find_first_of( "34725" ) == std::string::npos )
{
    //...

class std::string 不是数组。所以下面循环中的表达式 sizeof(c) / sizeof(c[0]) 也没有意义。

    for (int i = 0; i < sizeof(c) / sizeof(c[0]); i++) {
        c2[i] = c[sizeof(c) / sizeof(c[0]) - i - 1];
    }

而且对象 c2 是空的。所以你可能不会使用像 c2[i].

这样的下标运算符

你可以只写而不是循环

std::string c2( c.rbegin(), c.rend() );

这个不正确的 for 循环

    for (int i = 0; i < sizeof(c) / sizeof(c[0]); i++) {
        if (c2[i] == '6') {
            c2[i] = '9';
        } else if (c2[i] == '9') {
            c2[i] = '6';
        }
    }

可以改成下面的range-basedfor循环

for ( auto &ch : c2 )
{
    if ( ch == '6') 
    {
        ch = '9';
    }
    else if ( ch == '9' ) 
    {
        ch = '6';
    }
}

注意第一个函数参数没有在函数内部使用

在函数中使用全局变量 total 也是一个坏主意。如果函数具有 return 类型 bool 和 returned true 以防数字满足要求,那就更好了。

如果我正确理解了作业,那么我会编写如下程序。

#include <iostream>
#include <string>
#include <utility>
#include <algorithm>

bool numf( const std::string &s )
{
    if ( s.find_first_of( "34725" ) == std::string::npos )
    {
        std::string s2( s.rbegin(), s.rend() );

        for ( auto &c :s2 )
        {
            if (c == '9')
            {
                c = '6';
            }
            else if (c == '6')
            {
                c = '9';
            }
        }

        return s == s2;
    }
    else
    {
        return false;
    }
}

int main()
{
    unsigned int num1 = 0, num2 = 0;

    std::cin >> num1 >> num2;

    std::tie( num1, num2 ) = std::minmax( { num1, num2 } );

    unsigned int total = 0;

    for (; num1 <= num2; ++num1)
    {
        total += numf( std::to_string( num1 ) );
    }

    std::cout << "total = " << total << '\n';
}

程序输出可能看起来像

60 99
total = 3

你的任务很有趣。以防万一,如果您对解决任务的其他方法感到好奇,而不仅仅是对如何修复代码感到好奇,为此我为您编写了自己的解决方案。

我的解决方案是使用小转换 table "01xxxx9x86" 来计算数字的 180 度旋转,x 这里表示数字不是 rotatable.

如您所见,我将 1 包含在 rotatable 中,与您在代码中所做的相同,但在某些类型的字体中 1 旋转 180 度看起来并不像相同的。您可以通过在我的代码的转换 table 中用 x 符号标记它来将其从 rotatables 中排除。

Try it online!

#include <cstdint>
#include <string>
#include <iostream>

uint64_t RotateCount(uint64_t begin, uint64_t end) {
    uint64_t cnt = 0;
    char constexpr conv[] = "01xxxx9x86";
    for (uint64_t n = begin; n < end; ++n) {
        std::string const s = std::to_string(n);
        bool matched = true;
        for (size_t i = 0; i < (s.size() + 1) / 2; ++i)
            if (conv[s[i] - '0'] != s[s.size() - 1 - i]) {
                matched = false;
                break;
            }
        if (matched)
            ++cnt;
    }
    return cnt;
}

int main() {
    uint64_t begin = 1'000'000, end = 9'000'000;
    std::cout << "Count: " << RotateCount(begin, end)
        << std::endl;
}

输入范围:

1'000'000 ... 9'000'000

输出:

Count: 225