Replacing Strings in C++

Programming, for all ages and all languages.
Post Reply
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Replacing Strings in C++

Post by pcmattman »

I'm using the string class in a C++ program I'm writing to assist me in diagnosing network issues.

The problem is, I need to be able to handle newlines written into the console as '\n' (ie. '\\', 'n'). I need to be able to replace the string "\n" (which is two bytes) to '\n' (the one byte version), and make sure no remnants are left over.

I'm using VC++ 6.

Edit: never mind, I got it:

Code: Select all



				// search for newlines
				int lastf = 0;
				for( i = 0; i < dat.length(); i++ )
				{
					if( lastf != 0 )
					{
						lastf = dat.find( "\\n", lastf + 1 );
					}
					else
					{
						lastf = dat.find( "\\n", lastf );
					}

					if( lastf == -1 )
						break;
					else
					{
						dat.replace( lastf, 2, "\n" );
					}
				}
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

If you need to process more than one escape, I suggest you take the source string, and copy it to destination string one character at a time. Both strings can actually be the same, if you want to work in place. You keep separate index for each. While reading the source, if you hit a backslash, instead of just copying it, you advance the source-index only, looking at the next character to see what kind of escape it is, and then write the escaped special character instead of the two characters. This way you only have to go over the string once.

It's been too long since I used STL strings for anything, so I'll give an example in C:

Code: Select all

// replaces \n with newline, \e with escape, \b with backspace and \\ with \
// returns -1 and prints error if other escapes are encountered
int replace_escapes(char * dest, const char * src) {
   int si = 0, di = 0;
   while(src[si]) {
      if(src[si] == '\\') {
         switch(src[++si]) {
           case 'e': dest[di] = '\033'; break;
           case 'n': dest[di] = '\n'; break;
           case 'b': dest[di] = '\b'; break;
           case '\\': dest[di] = '\\'; break;
           default: fprintf(stderr, "invalid escape \\%c\n", src[si]); return -1;             
      } else {
           dest[di] = src[si];
      }
      ++si; ++di;
   }
}
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Post by Solar »

Code: Select all

size_t pos = 0;
while ( ( pos = mystring.find( "\\n", pos ) ) != string::npos )
{
    mystring.replace( pos++, 2, "\n" );
}
Can probably be optimized further, but should suffice as example for how to do it with the STL.
Every good solution is obvious once you've found it.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

Hmmm... sounds good.

I'll have to write a str_replace() function to do the same thing with ny length string. Saves a lot of code space sometimes :D.
Post Reply