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.
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 ********.