Question

replace function efficiency

Asked by: sizak

Hey guys need a lil help/opinion on this.  this code is being used and heres the senario.. find and replace a tag in a body of text.  now its alright for small things but try when it has to do it 3 million times over and over replacing it once or up to 25 times.  heres the replace function right now


str is the buffer(text), code is the tag in the text and then val is what needs to be in place of the code.. an example of the function in use is

res=replace(res,"%%CODE%%",zak);

so %%CODE%% would be replaced with zak and then return'd.


char * replace(char * str,char *code,char * val){
  char * needle;
  char * tmpstr;
  bool changed;

  tmpstr=(char *) malloc(strlen(str)+strlen(val)*4086);

  changed=true;
  while(changed ) {
    changed=false;
    needle=strstr(str,code);
      if (needle!=NULL) {
       changed=true;
       memcpy(tmpstr,str,needle-str);
       tmpstr[needle-str]=0;
       strcat(tmpstr,val);
       strcat(tmpstr,needle+strlen(code));
       strcpy(str,tmpstr);
    };
  };
  free(tmpstr);

  return str;
};



this would be a HUGE help to me thanks guys

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2003-07-09 at 12:03:20ID20673493
Tags

char

,

malloc

Topic

C Programming Language

Participating Experts
6
Points
500
Comments
27

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. strlen & strcpy
    Hello all I have posted my code here i know it is riddled with errors but i need help in telling me what is wrong with the lines len = strlen(word); and strncpy(solution,STARS,len); and how can I overcome this problem #include <stdio.h> #include<ctype.h...
  2. malloc doesn't work with a CSV file?
    I'm trying to read in value from a CSV file and dynamically allocate them in memory. I'm using an array of pointers to pointers. char **field - holds column headers char **value - holds line values When the functions 'parse_firstline' and 'parse_lines' are called they ...
  3. Used malloc in a function to return a pointer to a string.
    Assume a function like this ... char *ConvertTriplet(const char* sTriplet, int iTripletCounter, int iTripletCount) { char *sTripletWords; sTripletWords = (char *)malloc(1025); sTripletWords[0] = 0; // Do something with sTripletWords. return sTripletWords; } ...
  4. segmentation fault on malloc
    Hi, I started using some propritory linux distribution (which is based on RedHat) about three days ago. I have copied some c++ programs which I was working on from my personal RedHat 8.0 machine, but somethings seems to be wrong. The programs compile perfectly but wh...

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: gj62Posted on 2003-07-09 at 12:59:51ID: 8888432

Hi sizak,

Most of your time is probably spent on the actual search (let me know if that's incorrect).  If you are using strstr(), you can get significant improvement using Boyer-Moore search algo.  Here's the best link I know (which has some source)...

http://www-igm.univ-mlv.fr/~lecroq/string/node14.html

Obviously, I'm assuming you need to do this in C - there are existing tools out there that can do this (though generally they have not been optimized for exact string searches)...

Cheers!

 

by: grg99Posted on 2003-07-09 at 13:11:13ID: 8888529

Here's some general hints:

Save a ton of memory and copying by making the changes in-place.  You can do it if
you first scan the text for your pattern and just record those places (can even be done right
in the text if the pattern is long enough.  Then go back and make the changes.  If the
replacement string is longer than the original, you'll have to grow the memory bloack and process the text backwards,  otherwise process it forwards.  This saves a ton of string moves and temporaries and copies.

Search for the least likely character in your search string.  This will give you the fewest false hits.

Don't restore the whole buffer after each replace, just copy the minimum needed.

If the outptu text is going into some sequential consumer task, then you can optimize things even more
by passing on the data without ever having actually made a complete copy of it.

Hope this helps,


grg99


 

by: sizakPosted on 2003-07-09 at 13:19:29ID: 8888613

the data it returns is then dumped out and then sent over a tcp/ip connection.  my main problem is the search speed.  if you could create the code for it i'd love you guys even more :)

 

by: sizakPosted on 2003-07-09 at 13:20:24ID: 8888625

btw, the programmer who built this was killed in a car accident a year or so ago.. I can do some coding 2 years of college stuff but not really to indepth info on c/c++ so i'm dumbfound on this.

 

by: cgi-binPosted on 2003-07-09 at 14:49:18ID: 8889322

/*
 * I didn't do any extensive testing, but it seems to do the job.
 */

#include <stdio.h>
#include <string.h>
#include <malloc.h>

char *replace (char *haystack, char *needle, char *value)
{
    register char *p, *q, *s, *t;
    register int count;
    register int needlelen = strlen (needle);
    register int valuelen = strlen (value);
    register int delta, newlen;
    register int remainlen = 0;
    char *newbuf = NULL;

    /* First, count the occurences of needle */

    for (count = 0, p = haystack; (q = strstr (p, needle)) != NULL; p = q + needlelen, count++)
        ;

    /* Get number of characters from last needle we found to end of string.  We
     * need this later.
     */

    remainlen = strlen (p);

    /* Compute new buffer size */

    if (count > 0) {

        newlen = strlen (haystack) + (count * strlen (value) - count * needlelen);

        /* Allocate memory for new buffer */

        if ((newbuf = malloc (newlen + 1)) != NULL)
        {
            memset (newbuf, '\0', newlen + 1);

            for (s = p = haystack, t = newbuf; (q = strstr (p, needle)) != NULL; )
            {
                memcpy (t, s, q - s);
                t += (q - s);
                memcpy (t, value, valuelen);
                t += valuelen;

                s = p = q + needlelen;
            }

            memcpy (t, s, remainlen);

            return newbuf;
        }
    }
    else
        return haystack;
}

 

by: cgi-binPosted on 2003-07-09 at 15:20:50ID: 8889502

The calling function should check the value of the pointer to haystack after the function returns.  If it's the same (t == x), then no substitutions occured.  Do not free(t).  If (t != x) then at least one substitution occured and you must free(t).  In my test, 25 million iterations took 111 seconds on a 700 MHz P3 running RHL7.2.

main () {

    char *t, *x;

    int i;
    time_t s, e;

    printf ("%lu\n", s = time(NULL));

    for (i = 0; i < 25000000; i++)
    {
        x = "This is a test of substituting %%CODE%% with 'new value' everywhere that %%CODE%% is seen";
        t = replace (x, "%%CODE%%", "new value");
        if (t != NULL && t != x) free (t);
    }

    printf ("%lu\n", e = time(NULL));
    printf ("%lu\n", e - s);


}
"test.c" 78L, 1550C written
[root@pp170a tmp]# cc test.c -o test
[root@pp170a tmp]# ./test
1057788609
1057788711
102

 

by: cgi-binPosted on 2003-07-09 at 15:22:06ID: 8889514

err...102 seconds

 

by: sizakPosted on 2003-07-09 at 15:26:11ID: 8889533

looks promising only problem is i get this error.


email_func.cpp: In function `char * replace(char *, char *, char *)':
email_func.cpp:139: ANSI C++ forbids implicit conversion from `void *' in assignment

this is a freebsd box using gmake.. any ideas?  it throws a erorr saying run stdlib.h which is already called anyway.  that line thats spitting the error is this line


if ((newbuf = malloc (newlen + 1)) != NULL)


 

by: cgi-binPosted on 2003-07-09 at 15:34:36ID: 8889593

You can explicity typecast the call to malloc() as in:

if ((newbuf = (char *) malloc(newlen + 1)) != NULL)
{
    /* blah, blah */
}

OR even more paranoid:

if ((newbuf = (char *) malloc(newlen + 1)) != (char *) NULL)
{
    /* blah, blah */
}

I tend to think that the first one of these two will correct the problem.

 

by: zebadaPosted on 2003-07-09 at 15:42:11ID: 8889645

This one does 3 million in about 10 seconds (PIII 1.5GHz)

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define GRAIN 100

char *replace(char *str,char *code,char *val);

int
main(int argc, char * argv)
{
  char *s = "she sells sea shells by the sea shore";
  //         0123456789012345678901234567890123456
  //                   1         2         3
  char *c = "sh";
  char *v = "XY";
  char *result;
  int  i;
 
  // Test 3 million iterations
  for ( i=0 ; i<3000000 ; i++ ) {
    if ( (result=replace(s,c,v))!=NULL )
      free(result);
  }
  // Show result (call it once more 'cause we free'd it above)
  if ( (result=replace(s,c,v))!=NULL ) {
    printf("[%s]\n",result);
    free(result);
  }
}

char *
replace(char *str,char *code,char *val)
{
  char *s,*c;
  char *result,*r;
  char **matchList,**tmp;
  int  matchCount,matchListSize;
  int  strLength,codeLength,valLength,resultLength,len;
  int  i;
 
  // Make a list of pointers to all the matching positions in str
  matchList = malloc(GRAIN*sizeof(char *));
  matchListSize = GRAIN;
  matchCount = 0;
  for ( s=str ; *s!='\0' ; s++ ) {
    matchList[matchCount] = s;
    for ( c=code ; *s==*c && *c!='\0' ; *c++ )
      *s++;
    if ( *c=='\0' ) {
      matchCount++;
      if ( matchCount==matchListSize ) {
        matchListSize += GRAIN;
        if ( (tmp=realloc(matchList,GRAIN*matchListSize*sizeof(char *)))==NULL ) {
          free(matchList);
          return NULL;
        }
        matchList = tmp;
      }
    }
  }

  // Work out how big the result needs to be
  strLength = strlen(str);
  codeLength = strlen(code);
  valLength = strlen(val);
  resultLength = strLength+(matchCount*(valLength-codeLength));
  result = malloc(resultLength+1);

  // Now copy the data from str to result
  s = str;
  r = result;
  for ( i=0 ; i<matchCount ; i++ ) {
    len = matchList[i]-s;
    memcpy(r,s,len);
    r += len;
    s += len;
    memcpy(r,val,valLength);
    r += valLength;
    s += codeLength;
  }
  memcpy(r,s,strLength-(s-str));
  *(result+resultLength) = '\0';

  free(matchList);
  return result;
}

 

by: zebadaPosted on 2003-07-09 at 15:47:38ID: 8889666

Same code on linux takes 5 seconds.
I'll test it using the same "strings" as cgi-in used just for comparison.

 

by: zebadaPosted on 2003-07-09 at 15:48:32ID: 8889675

Here it is with 25 million iterations using the same strings as cgi-bin used:
58 seconds.

pb@linux:/home/pb/test> time ./r
[This is a test of substituting new value with 'new value' everywhere that new value is seen]
   58.72s real    58.60s user     0.04s system
pb@linux:/home/pb/test>

 

by: cgi-binPosted on 2003-07-09 at 16:05:22ID: 8889753

Nice implementation and the length of the string makes a big difference.  I used zebada's strings using my algorithm and ET dropped from 102 down to 69 seconds.  His compiled on mine and runs in 59 seconds.

 

by: sizakPosted on 2003-07-09 at 16:21:30ID: 8889808

email_func.cpp: In function `char * replace(char *, char *, char *)':
email_func.cpp:165: ANSI C++ forbids implicit conversion from `void *' in assignment
email_func.cpp:171: warning: value computed is not used
email_func.cpp:171: warning: value computed is not used
email_func.cpp:176: ANSI C++ forbids implicit conversion from `void *' in assignment
email_func.cpp:190: ANSI C++ forbids implicit conversion from `void *' in assignment

each one of those ANSI errors is where a malloc is.. guys wanna help me out with the type casting on it?

 

by: zebadaPosted on 2003-07-09 at 18:01:20ID: 8890232

Change to:
matchList = (char **)malloc(GRAIN*sizeof(char *));
if ( (tmp=(char **)realloc(matchList,GRAIN*matchListSize*sizeof(char *)))==NULL ) {

result = (char *)malloc(resultLength+1);
Note the number of asterisks is different in the first two!

What does line 171 contian?
I'm guessing it's *s++ which should be changed to s++

Hey cgi, you said you were running on PIII 700 and it runs in 59 seconds.
I'm running P4 (I said PIII before - actually its a P4) 1.5GHz and it runs in 58 seconds.
Go figure! I wasted my money :(

I can't claim to have thought up the method I used - I just implemented grg99's comment.

Paul

 

by: sunnycoderPosted on 2003-07-10 at 01:56:36ID: 8891593

I am suggesting a solution which should work faster with a little expense in terms of memory

 tmpstr=(char *) malloc(strlen(str)+strlen(val)*4086);      ------------ get rid of this malloc ... if your function won't be called from
                                                                                          -------------two or more processes then use a static array big enough
                                                                                          -------------for your needs .... you have already cut down on 3 million
                                                                                          ------------- mallocs and free which is substantial execution time


#define BIG_ENOUGH_MEMORY 1024

char * replace(char * str,char *code,char * val){
char * needle, *track;
static char tmpstr [BIG_ENOUGH_MEMORY];
tmpstr = '\0';
track = str;

 while(  ( needle = strstr(track,code) ) != NULL  )  //as long as we have code in str
          {
           strncat ( tmpstr, track, needle - track );          // add everything from previous find uptill this find
           strcat ( tmpstr, val);                                        // add val
           track = needle + strlen (code);                       // advance track to end this find
          }
strcat ( tmpstr, track);                                               // add last part of str after last find
return tmpstr;
}

I haven't compiled/tested the code but I feel it should be a good start atleast

 

by: zebadaPosted on 2003-07-10 at 04:15:11ID: 8892005

The static is a good idea - getting rid of the malloc/free is a good saving.

But the strncat, strlen and strcat inside the loop - now that is wasteful - especially if the strings are not small.
Each time one of those functions is called it has to iterate a counter over the entire length of the string looking for the null terminator.
I would be interested to see a working version of your code to see if it is quicker or not.

Regards
Paul

 

by: cgi-binPosted on 2003-07-10 at 04:20:25ID: 8892018

If BIG_ENOUGH_MEMORY isn't big enough, the program is vulnerable to a buffer overrun, isn't it?

 

by: zebadaPosted on 2003-07-10 at 04:34:38ID: 8892079

I just tested Sunnycoder's suggestion and it does the 25,000,000 iterations in 20 seconds. That's better then twice as fast.

malloc() is the speed killer.

However, I then ran a test where the string length is about 10K and there are 120 substitutions to be done.
The code with the malloc did 25,000 iterations in 2.5 seconds.
The code with the strcat, strlen did 25,000 iterations in 13.7 seconds.
(25,000,000 would have taken too long)

So for short strings <1K, I'd say go with Sunnycoder's solution,
for longer strings (>1K) go with the one I submitted.

Or better still use a static (as Sunnycoder suggests) in my solution - just make it big enough to hold the biggest string you expect to encounter.

Regards
Paul

 

by: grg99Posted on 2003-07-10 at 05:32:29ID: 8892359

The OP now informs us that the stuff is going out a TCP/IP connection, which means we can save TONS of time by not building the output in memory.  Just look for the next occurrence of the string, TCPwrite() the preceding, tcpwrite() the new text, and repeat.

Oh, and I assume the original text doesnt change too often, you can speed things up EVEN MORE by caching the locations of where you found the pattern strings, this saves 3 million * num pats searches, which should amount to a lot.

And Oh, you may already be limited in speed by the TCP buffering code, it may not be worthwhile to keep tuning this bit of code forever.

 

by: sunnycoderPosted on 2003-07-10 at 06:08:51ID: 8892592

>>But the strncat, strlen and strcat inside the loop - now that is wasteful - especially if the strings are not small.
>>Each time one of those functions is called it has to iterate a counter over the entire length of the string looking for the null
>>terminator.

Good observation ... so heres how we can cut it

use another char * track_tmpstr which will point to last char in tempstr

while(  ( needle = strstr(track,code) ) != NULL  )  //as long as we have code in str
         {
          strncat ( track_tmpstr, track, needle - track );      ---- looping time reduced
          track_tmpstr += (needle - track);                         ---- end of tmpstr has advanced
          strcat ( track_tmpstr, val);                                     ---- looping time reduced
          track_tmpstr += strlen(val);                                  ---- end of tmpstr has advanced
                                                                                        ---- val is constant in  function call ... move it outside loop
          track = needle + strlen (code);                              ----- code is constant in a function call ... move it outside loop
          }


so we finally end up with this loop

i = strlen (val);
j = strlen (code);
while(  ( needle = strstr(track,code) ) != NULL  )  //as long as we have code in str
         {
          strncat ( track_tmpstr, track, needle - track );      
          track_tmpstr += (needle - track);                        
          strcat ( track_tmpstr, val);                                    
          track_tmpstr += i;    
          track = needle + j;                                
          }


this should be fast enough

 

by: grg99Posted on 2003-07-10 at 09:42:01ID: 8894549

It would also help if we knew how often the input file changes,
how often the patterns to search for change, and how often the
replacement strings change.

Or can we form a queue of files to be changed-- sort them
by similarities so we can minimize the number of repeated searches.
In other words, if we have a backlog of say 50 files to do,
if we can identify that TEN of the input files are the same one,
with only changes in the stuff to substitute, we only have to
search ONCE, and do the ten replacements in parallel,
or just refer to a cached list of places to replace text.
Similarly for replacements, if we can identify similar input files,
and/or similar replacements to be made, we can reduce the
work by a HUGE factor, without even encroaching on any
changes in the search/replace algorithms.






 The idea is we may be able to cache
some of the information we get from the searches, or even
cache the replaced output.  That would bring the time down to zero.

 

by: sizakPosted on 2003-07-10 at 10:39:46ID: 8895022

the string changes once a day. the times that it replaces a token is 1 to 25 depends on the string.  there are also 2 or 3 diff tokens that have to be ran through and sorted.  right now it looks like

res = replace(res,"%%TOKEN1%%",replaceFirst)
res = replace(res,"%%TOKEN2%%",replacedSecond)

 

by: KdoPosted on 2003-07-11 at 13:27:38ID: 8905841

Jumping in a little late.....

Here's a bit of code that should really zip along.  It can be made slightly faster by doing the token compares in-line, but with only 25 expected the savings are nominal.  There's also a slight performance improvement that can be made if the tokens are the same length and the original buffer is being reused by not copying the "static" characters.

// Set an upper limit to the number of changes allowed.
// As long as it's sufficiently large, any number will do.
// This value is used to compute the maximum possible length of a new dynamic buffer

#define MAX_CHANGES 100


// Set to true to use a static buffer, false to malloc() a new buffer.

#define USESTATICBUFFER 0


// This function will return the address of the new buffer.
// Note that this may or may not be the address of the original buffer.

char *ReplaceTokens (char *Buffer, char *OldToken, char *NewToken)
{
  int OldTokenLength = strlen (OldToken);
  int NewTokenLength = strlen (NewToken);
  char *Op;  // Old Pointer
  char *Np;  // New Pointer
  char *NewBuffer;

  Op = Buffer;
  if (OldTokenLength <= NewTokenLength)  // We can copy in place (no new buffer needed)
  {

//  Advance the token pointers past the initial chars that won't be replaced

    while (*Op && *Op != *OldToken)
      *Op++;
    NewBuffer = Buffer;
    Np = Op;
  }
  else
  {

//  Set up the new buffer

    if (USESTATICBUFFER)
      NewBuffer = StaticBuffer
    else
      malloc (strlen (Buffer)+MAX_CHANGES*(NewTokenLength-OldTokenLength)+1);

    Np = NewBuffer;    
  }

// Loop through the buffer, copying chars until a possible match is found

  while (*Op)
  {
    if (*Op != *OldToken)   // character is not the first char of the replacement string
    {
      *(Np++) = *(Op++);    // copy character
    }
    else
    {
      if (memcmp (Op, OldToken, OldTokenLength))  // Token not found
      {
        *(Np++) = *(Op++);  // Copy character and continue
      }
      else                  // replace token
      {
        memcpy (Np, NewToken, NewTokenLength);
        Op += OldTokenLength;
        Np += NewTokenLength;
      }
    }
  }  
  *Np = 0;                  // Terminate the new string
  return (NewBuffer);
}

Kdo  :)

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...