Visual Studio 中的字符串下标超出范围
String subscript out of range in Visual Studio
我一直在学习 Codecademy 的 C++ 课程,我已经学完了,但我对最后一个任务感到困惑。
我们必须创建一个程序,将所选单词过滤为 'swear words' 并用所选字符替换它们。
我把代码写在了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);
}
}
}
functions.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 中。
如果您 运行 您的程序处于调试模式(通过按 F5),调试器将在问题所在的位置停止您的程序。然后您可以检查变量的值,例如 i
和 j
.
当你在做文本[i + j]时,当i已经接近句子的结尾时(比如在西兰花后面的.上),[i+j]会超出句子的结尾句子.
当你在 vs 中处于调试模式时,它会检查下标的范围。也许代码学院没有。
您应该添加一个检查以确保 i 还没有超过单词不能放入剩余 space 的点。您可以在此时结束外循环。
这是内循环
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++) {
//...
}
更有效和更安全的方法是使用 class 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 ********.
我一直在学习 Codecademy 的 C++ 课程,我已经学完了,但我对最后一个任务感到困惑。
我们必须创建一个程序,将所选单词过滤为 'swear words' 并用所选字符替换它们。
我把代码写在了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);
}
}
}
functions.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 中。
如果您 运行 您的程序处于调试模式(通过按 F5),调试器将在问题所在的位置停止您的程序。然后您可以检查变量的值,例如 i
和 j
.
当你在做文本[i + j]时,当i已经接近句子的结尾时(比如在西兰花后面的.上),[i+j]会超出句子的结尾句子.
当你在 vs 中处于调试模式时,它会检查下标的范围。也许代码学院没有。
您应该添加一个检查以确保 i 还没有超过单词不能放入剩余 space 的点。您可以在此时结束外循环。
这是内循环
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++) {
//...
}
更有效和更安全的方法是使用 class 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 ********.