substr

Started by
26 comments, last by zealouselixir 22 years, 2 months ago
Hey guys. I was hacking around this afternoon and I came up with a pretty nifty implementation of a substr()-style function. I was wondering if there are any optimizations that could be easily made without the introduction of additional function calls. Anyway, here's the code. Let the flaming commence.
      
char *substr(char *base, int start, int length)
{
    int i = 0, j = 0, baselength = 0;
    
    while(base[i++] != '\0')
        baselength++;
    if(length > baselength)
        return "=NULL=";
    char* substring = new char[length + 1];
    for (i = start; i < length + start; i++, j++)
        substring[j] = base[i];
    substring[j] = '\0';
    return substring;
}
  
Thanks. Later, ZE. [EDIT: code formatting (still doesn't look right)] //email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links
[if you have a link proposal, email me.] Edited by - zealouselixir on February 6, 2002 1:25:55 PM

[twitter]warrenm[/twitter]

Advertisement
Why have it return ''null'' as a string if the length is longer than the base length? why not have it return the string up to the base length?

-Uhfgood
*************************************Keith Weatherby IIhttp://twitter.com/Uhfgoodhttp://www.facebook.com/Uhfgoodhttp://www.youtube.com/Uhfgoodhttp://www.gamesafoot.comhttp://indieflux.com*************************************
Because I am the man.


Seriously, good idea. I'll fix that.

Later,
ZE.

P.S. Here's the fix:

    if(length > baselength)    return "=NULL=";// the above turns into...if(length > baselength)    length = baselength;    


In addition, if you want it to be as fool-proof as possible, add the following lines at the top:
  	if(!base)		return "\0";  



//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links

[if you have a link proposal, email me.]



Edited by - zealouselixir on February 6, 2002 1:37:59 PM

[twitter]warrenm[/twitter]

your code won''t work. It may also cause core-dump. If you need help with your code, just say so.
Define "won''t work." It does the job just fine as far as I''ve tested it.

Later,
ZE.

//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links

[if you have a link proposal, email me.]

[twitter]warrenm[/twitter]

As far as I can tell, it won''t cause core dump, as long as you delete the substring when you''re finished with it. If you''re not concerned with memory leakage, you don''t even have to do that . Seriously though, if there are some issues I''m overlooking, tell me.

Later,
ZE.

//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links

[if you have a link proposal, email me.]

[twitter]warrenm[/twitter]

The most obvious problem is that you don''t verify that start < baselength. The second problem is that it''s impossible to tell whether it''s ok to delete the returned string or not without examining the string (sometimes you return a string allocated with new, sometimes you return a constant string). A third (related) problem is that you can''t distinguish a success from a failure - consider if base actually contained the string "=NULL=".

-Mike

-Mike
Aiiight, here's version 3.

      char *substr(char *base, int start, int length){    char *substring;    if(!base)    {        substring = new char[1];        substring[0] = '\0';        return substring;    }    int i = 0, j = 0, baselength = 0;        while(base[i++] != '\0')        baselength++;          if(length > baselength)        length = baselength;        if(start > baselength)    {        substring = new char[1];        substring[0] = '\0';        return substring;    }    substring = new char[length + 1];        for (i = start; i < length + start; i++, j++)        substring[j] = base[i];        substring[j] = '\0';        return substring;}      


Now you always have to delete the returned string, you can't go out of any boundaries, and (this wasn't a concern after version 2, but Mike didn't read all the follow-up posts) an empty string is simply returned when an error can't be recovered from. Now we just need optimizations

Later,
ZE.

//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links

[if you have a link proposal, email me.]

[EDIT: formatting and spelling]


Edited by - zealouselixir on February 6, 2002 9:25:53 PM

[twitter]warrenm[/twitter]

1. Just return a null pointer instead of constructing a null string on the free store.
2. Prefer pre-increment to post increment, unless post-increment is necessary.
3. Reuse the standard library copy instead of writing your own.
4. Use the preprocessor to specify that the checks only be performed in debug mode (optional!).

  #include <algorithm> char* substr (char* base, int start, int length){  using std::copy;   if (!base) return 0; #ifndef NDEBUG  {    int i = 0, baselength = 0;     while (base[i++] != ''\0'') ++baselength;     if (length > baselength) length = baselength;    if (start  > baselength) return 0;  }#endif // NDEBUG   char* substring = new char [length + 1];   char* begin = base  + start;  char* end   = being + length;   copy (begin, end, substring);   *end = ''\0'';   return substring;}  


I suppose that you could use std::memcpy to copy words at a time instead of bytes. std::memcpy should be highly optimized already. Outside of that, there isn''t much you can do to make your code execute faster.
I think that''s a bad use of a debug-only check, as it will result in code that executes fine without any warnings in debug mode but crashes in release mode. Better to use assertions in debug mode if you want to insist that the function is given valid inputs. Otherwise choose between the range-checking that you have now and throwing exceptions when stuff is out of range.

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost ]

This topic is closed to new replies.

Advertisement