|
The solutions posted above suffer from bugs (e.g. infinite loops) due to two conceptual errors:
1. The work must be separated into two passes. The first pass finds and stores the positions of any instances of the old string, and the second pass does the substitutions.
2. The substitutions must be done in reverse order, so that the stored indices remain stable despite deletions and insertions.
int ReplaceNoCase(CString& str, LPCTSTR pszOld, LPCTSTR pszNew)
{
CString sDest(str);
CString sOld(pszOld);
sDest.MakeLower();
sOld.MakeLower();
int nOldLen = sOld.GetLength();
CDWordArray arrSub;
int iPos = 0;
while ((iPos = sDest.Find(sOld, iPos)) >= 0) {
arrSub.Add(iPos);
iPos += nOldLen;
}
int nSubs = static_cast<int>(arrSub.GetSize());
for (int iSub = nSubs - 1; iSub >= 0; iSub--) {
str.Delete(arrSub[iSub], nOldLen);
str.Insert(arrSub[iSub], pszNew);
}
return nSubs;
}
The MFC implementation also does two passes, though it's much more complicated due to its fancy optimizations. The code above isn't as fast as CString::Replace but it gets the job done without bugs.
|
|
|
|
|
Sooo lange gesucht, auf CP gefunden .
Danke !!!
|
|
|
|
|
Gerne doch
|
|
|
|
|
Regex is faster and better
|
|
|
|
|
...is to use Regex.Replace with the IgnoreCase option.
|
|
|
|
|
hi,
for one of my application, i used this code.but when i run this code without UNICODE,_UNICODE setting this function work fine but when i change setiing to UNICODE this function does not take overall string as there arguments.it only take only one character. can you help me on that.
how can i run this code on UNICODE setting.
Plz help me.
Thanks
Pankaj Jain
|
|
|
|
|
While I was making some slight modifications to this for a project I was working on, I made some modifications that ended up working faster. The basic gist is that instead of performing the replace in the old string and the new string, I keep some extra track of positions so that I only need to do the replace in the main string. There was about a 27% gain in speed with this version compared to the original when I tested it (I ran it on a fairly large string 1000 times for each function). Sorry for the minor differences in parameters and such, this way suited my needs better.
void newReplace2(CString& mainStr, CString& oldStr, CString& newStr)<br />
{<br />
if (oldStr != "")<br />
{<br />
int oldLen = oldStr.GetLength(), newLen = newStr.GetLength();<br />
int nPos = 0, lastPos = 0, newPos = 0, posDiff = 0;<br />
<br />
CString mainStr_low(mainStr);<br />
CString oldStr_low(oldStr);<br />
mainStr_low.MakeLower();<br />
oldStr_low.MakeLower();<br />
<br />
while ((nPos = mainStr_low.Find(oldStr_low, nPos)) != -1)<br />
{<br />
posDiff = nPos - lastPos;<br />
<br />
newPos += posDiff;<br />
<br />
mainStr.Delete(newPos, oldLen);<br />
mainStr.Insert(newPos, newStr);<br />
<br />
nPos += oldLen;<br />
newPos += newLen;<br />
lastPos = nPos;<br />
}<br />
}<br />
}
|
|
|
|
|
Just wanted to let you know I'm using it in my latest project for a SPAM reporting tool and reverse DNS blacklist. Thanks for saving me some time!
Sam
http://www.spamthwart.com
Spam Thwart
Realtime SPAM DNS Blacklist and reporting tool
-- modified at 23:39 Tuesday 15th November, 2005
|
|
|
|
|
Hmm... I'm a C++ newbie here... :P
Look, I put this at the top of my program, in the function declarations part:
CString ReplaceNoCase( LPCTSTR instr, LPCTSTR oldstr, LPCTSTR newstr );
And that gives me an error, so I replace LPCTSTR with char*, and that gives me 26 errors! I get something about "std" not being a a namespace or something, and I think the rest of the errors are based on this... What do I do? Sorry, this is my 2nd day using C++... Thanks!
Sulfurik K. Nosferathus (Darth_Sulfur)
www.SulfurMidis.com
www.SulfurSoft.tk
http://www.BeepXtreme.tk
[ftp://][http://][hotline://]tsfc.ath.cx
|
|
|
|
|
This code relies on MFC, are you building an MFC app ?
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
|
MFC is a class library that is included with Visual Studio. Not all VC projects are MFC, but this one sure is, CString is the MFC string class.
You're going to find it rough going if you don't have VC - most of the projects on this site in C++ probably use MFC.
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
Ooohh...
Well, I once bought VS .NET Everett (the 2003 beta) on a thrift store for like 2 dollars... It's the "Enterprise Architect" version. Does the C++ included with that the same as VC++ 6? Does MFC come with it? Does it make native Windows EXE's and not .NET? Thanks!
Sulfurik K. Nosferathus (Darth_Sulfur)
www.SulfurMidis.com
www.SulfurSoft.tk
http://www.BeepXtreme.tk
[ftp://][http://][hotline://]tsfc.ath.cx
|
|
|
|
|
Darth_Sulfur wrote:
Well, I once bought VS .NET Everett (the 2003 beta) on a thrift store for like 2 dollars...
I doubt it would run now, if it's the beta. The 2005 beta is pretty easy to get tho.
Darth_Sulfur wrote:
Does the C++ included with that the same as VC++ 6?
No, it's tons better. It's chalk and cheese. From 2002, Microsoft did major work on standards compliance.
Darth_Sulfur wrote:
Does MFC come with it?
Yes.
Darth_Sulfur wrote:
Does it make native Windows EXE's and not .NET?
It does both in C++.
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
|
If there's no download, Microsoft are certainly sending DVDs to every user group around, find a user group and get one.
Remember, it's a beta, it will expire, and costs a fair amount to buy, although I think there's one that's C++ only that is a lot cheaper, and still has MFC.
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
I needed a case insensitive string replace and made a Google search for a CString algorithm. This was the only place I found. I have no speed problem as I am searching relatively short strings (database entries with up to 15 characters - not speed critical).
However, the original code gets into an endless loop in the following examples:
inst = "nnn"
oldstr = "n"
newstr = "N"
output should be "NNN"
inst = "can"
oldstr = "n"
newstr = "nnot"
output should be "cannot"
Please test the following version. I think it solves the problems but I have not tested all the possibilities:
CString ReplaceNoCase( LPCTSTR instr, LPCTSTR oldstr, LPCTSTR newstr )
{
CString output( instr );
// lowercase-versions to search in.
CString input_lower( instr );
CString oldone_lower( oldstr );
input_lower.MakeLower();
oldone_lower.MakeLower();
// search in the lowercase versions,
// replace in the original-case version.
int pos=0;
for (;;)
{
pos=input_lower.Find(oldone_lower,pos);
if (pos == -1)
break;
// need for empty "newstr" cases.
input_lower.Delete( pos, lstrlen(oldstr) );
input_lower.Insert( pos, newstr );
// actually replace.
output.Delete( pos, lstrlen(oldstr) );
output.Insert( pos, newstr );
pos += strlen(newstr);
}
return output;
}
Peter M.C. Werner
www.cadelec.com
|
|
|
|
|
This is the better way to do it for sure, the original in buggy. Cool, thanks!
|
|
|
|
|
Try replacing "n" with "nWaterFilteringPlant". It will enter in an endless loop. Although I have not tested it under all circumstances, I think it should be written
if ( (pos=input_lower.Find(oldone_lower,pos))!=-1 ) {
// need for empty "newstr" cases.
// input_lower.Delete( pos, lstrlen(oldstr) );
// input_lower.Insert( pos, newstr );
// actually replace.
output.Delete( pos, lstrlen(oldstr) );
output.Insert( pos, newstr );
}
|
|
|
|
|
I find that MakeLower() sometime don't work. Who can tell me why?
VC6 with sp5.
|
|
|
|
|
If you replace "MyString" with "MyString2"
you fall into an infinite loop...
|
|
|
|
|
Sorry, it was a mistake from me, not a bug!
It works as it should, I thing!
|
|
|
|
|
"lstrlen(oldstr)" is constant -> out of while operation
|
|
|
|
|
Sounds reasonable - but do you really wanna get your compiler's optimizer getting unemployed?
--
See me: www.magerquark.de
|
|
|
|
|
Hi,
It´s good, to have that type of algorithm, but I guess using CString class, can be not so ok if you have to do that replace on a big file for example ( better to go down, and have some headache with the str... and buffer manipulating and all that sh..., I have seen what makes CString for some operation and is not so optimized... take a look at CString in a NutShell article ).
Anyway good work, Bye !
Braulio
|
|
|
|