replace words in strings

closed account (EwCjE3v7)
I have this exercise from my book, I have to use iterators and the insert and erase functions to replace all oldVals with newVals in s.

But I get an out of range exception

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
27
28
29
30
31
32
33
34
35
36
37
// Keyboard keys \ |
#include <iostream>
#include <string>
using std::cout; using std::cerr; using std::endl;
using std::string;

// function that replaces one word with another, suck as "tho" with "though"

string replace_str(string s, string oldVal, const string newVal) // replace oldVal with newVal in s
{
	if (!s.empty() && !oldVal.empty()) {
		auto sbeg = s.begin(), OVbeg = oldVal.begin();
		unsigned cnt = 0;

		while (sbeg != s.end()) {
			while (sbeg != s.end() && OVbeg != oldVal.end() && *sbeg == *OVbeg) {
				++cnt;
				++sbeg;
				++OVbeg;
			}
			if (cnt == oldVal.size()) {
				sbeg = s.erase(sbeg - oldVal.size(), sbeg);
				s.insert(sbeg, newVal.cbegin(), newVal.cend());
			}
			if (sbeg != s.end())
				++sbeg;
		}
	}
	return s;
}

int main()
{
	cout << replace_str("You are tho wrong. tho", "tho", "though") << endl;
	return 0;
}
Last edited on
Please move this to an appropriate forum. You know.. one with "programming" in the name, or it might also be at home in "Beginners"

You never reset the values of cnt or OVbeg in the case of a partial or full match.
closed account (EwCjE3v7)
Moved, sorry for that.

And about the program, what do you mean?

Do you mean this? Still out of range.

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
27
28
29
30
31
32
33
34
35
36
37
38
39
// Keyboard keys \ |
#include <iostream>
#include <string>
using std::cout; using std::cerr; using std::endl;
using std::string;

// function that replaces one word with another, suck as "tho" with "though"

string replace_str(string s, string oldVal, const string newVal) // replace oldVal with newVal in s
{
	if (!s.empty() && !oldVal.empty()) {
		auto sbeg = s.begin(), OVbeg = oldVal.begin();
		unsigned cnt = 0;

		while (sbeg != s.end()) {
			while (sbeg != s.end() && OVbeg != oldVal.end() && *sbeg == *OVbeg) {
				++cnt;
				++sbeg;
				++OVbeg;
			}
			if (cnt == oldVal.size()) {
				sbeg = s.erase(sbeg - oldVal.size(), sbeg);
				s.insert(sbeg, newVal.cbegin(), newVal.cend());
			}
			cnt = 0; // This?
			OVbeg = oldVal.begin();
			
			if (sbeg != s.end())
				++sbeg;
		}
	}
	return s;
}

int main()
{
	cout << replace_str("You are tho wrong. tho", "tho", "though") << endl;
	return 0;
}


The issue occurs on line 23. I don't believe you get the resulting iterator from that operation (a C++11 feature, but an important one) which I believe ultimately leads to an invalid iterator.

Inserting each character from newVal one by one, however, works in C++03. Remember to get the resulting iterator from each std::insert operation.

-Albatross
closed account (EwCjE3v7)
Albatross, when I do sbeg = s.insert(sbeg, newVal.cbegin(), newVal.cend());, its gives me the following error :

Testing.cpp: In function ‘std::string replace_str(std::string, std::string, std::string)’:
Testing.cpp:23:10: error: no match for ‘operator=’ (operand types are ‘__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >’ and ‘void’)
     sbeg = s.insert(sbeg, newVal.cbegin(), newVal.cend());
You are using the form 7 of string::insert
http://www.cplusplus.com/reference/string/string/insert/

The return type is void. That is why it cannot be assigned to a iterator variable.

Form 6 will do what Albatross said
iterator insert (iterator p, char c);

This is all assuming you are using C++98 standards. If you are compiling with C++11 standards you should look at those forms on that reference link I gave.

Edit: Assuming you will probably want to compile with C++11 features. You might have a look here if you are using g++
http://stackoverflow.com/questions/10363646/compiling-c11-with-g
Basically just tack on
-std=c++11
as a compiler flag or try
-std=c++0x
if the other does not work.
Last edited on
closed account (EwCjE3v7)
@kevin I always compile with C++11, but can you tell me where it states that the range returns void, as on that link it says the following:
Return value
The signatures returning a reference to string, return *this.
Those returning an iterator, return an iterator pointing to the first character inserted.

Member type iterator is a random access iterator type that points to characters of the string.
When you look at the reference pages on here, at the top there is C++98, C++11, C++14. You can click those and see the different prototypes for the reference you are looking at. The prototypes tell what type the function returns. The explanation you quoted applys to all the different overloaded forms.
Last edited on
closed account (EwCjE3v7)
I got it, but it still has a few errors that I think I can fix, thank you kevin and albatross.
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// Keyboard keys \ |
#include <iostream>
#include <string>
using std::cout; using std::cerr; using std::endl;
using std::string;

// function that replaces one word with another, suck as "tho" with "though"

string replace_str(string s, string oldVal, const string newVal) // replace oldVal with newVal in s
{
	if (!s.empty() && !oldVal.empty()) {
		auto sbeg = s.begin(), OVbeg = oldVal.begin();
		unsigned cnt = 0;

		while (sbeg != s.end()) {
			while (sbeg != s.end() && OVbeg != oldVal.end() && *sbeg == *OVbeg) {
				++cnt;
				++sbeg;
				++OVbeg;
			}
			if (cnt == oldVal.size()) {
				sbeg = s.erase(sbeg - oldVal.size(), sbeg);
				for (decltype(newVal.size()) ind = 0; ind != newVal.size(); ++ind) {
					sbeg = s.insert(sbeg, newVal[ind]);
					++sbeg;
				}
			}
			cnt = 0; // This?
			OVbeg = oldVal.begin();

			if (sbeg != s.end())
				++sbeg;
		}
	}
	return s;
}

int main()
{
	cout << replace_str("tho You are tho wrong. tho", "tho", "though") << endl;
	return 0;
}

Topic archived. No new replies allowed.