473,897 Members | 2,557 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Interesting std::replace_if problem

I guess this problem can be distilled down to: How do I search through a
string, find the first matching substring, replace it, and continue through
the string doing this. Can replace_if() be used to do this?

Here is a concrete example:
If I have a string with sequences of CRLF and possibly just CR's, is there a
simple way of replacing the CRLF characters with a LF?

If you look at the function below is it possible to use a replace_if to do
this?
void CGeneralMessage Dlg::ToLF( std::string & s)
{
char CR = '\r';
char LF = '\n';
std::string CRLF = "\r\n";
// Problem: how can I replace multiple CRLF's in a string with just one LF?
// This is my naive attempt, which doesn't work:
//
std::replace_if (s.begin(),s.en d(),std::bind2n d(std::equal_to <std::string>() ,
CRLF),LF);

// Replace any CR's with a LF.

std::replace_if (s.begin(),s.en d(),std::bind2n d(std::equal_to <char>(),CR),LF )
;
}
Any comments/help would be appreciated.

Thankyou
Andrew

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Nov 17 '05 #1
15 3852
On Tue, 17 Feb 2004 09:27:30 -0500, Andrew Maclean wrote:
I guess this problem can be distilled down to: How do I search through a
string, find the first matching substring, replace it, and continue through
the string doing this. Can replace_if() be used to do this?

Here is a concrete example:
If I have a string with sequences of CRLF and possibly just CR's, is there a
simple way of replacing the CRLF characters with a LF?


I guess all examples using the STL would result in an O(N^2) algorithm, so
you would be better using an algorthm that can do it for you in linear
time. Something like this:
#include <iostream>
#include <string>
#include <vector>

using namespace std;
int main ()
{
string s = "I want to replace all occurancess oof a doubble cc with a sinngle cc x ccharacter. Is "
"that ook witcch you???";

cout<<s<<endl;

//Simple 2 pass procedure that does that in O(N) time.
std::vector<int > pos; //Record the position of the double c's to remove.

string::iterato r i = s.begin();
//Assume that the string is non-empty.

//Recording loop. We are sure that 3 c's can never be together?
while (!s.empty() && i != s.end()-1)
{
if (*i == 'c' and *(i+1) == 'c')
pos.push_back (i-s.begin()), *i = 'x';
++i;
}

//Removing loop.
std::vector<int >::iterator iter = pos.begin();
while (iter != pos.end())
{
//Move all characters between *iter and *(iter+1) left by
//(iter-pos.begin()+1) positions.
int Offset = (iter-pos.begin()+1);
int Start = *iter + 2;
int End = (iter+1 == pos.end()?s.siz e():*(iter+1) + 2);

while (Start != End)
s[Start-Offset] = s[Start], ++Start;
++iter;
}

s.erase (s.end()-pos.size(), s.end());
cout<<s<<endl;
}
It's fun writing programs like these! They are quite interesting for the
perceived simplicity at first sight!
Regards,
-Dhruv.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Nov 17 '05 #2
"Andrew Maclean" <it***@gok.co m> wrote in message
news:<c0******* **@spacebar.ucc .usyd.edu.au>.. .
I guess this problem can be distilled down to: How do I search through
a string, find the first matching substring, replace it, and continue
through the string doing this. Can replace_if() be used to do this?
No. The replace_if function can only replace single elements.
Here is a concrete example:
If I have a string with sequences of CRLF and possibly just CR's, is
there a simple way of replacing the CRLF characters with a LF? If you look at the function below is it possible to use a replace_if
to do this?


No.

I don't think that there is anything in the standard library which will
really help. I'd just write a simple loop, and do it by hand:

void
GeneralMessageD lg::toLF( std::string& s )
{
std::string result ;
size_t end = s.size() ;
size_t current = 0 ;
while ( current < end ) {
switch ( s[ current ] ) {
case '\n' :
case '\r' :
result += '\n' ;
current = s.find_first_no t_of( "\r\n", current ) ;
break ;

default :
result += s[ current ] ;
++ current ;
break ;
}
}
s.swap( result ) ;
}

IMHO, it is a lot simpler to generate to a new string, rather than
modifying in place.

I think that the Boost regex classes have something that will do exactly
what you want. I'd verify, but I'm stuck with a compiler too old to
handle Boost. But something like:

boost::regex_re place( std::back_inser ter( result ),
s.begin(),
s.end(),
boost::regex( "[\\n\\r]+" ),
"\n" ) ;

should do the trick, I think. Maybe someone who can actually use the
library can verify that I've got it right. And if you are doing this a
lot, you might want to declare the regular expression a static object,
so that it will only be constructed once. (It's probably premature
optimization and just guessing on my part, but I presume that
construction of a regular expression is a fairly expensive operation.)

--
James Kanze GABI Software mailto:ka***@ga bi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientier ter Datenverarbeitu ng
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Nov 17 '05 #3
"Andrew Maclean" <it***@gok.co m> wrote in message news:<c0******* **@spacebar.ucc .usyd.edu.au>.. .
I guess this problem can be distilled down to: How do I search through a
string, find the first matching substring, replace it, and continue through
the string doing this. Can replace_if() be used to do this?
No it can not, since it only replace a single element.
Here is a concrete example:
If I have a string with sequences of CRLF and possibly just CR's, is there a
simple way of replacing the CRLF characters with a LF?


If you know the file contains only CRLF you can simply do
last = std::remove(fir st, last, '\r');
That will leave the \n's.

Alternatively use this function:

template <typename _ForwardIter>
_ForwardIter replace_crlf (_ForwardIter first, _ForwardIter last)
{
_ForwardIter res = first;
while(first != last)
{
static const char crlf[] = { '\r', '\n' };
_ForwardIter eol = std::search(fir st, last, crlf + 0, crlf + 2);
res = std::copy(first , eol, res);
if(eol == last)
break;
*res++ = '\n';
first = eol;
std::advance(fi rst, 2);
}
return res;
}

A similar result could be achieved with std::unique with a custom
binary predicate function, but degenerate cases can be constructed
which will make it do the "wrong" thing, i.e. collapsing a "bad"
sequence like "\r\n\n\n" into only one character.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Nov 17 '05 #4
On 17 Feb 2004 09:27:30 -0500, "Andrew Maclean" <it***@gok.co m> wrote:
I guess this problem can be distilled down to: How do I search through a
string, find the first matching substring, replace it, and continue through
the string doing this. Can replace_if() be used to do this?


Not in general. In this case, your substring can be reduced to a single
char and bending the rules allows a solution. A predicate object is not
allowed to have state because the original may be copied more than once.
It is also not allowed to have side effects for no good general reason.
It must not change the sequence being processed for obvious reasons, but
other side effects are harmless.

The objective is to replace "\r\n" and '\r' with '\n'. What we need is
a predicate with memory of previous character. We can remove the '\n'
from the "\r\n" on pass one and replace all '\r' with '\n' on pass two.
To make the predicate usable, we contain a pointer to an external char
for the memory.

struct Pred {
char* pred;
Pred (char& pred) : pred(&pred) {
}
bool operator () (char cur) const {
bool result(cur == '\n' && *pred == '\r');
*pred = cur;
return result;
}
};

Now we can use that to remove_if some newlines and then use replace to
change the returns to newlines.

int main () {
string s("This is\r\na two line thing\rwith a third line\n");
char pred('\n'); // Anything other than '\r'
s.erase(remove_ if(s.begin(), s.end(), Pred(pred)), s.end());
assert(s == "This is\ra two line thing\rwith a third line\n");
replace(s.begin (), s.end(), '\r', '\n');
assert(s == "This is\na two line thing\nwith a third line\n");
}

John

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Nov 17 '05 #5
"Andrew Maclean" <it***@gok.co m> wrote in message news:<c0******* **@spacebar.ucc .usyd.edu.au>.. .
I guess this problem can be distilled down to: How do I search through a
string, find the first matching substring, replace it, and continue through
the string doing this. Can replace_if() be used to do this?
Given iterators, first and last, a predicate pred and a replace value,
new_value std::replace_if () performs the following:

For each iterator i in the range [first,last) if pred(*i) is true then
the assignment *i = new_value is performed.

Now the type of *i, and new_value is 'char' in your case. So you can
only replace a single characther by another in the string. Thus you
cannot replace a substring by another using replace_if(). To do this
it would be better to use the std::string member functions as follows:

const char* crlf = "\r\n";
std::string s("asb\r\nasdf\ r\n\r\nasd");
int index = s.find( crlf )
while (index != std::string::np os) {
s.replace( index, 2, "\r" );
index = s.find( crlf, index );
}
Here is a concrete example:
If I have a string with sequences of CRLF and possibly just CR's, is there a
simple way of replacing the CRLF characters with a LF?

In this specific case, you can use std::remove_if( ) to remove all CR's

std::string crlf("\r\n");
std::remove_if( crlf.begin(), crlf.end(),
std::bind2nd( std::equal_to<c har>(), '\r' ) );
HTH
~ aniket

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Nov 17 '05 #6
"Andrew Maclean" <it***@gok.co m> wrote in message news:<c0******* **@spacebar.ucc .usyd.edu.au>.. .
I guess this problem can be distilled down to: How do I search through a
string, find the first matching substring, replace it, and continue through
the string doing this. Can replace_if() be used to do this?

<snip>

I am of the opinion that a regular expression library is the most
correct way to do this. foreach with a lookahead and a functor-stored
result can also get you there in O(n) time if memory isn't a prob.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Nov 17 '05 #7
On 18 Feb 2004 16:21:01 -0500, ka***@gabi-soft.fr wrote:
I don't think that there is anything in the standard library which will
really help. I'd just write a simple loop, and do it by hand: void
/* Make it a free function for ease of testing GeneralMessageD lg:: */
toLF( std::string& s )
{
std::string result ;
size_t end = s.size() ;
size_t current = 0 ;
while ( current < end ) {
switch ( s[ current ] ) {
case '\n' :
case '\r' :
result += '\n' ;
current = s.find_first_no t_of( "\r\n", current ) ;
break ;

default :
result += s[ current ] ;
++ current ;
break ;
}
}
s.swap( result ) ;
}


int main () {
std::string s("\n\n\n\n\n\n \n\n\n"
"Where did my top margin go?\n\n\n");
toLF(s);
std::cout << s;
}

John

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Nov 17 '05 #8
On Wed, 18 Feb 2004 16:21:01 -0500, kanz wrote:
"Andrew Maclean" <it***@gok.co m> wrote in message
news:<c0******* **@spacebar.ucc .usyd.edu.au>.. .
I guess this problem can be distilled down to: How do I search through
a string, find the first matching substring, replace it, and continue
through the string doing this. Can replace_if() be used to do this?


No. The replace_if function can only replace single elements.
Here is a concrete example:
If I have a string with sequences of CRLF and possibly just CR's, is
there a simple way of replacing the CRLF characters with a LF?

If you look at the function below is it possible to use a replace_if
to do this?


No.

I don't think that there is anything in the standard library which will
really help. I'd just write a simple loop, and do it by hand:


How about this horribly inefficient algorithm that uses the STL. I can not
see anything majorly wrong with this?

#include <iostream>
#include <string>
#include <vector>

using namespace std;
int main ()
{
string s = "I want to replace all occurancess oof a doubble cc with a sinngle cc x ccharacter. Is "
"that ook witcch you???";

cout<<s<<endl;

string::size_ty pe pos = 0;

pos = s.find ("cc", pos);

while (pos != string::npos)
//I don't know why s::npos does not work? Any ideas anyone? Maybe there is
//something wrong with the way I have understood what npos is?
{
s.replace (pos, 2, 1, 'x');
pos = s.find ("cc", pos+1);
}
cout<<s<<endl;
}

--
Regards,
-Dhruv.

Proud to be a Vegetarian.
http://www.vegetarianstarterkit.com/
http://www.vegkids.com/vegkids/index.html
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Nov 17 '05 #9
On 20 Feb 2004 16:14:14 -0500, "Dhruv Matani" <dh*******@gmx. net> wrote:
while (pos != string::npos)
//I don't know why s::npos does not work? Any ideas anyone? Maybe there is
//something wrong with the way I have understood what npos is?


It is a static size_type const data member of string.

assert(string:: npos == s.npos);

John

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.m oderated. First time posters: Do this! ]
Nov 17 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
1227
by: Adam Hartshorne | last post by:
Hi All, I have an interesting problem with the aforementioned IDE. I am using an external library, wildmagic to be precise. I was using version 2 of this library and have just moved to version 3. Ok so I changed the paths to point at version 3, and deleted all source, header, lib and dll files for version 2. To my surprise when I do the . the list of methods available is still
1
1768
by: jrmsmo | last post by:
Hi there, I have an interesting problem that maybe you pros can suggest how I solve. I'm working with a third party program that serializes an XML document (it was obviously not designed with schema in mind). I created a schema from this document. It works fine. Except for some unknown reason, in a small part of the XML document, this program switches the order around, and of course the validator I built then fails. Its always the same two...
0
1267
by: raza | last post by:
Hi, I have been programmin in C# for quite some time now and recently got into sockets programming in C# though i have done it in C++ on windows/linux . I have an interesting problem at hand . I am porting a C++ tunnel library into C# . It has 2 functions WriteOut: I make a header and send it then send the actual data to the server and it calls Write function
3
2826
by: Sabari | last post by:
Hi, I have an interesting problem in DataGrid.I have a footer in the Datagrid which has a textbox and a link button and im adding values to the grid.Everything seems to work fine until this point.After adding the value i bind the data to control.now if refresh my browser the value that i added recently gets added again.This happens everytime i refresh the same page. Im adding the values in the grids Itemcommand by finding out the...
0
420
by: Andrew Maclean | last post by:
I guess this problem can be distilled down to: How do I search through a string, find the first matching substring, replace it, and continue through the string doing this. Can replace_if() be used to do this? Here is a concrete example: If I have a string with sequences of CRLF and possibly just CR's, is there a simple way of replacing the CRLF characters with a LF? If you look at the function below is it possible to use a replace_if...
2
1246
by: Michael Sutherland | last post by:
Here's an interesting problem I've come across. I'm writing a program that essentially generates random strings (its a simulator of the game Boggle) and sends them to a function that does a binary search on a word list to see if that string is listed. However, at seemingly random intervals (I've seen it happen on everything from a few dozen calls to the function to a few thousand) I get a system.stackoverflowexception. I'm assuming I've...
1
1827
by: Steve Lutz | last post by:
I have written a web service to provide some back-end functionality to a Web Site. The web service returns lists of items. If I use the webservice via a browser, it works fine and returns the results in XML. I then created the proxy for the Web Service in VS.NET. I can call the webmethod fine and get an array of Items. (Although it's a local class to the WebSite). When I attempt to have a repeater control list the reults in a web form,...
7
1767
by: manas312 | last post by:
Hey guys.... I'm facing an interesting problem ....and need some solution..... The problem goes like this. You r having one site like www.abc.com (for example). The website contains only one textbox....blank textbox. Now I have a database of names of people. I hv control over database. I hv another site containing only one 'button'. (for ex. www.xyz.com) It acts as an interface site.(not exactly interface...but kinda)
1
1210
by: manas312 | last post by:
Hey guys.... I'm facing an interesting problem ....and need some solution..... The problem goes like this. You r having one site like www.abc.com (for example). The website contains only one textbox....blank textbox. Now I have a database of names of people. I hv control over database. I hv another site containing only one 'button'. (for ex. www.xyz.com) It acts as an interface site.(not exactly interface...but kinda)
11
1584
by: onkar.n.mahajan | last post by:
Is it possible to from function call on fly in C programming language ? I am faced with an interesting problem in that I need to take function name and arguments on fly (actually from Database as string ) and form a function call based on that ? something like FUN_NAME="fun1" , ARGS ="arg1,arg2,arg3" , for this pair function call must be
0
9837
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10850
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10941
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9656
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
7185
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
6074
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4698
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4293
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3300
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.