View Full Version: InsertStr -Finally!

C++ Learning Community > C++ Tips > InsertStr -Finally!


Title: InsertStr -Finally!
Description: emulation of std::string::insert()


Joel - January 1, 2006 02:39 AM (GMT)
Man, pointers can help a lot...
After a long time... I finally create one of my personal emulation favorites, insert. :wub:
I didn't steal code, all the algorithm was created on my code using pointers....
Ok...maybe they're another ways...but at least this one came from me, and with the help of some people

*Joel waves myork:

CODE

#include <iostream>

using std::cout;
using std::cin;
using std::endl;


int InsertStr(char *dst, const char *src, const char *str, int pos)
{
int i = 0;
while(*src)
{
 if (i == pos)
 {
  while (*str)
  {
   *dst = *str;
   ++dst;
   ++str;
   ++i;
  }
 }
 else
 {
  *dst = *src;
  ++dst;
  ++src;
  ++i;
 }
}
*dst++ = '\0';
return i; // how many chars are in the buffer
}

int main()
{
char s[64];
cout << InsertStr(s, "Hello people", " C++", 5) << endl;
cout << s << endl;

cin.get();
return 0;
}

I do honestly want some comments?

myork - January 1, 2006 09:55 PM (GMT)

I can think of easier ways to do it:

As you did not comment on the exact algorithm (as you should do)!!
What happens if pos > strlen(src)?

CODE

/*
* InsertStr:
*    Arguments:
*        OUT:   dst:   Assumed to point at a buffer of at least strlen(src) + strlen(str) + 1
*        IN:    src:   A null terminated string.
*        IN:    str:   A null terminated string.
*        IN:    pos:   The position in dst that 'str' will be inserted.
*   Description:
*        If pos <= strlen(src) then str will be inserted into src starting at pos.
*        The resulting string copied to dst
*        else src will copied to dst.
*/


My attempts: (Untested)
CODE
/*
* Method 1: Using loops.
* Obvious but not the most effecient.
*/
int InsertStr1(char*dst,const char* src,const char* str,int pos)
{
   int loop;
   for(int loop=0;(loop < pos) && ((*src) != '\0');++loop,++dst,++src)
   {
       (*dst)  = (*src);
   }
   /*
    * Add this condition to make sure it behaves like the orginal code
    * posted by Joel
    */
   if (loop == pos)
   {
       for(;(*str) != '\0';++str,++dst)
       {
           (*dst)  = (*str);
       }
       for(;(*src) != '\0';++dst,++src)
       {
           (*dst)  = (*src);
       }
   }
}


CODE
/*
* Method 2: Using strcpy
* Use the standard C string handling functions.
* This may be faster than method 1 as these libraries are often optimized.
* Also this is easier to read.
*/
int InsertStr2(char*dst,const char* src,const char* str,size_t pos)
{
   int len     = std::min(pos,strlen(src));
   strncpy(dst,src,len);
   dst[len]    = '\0';     // Make sure it is null terminated. if (pos > strlen(src) then it may not be
   if (len == pos)
   {
       strcat(dst,str);
       strcat(dst,src+len);
   }
}

Joel - January 2, 2006 01:35 AM (GMT)
Let me tell you that this are my first functions with pointers...second...let me think about:
QUOTE

What happens if pos > strlen(src)?

;)

dr voodoo - January 2, 2006 10:57 AM (GMT)
@myork you did not document that dst and src must be different, the same for str. Also you declare your function as returning int but never return anything.

myork - January 2, 2006 04:42 PM (GMT)
QUOTE (dr voodoo @ Jan 2 2006, 05:57 AM)
@myork you did not document that dst and src must be different

Very good point. That is a definite limitation of the algorithim (that I had not thought about). When str has a length greter than 0. (ie anytime it matters). So needs to be documented.

Remember when sombody uses your functions they may not have access to the code (or the skill to understand it). So you must document all limitations and assumptions. As well as expected results of the function.


QUOTE (dr voodoo @ Jan 2 2006, 05:57 AM)
Also you declare your function as returning int but never return anything.

That's just sloppy.

dr voodoo - January 2, 2006 07:31 PM (GMT)
QUOTE
Remember when sombody uses your functions they may not have access to the code (or the skill to understand it).
Even if he has access and the skills and even if he is the author this doesn't assure that he knows about the limitation at the time that he uses the function. It merly helps tracking down the bug but doesn't avoid it.

However you should even document that src and dst may overlap if the algorithms allows this. Otherwise somebody that maintains the code might get the idea to optimize and replace the algorithm with a more effcient one that doesn't allow overlapping and stop code from working.

Joel - January 4, 2006 05:11 PM (GMT)
Add some things:
CODE

#include <iostream>

using std::cout;
using std::cin;
using std::endl;

/*
_strlen: Emulator for strlen
Params:
IN: str
returns the number of chars. of 'str'
*/
int _strlen(const char *str)
{
int i = 0;
for(;(*str) != '\0'; ++i, ++str){}
return i;
}

/*
InsertStr: Function to insert the first 'len' chars of 'str' on 'src' starting position 'pos'
Params:
IN: src, str, pos, len
OUT: dst
Notes:
1. if pos > 'str' then 'src' will be concatened with 'str'.
2. if len > 'src' or len <= 0 then 'str' will be used complety
returns the number of chars on 'dst'
*/
int InsertStr(char *dst, const char *src, const char *str, int pos, int len)
{
int j = 0;
int l = _strlen(src);
// if 'pos' is bigger than 'src'
if (pos >= l)
{
 // concatenate 'str' with 'src' into 'dst'
 for(l = 0;*dst = *src; ++l, ++dst, ++src)
 {}
 for(;*dst = *str; ++l, ++dst, ++str)
 {}
 // ads null termination
 *dst++ = '\0';
 return l;
}
// number of chars on 'str'
l = _strlen(str);
// if it isn't, start the insertion...
for(;*src != '\0'; ++j, ++src, ++dst)
{
 // if our counter matches the 'pos'
 if (j == pos)
 {
  // begin 'str' insertion...
  // let's see if 'len' is valid number
  if ( (len <= 0) || (len >= l) )
  {
   // if len <= 0 than 'str' or
   // len > 'str'
   // 'str' will be inserted complety
   for(;*str != '\0'; ++j, ++str, ++dst)
   {
    *dst = *str;
   }
  }
  else
  {
   // let's insert the first 'len' of 'str' on 'src'
   for(;(*str != '\0') && (len != 0); ++j, --len, ++str, ++dst)
   {
    *dst = *str;
   }
  }
 }
 // continues copying into buffer
 *dst = *src;
}
// ads null termination
*dst++ = '\0';
return j;
}

int main()
{
char s[64];
cout << InsertStr(s, "JoelPower", "-void", 4, 1) << endl;
cout << "[" << s << "]" << endl;

cin.get();
return 0;
}




Hosted for free by InvisionFree