Replace Words or combinations in a string

Sep 14, 2019 at 10:13am
Hey everyone,
I am trying to replace any word in a string with another. The following code works for single characters, but I can't get it to work for words as well. Can anyone please help?
Thanks

#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main()
{
string a;
cin >> a;
replace( a.begin(), a.end(), "good", "bad" );
cout << a << endl;

} //("code")

Sep 14, 2019 at 11:16am
You'er going to have to find each occurence of the string "good" and replace them individually in a loop. Also, replace needs the length of the string "good".

Here's an example that seems to work:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <string>
#include <iostream>

int main(){
    std::string a;
    std::string good = "good";
    std::getline(std::cin, a);
    size_t index = a.find(good);
    while(index != std::string::npos){
        a.replace(index, good.length(), "bad");
        index = a.find(good);
    }
    std::cout << a << std::endl;
    return 0;
}

If you'd like me to explain what each line does, I'd be happy to.
Sep 14, 2019 at 3:46pm
That is very inefficient if you were doing something serious.
you are starting over at the beginning of the string each time, making a O(N) problem into a N*N … which is a common problem when using the built in functions without care as they hide a bit of looping from you. Try calling find from where you left off, rather than from the start each time. That works here; there are some cases where replacing a string can create a new copy of the original, forcing you to back up the starting point a bit.
Last edited on Sep 14, 2019 at 3:48pm
Sep 14, 2019 at 8:08pm
Thank you so much for your replies

The problem is I have a table of symbol combinations and their equivalent and I am asked to write a program that takes a string that has those combinations and other words and outputs the same string but without the symbol combinations

For instance,
if I input
"I have some %$# and other stuff too #$@# which makes it hard"

I should get

"I have some . and other stuff too <> which makes it hard

I don't know what should I do
Sep 14, 2019 at 8:09pm
Please if anyone replies write the using namespace std because it makes the code more fun to read
thanks
Sep 14, 2019 at 8:31pm
Well, a really slow method would be to just check for all words individually. I'm absolutely certain there are way more efficient algorithms but this is really simple to write and I think you get what's happening in it. You can try to optimize it later.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <string>
#include <map>
#include <iostream>
using namespace std;

//add your pairs in here
map<string, string> toReplace = {{"good", "bad"}, {"%$#", "."}, {"#$@#", "<>"}};
void replaceWords(string &s, string from, string to){
    size_t index = s.find(from);
    while(index != std::string::npos){
        s.replace(index, from.length(), to);
        index = s.find(from, index);
    }
}

int main(){
    string a;
    getline(std::cin, a);

    for(auto p : toReplace){
        replaceWords(a, p.first, p.second);
    }

    cout << a << std::endl;
    return 0;
}
Sep 14, 2019 at 8:36pm
@Bembel, test your code with the phrase "goodness me!".
Sep 14, 2019 at 8:39pm
@lastchance
Yep, returns "badness me", which I believe is what is being asked here. @Jack Van Stone is supposed to replace all occurences of some substring with some other substring, not just single words. At least thats how I interpreted it?
Sep 14, 2019 at 8:55pm
great!! Thank you so much
I'll make sure I understand it well and try to optimise it
Sep 14, 2019 at 9:09pm

@Bembel
I have never used maps in c++, can you please explain what happens?
Sep 14, 2019 at 9:23pm
@Jack Van Stone
Sure, this thread is getting a bit out of hand but eh, what the heck
Maps are essentially a bunch of pairs, a key and a value associated with the key. So the value associated with the key "good" is "bad", and so on.
In the code I wrote, I write out the pairs, "good" is paired with "bad" etc. Then, I iterate through all of my pairs. C++11 added this really nice functionality for going through different maps/arrays/strings/vectors, which I've used here. It's the for(auto p : toReplace) part and it's just taking one pair at a time from my map and putting it in the variable p. The first string of the two strings in this pair is in p.first.
So, "good" would be the first string in the pair, and that's the string we want to find and replace. We put that into the replaceWords function, do the same thing with p.second and voila. We process that pair, and move on to the next.

That's just a simple use case, they're really useful for loads of different things but it gets more in-depth and I don't want to confuse you too much.

There's more info here, along with some examples if you click around if you decide you do want to become more confused:
http://www.cplusplus.com/reference/map/map/
Sep 14, 2019 at 9:58pm
Actually, I interpreted a word as an entity delimited by blanks, but each to his own.
Sep 14, 2019 at 11:28pm
Regex would make this trivial. Use a regex to find all instances to replace, then iterate through, building the new string as you go. It wont get more efficient than that.

Edit: I forgot to add that the regex library will do this for yo. Find examples at cppreference.com, and here too.
Last edited on Sep 14, 2019 at 11:48pm
Topic archived. No new replies allowed.