Home > Back-end >  String subscript out of range in Visual Studio
String subscript out of range in Visual Studio

Time:09-22

I've been following Codecademy's course on C and I've reached the end but I'm confused with the last task.

We have to create a program which filters chosen words as 'swear words' and replaces them with whichever character chosen.

I have written the code in Visual Studio which can be seen below 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);

Now, when I run this code in Visual Studio, I get an assert relating to string subscript it out of range. But with the same code, it works in Codecademys in browser code editor. I cannot for the life of me work out why it won't run in VS.

CodePudding user response:

If you run your program in Debug mode (by pressing F5), the debugger will stop your program right where the problem is. You can then examine the values of your variables, like i and j.

CodePudding user response:

This for inner loop

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

does not take into account that the tail of the string text can be much less than the value of word.size(). So this for loop provokes access memory outside the string text.

To avoid this situation at least rewrite the outer loop the following way

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

A more efficient and safer approach is to use the method find of the class std::string instead of loops.

Here is a demonstrative program.

#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;
}

The program output is

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

CodePudding user response:

When you are doing the text[i j], when i is already near the end of the sentence (say on the . at the end after broccoli), [i j] will go beyond the end of the sentence.
When you're in debug mode in vs, it will check the range of the subscript. Maybe the codeacademy one does not.
You should add a check to ensure that i is not already past the point where the word cant fit in the remaining space. You can end the outer loop at that point.

  • Related