有趣的std :: replace_if问题 [英] Interesting std::replace_if problem

查看:74
本文介绍了有趣的std :: replace_if问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想这个问题可以归结为:我如何搜索

字符串,找到第一个匹配的子字符串,替换它,并继续通过

做这个的字符串。可以用replace_if()来做这个吗?


这是一个具体的例子:

如果我有一个包含CRLF序列的字符串,可能只是CR'是的,是否有一个用LF替换CRLF字符的简单方法?


如果你看下面的函数是否可以使用replace_if要做什么

这个?

void CGeneralMessageDlg :: ToLF(std :: string& s)

{

char CR =''\ r'';

char LF =''\ n'';

std :: string CRLF =" \ r \ n" ;;

//问题:如何用一个LF替换字符串中的多个CRLF?

//这是我天真的尝试,这不起作用:

//

std :: replace_if(s.begin(),s.end(),std :: bind2nd(std: :equal_to< std :: string>(),

CRLF),LF);


//用LF替换任何CR'。 br />

std :: replace_if(s.begin(),s.end(),std :: bind2nd(std :: equal_to< cha r>(),CR),LF)

;

}

任何评论/帮助将不胜感激。


谢谢你

Andrew


[见 http://www.gotw.ca/resources/clcm.htm 有关的信息]

[comp.lang.c ++。主持。第一次海报:做到这一点! ]

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 CGeneralMessageDlg::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.end(),std::bind2nd(std ::equal_to<std::string>(),
CRLF),LF);

// Replace any CR''s with a LF.

std::replace_if(s.begin(),s.end(),std::bind2nd(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++.moderated. First time posters: Do this! ]

推荐答案

2004年2月17日星期二09:27:30 -0500,Andrew Maclean写道:
On Tue, 17 Feb 2004 09:27:30 -0500, Andrew Maclean wrote:
我想这个问题可以归结为:我如何搜索
字符串,找到第一个匹配的子字符串,替换它,并继续执行这个字符串。可以用replace_if()来做这个吗?

这是一个具体的例子:
如果我有一个包含CRLF序列的字符串,可能只是CR',那么是否有一个
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?



我猜所有使用STL的例子都会产生O(N ^ 2)算法,所以

你会更好地使用algorthm来为你做线性

时间。这样的事情:

#include< iostream>

#include< string>

#include< vector>


使用命名空间std;

int main()

{

string s ="我想要替换所有出现的双重cc与一个单词cc x字符。是

,这对你来说是一个什么?" ;;


cout<< s<< endl;


//在O(N)时间执行此操作的简单2传递过程。

std :: vector< int> POS机; //记录要移除的双c'的位置。


string :: iterator i = s.begin();

//假设该字符串是非空的。


//录制循环。我们确定3 c'永远不会在一起吗?

while(!s.empty()& i!= s.end() - 1)

{

if(* i ==''c''和*(i + 1)==''c'')

pos.push_back( is.begin()),* i =''x'';

++ i;

}


/ /删除循环。

std :: vector< int> :: iterator iter = pos.begin();

while(iter!= pos.end())

{

//将* iter和*(iter + 1)之间的所有字符移动到

//(iter-pos.begin( )+1)位置。

int Offset =(iter-pos.begin()+ 1);

int Start = * iter + 2;

int End =(iter + 1 == pos.end()?s.size():*(iter + 1)+ 2);


while(开始! =结束)

s [Start-Offset] = s [开始],++开始;

++ iter;

}


s.erase(s.end() - pos.size(),s.end());

cout<< s<< endl;

}

编写像这样的程序很有趣!它们非常有趣,因为它们一见钟情就足够了!

问候,

-Dhruv。



[见 http://www.gotw.ca /resources/clcm.htm 有关的信息]

[comp.lang.c ++。moderated。第一次海报:做到这一点! ]



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::iterator 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.size():*(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++.moderated. First time posters: Do this! ]


" Andrew Maclean" <它*** @ gok.com>在消息中写道

news:< c0 ********* @ spacebar.ucc.usyd.edu.au> ...
"Andrew Maclean" <it***@gok.com> wrote in message
news:<c0*********@spacebar.ucc.usyd.edu.au>...
我想这个问题可以归结为:我如何搜索字符串,找到第一个匹配的子字符串,替换它,并继续通过字符串执行此操作。可以使用replace_if()来做到这一点吗?


编号replace_if函数只能替换单个元素。

这是一个具体的例子:
如果我有一个包含CRLF序列的字符串并且可能只是CR',是否有一种用LF替换CRLF字符的简单方法?
如果你看下面的函数是否可以使用replace_if
来做这个?
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.


我不认为标准库中有什么东西会给你带来很多帮助。我只想写一个简单的循环,并手工完成:


void

GeneralMessageDlg :: toLF(std :: string& s)

{

std :: string result;

size_t end = s.size();

size_t current = 0;

while(当前< end){

开关(s [当前]){

case''\ n'' :

case''\ r'':

结果+ =''\ n'';

current = s.find_first_not_of (\\ nn,当前);

休息;


默认值:

结果+ = s [当前];

++当前;

休息;

}

}

s.swap(结果);

}


恕我直言,生成新字符串要简单得多,而不是

到位修改。


我认为Boost正则表达式类有一些东西可以完全按照你想要的那样完成。我会验证,但是我被一个太老的编译器困住了

处理Boost。但是类似的东西:


boost :: regex_replace(std :: back_inserter(result),

s.begin(),

s.end(),

boost :: regex(" [\\\\
\\ r] +"),

" \\我认为,
应该可以解决这个问题。\\ n;

也许有人可以真正使用

库来验证我是否已经做对了。如果你这样做了很多,你可能想要将正则表达式声明为静态对象,

以便它只构造一次。 (这可能是不成熟的优惠而且只是猜测我,但我认为

正则表达式的构造是一个相当昂贵的操作。)


-

James Kanze GABI软件mailto:ka *** @ gabi-soft.fr

Conseils eninformatiqueorientéeobjet/ < a rel =nofollowhref =http://www.gabi-soft.frtarget =_ blank> http://www.gabi-soft.fr

Beratung in objektorientierter Datenverarbeitung

11 rue de Rambouillet,78460 Chevreuse,France,+ 33(0)1 30 23 45 16


[见 http://www.gotw.ca/resources/clcm.htm 了解有关的信息]

[comp.lang.c ++。版主。第一次海报:做到这一点! ]



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
GeneralMessageDlg::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_not_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_replace( std::back_inserter( 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***@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
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++.moderated. First time posters: Do this! ]


" Andrew Maclean" <它*** @ gok.com>在消息新闻中写道:< c0 ********* @ spacebar.ucc.usyd.edu.au> ...
"Andrew Maclean" <it***@gok.com> wrote in message news:<c0*********@spacebar.ucc.usyd.edu.au>...
我想这个问题可以归结为:如何我搜索一下
字符串,找到第一个匹配的子字符串,替换它,然后继续执行这个字符串。可以使用replace_if()来做到这一点吗?


不,它不能,因为它只替换单个元素。

这是一个具体的例子:
如果我有一个序列的字符串CRLF和可能只是CR',是否有一种用LF替换CRLF字符的简单方法?
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?




如果您知道该文件包含你只能做CRLF

last = std :: remove(first,last,''\ r'');

这将留下\ n'可以使用此功能:


模板< typename _ForwardIter>

_ForwardIter replace_crlf(_ForwardIter首先,_ForwardIter last)

{

_ForwardIter res = first;

while(first!= last)

{

static const char crlf [] = {''\ r'',''\ n''};

_ForwardIter eol = std :: search( first,last,crlf + 0,crlf + 2);

res = std :: copy(first,eol,res);

if(eol == last)

休息;

* res ++ =''\ n'';

first = eol;

std :: advance(first,2);

}

返回res;

}


使用自定义
二元谓词函数,但可以构造退化情况

这将使它做错误事情,即崩溃坏

序列,如\\\\\ n只有一个字符。


[见 http://www.gotw.ca/resources/clcm.htm 了解有关的信息]

[comp.lang.c ++。moderated。第一次海报:做到这一点! ]



If you know the file contains only CRLF you can simply do
last = std::remove(first, 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(first, last, crlf + 0, crlf + 2);
res = std::copy(first, eol, res);
if(eol == last)
break;
*res++ = ''\n'';
first = eol;
std::advance(first, 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++.moderated. First time posters: Do this! ]


这篇关于有趣的std :: replace_if问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆