I'm searching a text document and replacing substrings with other substrings. So for instance:
"ra,16(sp)" with "ra,16($sp)"

The issue I'm having is that say I have the following string:
"sp,sp,24"

How do I re-iteratively replace "sp" with "$sp" twice without getting:
"$$sp,$sp,24"

This is my code:

...
if ( words[i].find("sp")!=string::npos )
            {
                int temp = words[i].find("sp");
                words[i].erase(temp,2);
                words[i].insert(temp,"$sp");
                cout << words[i] << endl;
            } 
...

I handle each string on a word by word basis by the way. I'm going to try to maybe same the location to memory and then cancel an if statement if that location is found again. Any ideas on a string function that will make this easier?

Recommended Answers

All 16 Replies

Do you have to implement it from scratch? Because you should be able to use function string.replace() from string. If not, you need to keep track how far you have gone through so far in the find(). In other words, add a position variable to the first find(), and then use that position + 'substring replace length' as the starting position for the next find() call.

That sounds like a good idea. The problem with replace as far as I can see it is that because I'm trying to insert 3 characters where 2 characters once were, I need to allot new space for the extra character. erase/insert seem to work well in this respect. Am I wrong about replace?

Okay, I got it, things get slightly more complicated for 3 instances of the substring but in my plane of strings there are no such subsets. Here's my solution, if there is a better way to do this please let me know:

int temp = 0;
for ( int j=0; j<=2; j++)
{
   if ( words[i].find("sp",temp)!=string::npos )
   {
       temp = words[i].find("sp",temp);
       words[i].erase(temp,2);
       words[i].insert(temp,"$sp");
       temp = temp +3;
   } 
}

I have tested this and it works fine

for(int i = 0; i < words.length(); ++i)
	{	
		if ( words[i] == 's' && words[i+1] == 'p' )
		{
			words.insert(i, "$");
			cout << words << endl;
			i += 2;
		}
	}

EDIT: Didn't see your post

Not sure about replace is going to work in your loop. The code below is what I was trying to tell you in my previous post.

int found_pos = words[i].find("sp");
while ( found_pos>=0 ) {  // not sure what returns from find() when not found (-1?)
  words[i].replace(found_pos, 2, "$sp");  // 'sp' is length of 2
  found_pos += 3;  // '$sp' is length of 3
  found_pos = words[i].find("sp", found_pos);  // look for 'sp' starting from 'found_pos'
}

cout << words[i] << endl;

EDIT: Err, you posted before me... :P

for(int i = 0; i < words.length(); ++i) {	
  if ( words[i] == 's' && words[i+1] == 'p' ) {
    words.insert(i, "$");
    cout << words << endl;
    i += 2;
  }
}

For this code, I think it is not that way. The reason is that his 'words' variable is an array of string. He wants to replace each substring found in each word in 'words', not that words contains each char??? Or did I misinterpret?

So, my words vector is full of words (good name right?) and each word is made up of several characters. So as far as I can tell, to get Jeronim's code to work in my situation I have to just add the index "" to words. Hmm, I'm going to try out some of these ideas too.

Got it wrong sry.

in that case just add one extra for loop

for(int i=0; i<sizeof(words); ++i)
		for(int j=0; j<words[i].length(); ++j)
			if ( words[i][j] == 's' && words[i][j+1] == 'p'){

				words[i].insert(j, "$");
				cout << words[i]<<endl;
				j += 2;
			}

EDIT:

you can also add this to code so you don't have to change previous function

vector<string >::iterator part= words.begin();
	for(part; part != words.end(); ++part)
	replaceSP(*part);
for(int j=0; j<words[i].length(); ++j)
  if ( words[i][j] == 's' && words[i][j+1] == 'p'){
  ...

Sorry to pick up on your code... The quoted code part above is what may cause problem later (out of range)??? Shouldn't it be j<words.length()-2?

yep you are right :)

btw it's not sizeof(words) but words.size() in for loop

for(int i=0; i<words.size(); ++i)
		for(int j=0; j< ( words[i].length()-2 ); ++j)
			if ( words[i][j] == 's' && words[i][j+1] == 'p'){

				words[i].insert(j, "$");
				cout << words[i]<<endl;
				j += 2;
			}

Although I have this working well due to the help both of you have given me, I wonder if I should be doing this in Perl..

> I wonder if I should be doing this in Perl..
In applications with excessive string handling, C++ is probably not the best choice.

Agreed, I'm on a schedule so I figure I had better just get this done. But the next time around I think I should put forth the effort in learning Perl or Python.

Second. You can use regex to replace it and the code is much shorter.

simply use two conditions in your code..
One which skips the code if it finds $sp.
The other which finds sp and replaces it with $sp.

simply use two conditions in your code..
One which skips the code if it finds $sp.
The other which finds sp and replaces it with $sp.

The concept makes even more complicated. The reason is that the algorithm still needs 'start position' of find() in order to get the next 'sp'. Why would you put in more testing condition while you can just simply find 'sp' position, replace it with '$sp', and then find again starting from the position of last replaced?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.