Click to See Complete Forum and Search --> : Maybe I'm just not seeing something....


JamesSchumacher
April 20th, 2003, 05:17 PM
Trying to recode my Replaced() member function of my ApxString class to replace in a new buffer instead of in place for speed purposes, here's the code for that function. I put a printf() in here to illustrate a problem I'm having. main() code is first - I'm using Dev C++ with GCC 3.2 if it turns out to be a compiler bug.


int main(int argc, char *argv[])
{
ApxString myString("James James James James James Schumacher");
myString.Replace("James James James James James","James");
system("PAUSE");
return 0;
}

That spits out this:

0 30 31 32 33 34 35 36 37 38 39

If I print out the contents of the string after the replace, it's just "James" without the end.

Relevant because of where I put the the printf() in replace. Here is that function:


unsigned long ApxString::Replace(const char * pStrOld,const char * pStrNew) throw()
{
unsigned long dwStringsReplaced(0);
if (pStrOld != 0 && pStrNew != 0)
{
const unsigned long dwOldLen = ::ApxStringLen<char>(pStrOld);
if (dwOldLen != 0)
{
const unsigned long dwNewLen = ::ApxStringLen<char>(pStrNew);
if (dwNewLen != 0)
{
const unsigned long dwStrLen = GetLength();
if (dwOldLen <= dwStrLen)
{
// count how many substrings we have
unsigned long dwSubStringCount(0);
unsigned long dwCharsCounted(0);
bool bDone(false);
for (unsigned long x = 0; x < dwStrLen; ++x)
{
for (unsigned long y = 0; y < dwOldLen; ++y)
{
if (m_pStrData[x + y] == pStrOld[y])
{
++dwCharsCounted;
if (dwCharsCounted == dwOldLen)
{
++dwSubStringCount;
if (x + dwOldLen >= dwStrLen)
{
bDone = true;
}
dwCharsCounted = 0;
break;
}
}
else
{
dwCharsCounted = 0;
break;
}
}
if (bDone == true)
{
break;
}
else if (x + dwOldLen >= dwStrLen)
{
break;
}
}
// Are there any substrings to replace?
if (dwSubStringCount != 0)
{
// check the buffer size we need....
unsigned long dwTempLen = dwStrLen;
dwTempLen -= (dwOldLen * dwSubStringCount);
dwTempLen += (dwNewLen * dwSubStringCount);
const unsigned long dwAlloc = ::ApxDetermineBufferSize(dwTempLen);
// allocate a temporary buffer
char * pTempData = new char[dwAlloc];
if (pTempData != 0)
{
// reuse dwCharsCounted and bDone
dwCharsCounted = 0;
bDone = false;
for (unsigned long t = 0,z = 0; t < dwStrLen; ++t,++z)
{
::printf("%lu ",t);
pTempData[z] = m_pStrData[t];
if (bDone == false)
{
for (unsigned long u = 0; u < dwOldLen; ++u)
{
if (m_pStrData[t + u] == pStrOld[u])
{
++dwCharsCounted;
if (dwCharsCounted == dwOldLen)
{
// found one, copy the new string into the old spot
for (unsigned long p = 0; p < dwNewLen; ++p,++z)
{
pTempData[z] = pStrNew[p];
}
++dwStringsReplaced;
if (t + dwOldLen >= dwStrLen)
{
bDone = true;
}
else
{
t += dwOldLen;
}
dwCharsCounted = 0;
break;
}
}
else
{
dwCharsCounted = 0;
break;
}
}
}
}
// done....
pTempData[dwTempLen] = 0;
delete [] m_pStrData;
m_pStrData = pTempData;
m_dwBufferSize = dwAlloc;
}
}
}
}
}
}
return dwStringsReplaced;
}


I may be tired or something - am I missing something, a simple logic error, or compiler bug

JamesSchumacher
April 20th, 2003, 05:32 PM
If someone can help me fix it. I'm trying to rewrite V3 of ApxString again (since I lost the source code) before finishing V4 - in the process making it with GCC since it's going to be GNU'ed when it's done. Class is incomplete, but mostly functional. I'm trying to keep this class as independent as possible - it's purpose is to be a lightweight portable string class - including embedded systems, so outside library code is out of the question.

JamesSchumacher
April 22nd, 2003, 06:00 PM
I was WAY OFF, must of been on one of those bad days or something..... Anyway, here's the fixed code to see how FAR I was off.


unsigned long ApxString::Replace(const char * pStrOld,const char * pStrNew) throw()
{
unsigned long dwStringsReplaced(0);
if (pStrOld != 0 && pStrNew != 0)
{
const unsigned long dwOldLen = ::ApxStringLen<char>(pStrOld);
if (dwOldLen != 0)
{
const unsigned long dwNewLen = ::ApxStringLen<char>(pStrNew);
if (dwNewLen != 0)
{
const unsigned long dwStrLen = GetLength();
if (dwOldLen <= dwStrLen)
{
// count how many substrings we have
unsigned long dwSubStringCount(0);
unsigned long dwCharsCounted(0);
bool bDone(false);
for (unsigned long x = 0; x < dwStrLen; ++x)
{
for (unsigned long y = 0; y < dwOldLen; ++y)
{
if (m_pStrData[x + y] == pStrOld[y])
{
++dwCharsCounted;
if (dwCharsCounted == dwOldLen)
{
++dwSubStringCount;
if (x + dwOldLen >= dwStrLen)
{
bDone = true;
}
dwCharsCounted = 0;
break;
}
}
else
{
dwCharsCounted = 0;
break;
}
}
if (bDone == true)
{
break;
}
else if (x + dwOldLen >= dwStrLen)
{
break;
}
}
// Are there any substrings to replace?
if (dwSubStringCount != 0)
{
// check the buffer size we need....
unsigned long dwTempLen = dwStrLen;
dwTempLen -= (dwOldLen * dwSubStringCount);
dwTempLen += (dwNewLen * dwSubStringCount);
const unsigned long dwAlloc = ::ApxDetermineBufferSize(dwTempLen);
// allocate a temporary buffer
char * pTempData = new char[dwAlloc];
if (pTempData != 0)
{
// reuse dwCharsCounted and bDone
dwCharsCounted = 0;
bool bFound;
unsigned long dwCurrentIndex(0),dwBufferIndex(0),dwFoundIndex(0);
for (unsigned long p = 0; p < dwSubStringCount; ++p)
{
bFound = false;
// find the string
for (unsigned long t = dwCurrentIndex; t < dwStrLen; ++t)
{
for (unsigned long u = 0; u < dwOldLen; ++u)
{
if (m_pStrData[t + u] == pStrOld[u])
{
++dwCharsCounted;
if (dwCharsCounted == dwOldLen)
{
dwFoundIndex = t;
bFound = true;
break;
}
}
else
{
pTempData[dwBufferIndex] = m_pStrData[dwCurrentIndex];
++dwBufferIndex;
++dwCurrentIndex;
dwCharsCounted = 0;
break;
}
}
if (bFound == true)
{
// found the string, copy chars up until that index
for (unsigned long j = 0; j < dwFoundIndex - dwCurrentIndex; ++j,++dwCurrentIndex,++dwBufferIndex)
{
pTempData[dwBufferIndex] = m_pStrData[dwCurrentIndex];
}
// copy the new string into the buffer
for (unsigned long a = 0; a < dwNewLen; ++a,++dwBufferIndex)
{
pTempData[dwBufferIndex] = pStrNew[a];
}
// add the old len to dwCurrentIndex
dwCurrentIndex += dwOldLen;
// 0 dwCharsCounted
dwCharsCounted = 0;
break;
}
}
}
// copy any chars left after
for (unsigned long lm = 0; lm < dwStrLen - (dwFoundIndex + dwOldLen); ++lm,++dwBufferIndex,++dwCurrentIndex)
{
pTempData[dwBufferIndex] = m_pStrData[dwCurrentIndex];
}
pTempData[dwTempLen] = 0;
delete [] m_pStrData;
m_pStrData = pTempData;
m_dwBufferSize = dwAlloc;
dwStringsReplaced = dwSubStringCount;
}
}
}
}
}
}
return dwStringsReplaced;
}


I benchmarked the Replace() function on my 1.6 GHZ Athlon, here's the code I used.


#include <iostream>
#include <stdlib.h>
#include <string>
#define __APXSTRING_INCLUDE_STDSTRING__
#include "ApxString.h"

std::ostream & operator << (std::ostream & o,const ApxString & str) throw()
{
o << str.GetString();
return o;
}

std::istream & operator >> (std::istream & istr,ApxString & str) throw()
{
char szTemp[256];
istr.getline(szTemp,sizeof(szTemp),'\n');
str.Assign(szTemp);
return istr;
}

int main(int argc, char *argv[])
{
const char * pString = "abcdefghijklmnopqrstuvwxyz";
const char * pReplace = "ABC";
ApxString myString((unsigned long)26001);
unsigned long dwBefore = ::GetTickCount();
for (unsigned long x = 0; x < 10000; ++x)
{
myString.Append(pString);
}
unsigned long dwAfter = ::GetTickCount();
std::cout << "Length is: " << myString.GetLength() << std::endl;
std::cout << "Appending took " << dwAfter - dwBefore << " ticks." << std::endl;
dwBefore = ::GetTickCount();
myString.Replace(pString,pReplace);
dwAfter = ::GetTickCount();
std::cout << "Length is: " << myString.GetLength() << std::endl;
std::cout << "Replaced in: " << dwAfter - dwBefore << " ticks." << std::endl;
system("PAUSE");
return 0;
}


Spit out this:

Length is 260000
Appending took 13672 ticks.
Length is 30000
Replaced in: 15 ticks.