有趣的std :: replace_if问题 [英] Interesting std::replace_if problem
问题描述
我想这个问题可以归结为:我如何搜索
字符串,找到第一个匹配的子字符串,替换它,并继续通过
做这个的字符串。可以用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屋!