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.