tags:

views:

99

answers:

4

Hi,

Newbie here.

Given the following string, "Hi ~+ and ^*. Is ^* still flying around ~+?"

I want to replace all occurrences of "~+" and "^*" with "Bobby" and "Danny", so the string becomes:

"Hi Bobby and Danny. Is Danny still flying around Bobby?"

I would prefer not to have to call Boost replace function twice to replace the occurrences of the two different values.

Thanks in advance for help. John

A: 

Boost string_algo does have a replace_all function. You could use that.

Matthew Hall
Thanks Matthew, but that only takes one value to be converted and I would need to call it twice. I am trying to find out it there is a way to give essentially a map, if you find x1 replace with y1 and x2 with y2 and so on and the scan over the string only happens once.
John Goodson
+1  A: 

I suggest using the Boost Format library. Instead of ~+ and ^* you then use %1% and %2% and so on, a bit more systematically.

Example from the docs:

cout << boost::format("writing %1%,  x=%2% : %3%-th try") % "toto" % 40.23 % 50; 
     // prints "writing toto,  x=40.230 : 50-th try"

Cheers & hth.,

– Alf

Alf P. Steinbach
Thanks for the suggestion Alf, however I have no control over the input data so your suggestion will not work. I am have to process the content and change the values within as specified by the user who invokes the code.
John Goodson
+1  A: 

Hi John!

I managed to implement the required replacement function using Boost.Iostreams. Specifically, the method I used was a filtering stream using regular expression to match what to replace. I am not sure about the performance on gigabyte sized files. You will need to test it of course. Anyway, here's the code:

#include <boost/regex.hpp>
#include <boost/iostreams/filter/regex.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <iostream>

int main()
{
   using namespace boost::iostreams;

   regex_filter filter1(boost::regex("~\\+"), "Bobby");
   regex_filter filter2(boost::regex("\\^\\*"), "Danny");

   filtering_ostream out;
   out.push(filter1);
   out.push(filter2);
   out.push(std::cout);

   out << "Hi ~+ and ^*. Is ^* still flying around ~+?" << std::endl;

   // for file conversion, use this line instead:
   //out << std::cin.rdbuf();
}

The above prints "Hi Bobby and Danny. Is Danny still flying around Bobby?" when run, just like expected.

It would be interesting to see the performance results, if you decide to measure it.

Daniel

Edit: I just realized that regex_filter needs to read the entire character sequence into memory, making it pretty useless for gigabyte-sized inputs. Oh well...

Daniel Lidström
A: 

I would suggest using std::map. So you have a set of replacements, so do:

std::map<std::string,std::string> replace;
replace["~+"]=Bobby;
replace["^*"]=Danny;

Then you could put the string into a vector of strings and check to see if each string occurs in the map and if it does replace it, you'd also need to take off any punctuation marks from the end. Or add those to the replacements. You could then do it in one loop. I'm not sure if this is really more efficient or useful than boost though.

Jacob Schlather