【问题标题】:String subscript out of range in Visual StudioVisual Studio 中的字符串下标超出范围
【发布时间】:2021-11-15 04:29:58
【问题描述】:

我一直在学习 Codecademy 的 C++ 课程,我已经完成了,但我对最后一个任务感到困惑。

我们必须创建一个程序,将所选单词过滤为“脏话”,并用所选字符替换它们。

我在 Visual Studio 中编写了代码,如下所示 main.cpp

#include <iostream>
#include <string>

#include "functions.h"


int main()
{
    std::string word = "broccoli";
    std::string sentence = "I sometimes eat broccoli.";
    bleep(word, sentence);

    for (int i = 0; i < sentence.size(); i++) {
        std::cout << sentence[i];
    }

    std::cout << "\n";
}

functions.cpp

#include <iostream>
#include <string>
#include "functions.h"

void asterisk(std::string word, std::string &text, int i) {
    for (int k = 0; k < word.size(); k++) {
        text[i + k] = '*';
    }

}

void bleep(std::string word, std::string &text) {
    for (int i = 0; i < text.size(); i++) {
        int match = 0;
        for (int j = 0; j < word.size(); j++) {
            if (text[i + j] == word[j]) {
                match++;
            }       
            
        }
        if (match == word.size()) {
            asterisk(word, text, i);
        }
    }
}


函数.h

#pragma once

void bleep(std::string word, std::string &text);
void asterisk(std::string word, std::string &text, int i);

现在,当我在 Visual Studio 中运行此代码时,我得到一个与字符串下标相关的断言,它超出了范围。但是使用相同的代码,它可以在浏览器代码编辑器中的 Codecademys 中运行。 我一生都无法弄清楚为什么它不能在 VS 中运行。

【问题讨论】:

  • 可能与问题无关,但是否有任何理由使用循环打印main 中的string 而不是更简单的std::cout &lt;&lt; sentence;
  • Visual Studio 在调试模式下会添加一些 C++ 标准不需要的额外检查,以帮助您发现缓冲区溢出等常见错误。看起来它有助于找到一个。
  • 这里有一个错误:text[i + j] 你必须确保 i+j 小于 text.size()

标签: c++ string for-loop replace function-definition


【解决方案1】:

this for 内循环

    for (int j = 0; j < word.size(); j++) {
        if (text[i + j] == word[j]) {
            match++;
        }       
        
    }

没有考虑到字符串text的尾部可以远小于word.size()的值。所以这个 for 循环会在字符串文本之外引发访问内存。

为了避免这种情况,至少重写外循环如下方式

if ( not ( text.size() < word.size() ) )
{
    for ( size_t i = 0, n = text.size() - word.size() + 1; i < n; i++) {
        //...
}

更有效和更安全的方法是使用std::string 类的方法find 而不是循环。

这是一个演示程序。

#include <iostream>
#include <string>

std::string & bleep( std::string &text, const std::string &word, char c )
{
    if ( auto n = word.size() )
    {
        for ( std::string::size_type pos = 0; 
              ( pos = text.find( word, pos ) ) != std::string::npos; 
              pos += n )
        {
            text.replace( pos, n, n, c );
        }
    }
    
    return text;
}

int main() 
{
    std::string word = "broccoli";
    std::string sentence = "I sometimes eat broccoli.";
    
    std::cout << sentence << '\n';
    std::cout << bleep( sentence, word, '*' ) << '\n';
    
    return 0;
}

程序输出是

I sometimes eat broccoli.
I sometimes eat ********.

【讨论】:

  • 啊,我明白了。这完全有道理!非常感谢!
  • @George_H 完全没有。我们,初学者,应该互相帮助。:)
【解决方案2】:

如果您在调试模式下运行程序(通过按 F5),调试器将在问题所在的位置停止您的程序。然后,您可以检查变量的值,例如 ij

【讨论】:

    【解决方案3】:

    当你在做文本[i+j]时,当i已经接近句尾时(比如在broccoli后面的.),[i+j]会超出句尾.
    当您在 vs 中处于调试模式时,它会检查下标的范围。也许代码学院没有。
    您应该添加一个检查以确保 i 尚未超过单词无法放入剩余空间的点。您可以在此时结束外循环。

    【讨论】:

      猜你喜欢
      • 2018-02-28
      • 2015-03-31
      • 2013-04-22
      • 2012-04-27
      • 2014-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多