Re: Truncate a C++ string

Discussion in 'C++' started by Stefan van Kessel, Sep 21, 2010.

  1. On 9/21/2010 8:03 PM, Pete Becker wrote:
    > On 2010-09-21 13:52:04 -0400, Paul said:
    >
    >> I have a path in a string ie: std::string s =
    >> "/usr/local/src/test.dat"
    >>
    >> Is there a string function that will locate the last "/" in a string and
    >> null terminate the string on that character?
    >>

    >
    > start with basic_string::rfind.
    >


    While rfind is perfectly fine I think find_last_of states in the intent
    ever so slightly clearer.

    std::string str = "/usr/local/src/test.dat";
    std::string::size_type end = str.find_last_of('/');
    if(end != str.npos)
    str = str.substr(0, end+1);

    If you need a null terminated string i.e. a C-string, you can use
    str.c_str().
    Stefan van Kessel, Sep 21, 2010
    #1
    1. Advertising

  2. On 9/21/2010 8:21 PM, Paul wrote:
    > On 2010-09-21, Stefan van Kessel<> wrote:
    >> On 9/21/2010 8:03 PM, Pete Becker wrote:
    >>> On 2010-09-21 13:52:04 -0400, Paul said:
    >>>
    >>>> I have a path in a string ie: std::string s =
    >>>> "/usr/local/src/test.dat"
    >>>>
    >>>> Is there a string function that will locate the last "/" in a string and
    >>>> null terminate the string on that character?
    >>>>
    >>>
    >>> start with basic_string::rfind.
    >>>

    >>
    >> While rfind is perfectly fine I think find_last_of states in the intent
    >> ever so slightly clearer.
    >>
    >> std::string str = "/usr/local/src/test.dat";
    >> std::string::size_type end = str.find_last_of('/');
    >> if(end != str.npos)
    >> str = str.substr(0, end+1);
    >>
    >> If you need a null terminated string i.e. a C-string, you can use
    >> str.c_str().

    > I like that method! Very clear to understand.
    >

    Actually str.erase(end+1) would be better than assigning the substr. I
    didn't think of that before. But be sure to test if the character has
    actually been found (here end!=str.npos) unless you already know for
    sure it is in the string.
    sbackup.replace(sbackup.rfind("/"), sbackup.length(), "");
    which you wrote in the other message produces undefined behavior if
    there is no "/" in the string because replace requires the first
    argument to be smaller than the size of the string.
    Stefan van Kessel, Sep 21, 2010
    #2
    1. Advertising

  3. On 9/21/2010 11:14 PM, Pete Becker wrote:
    > On 2010-09-21 14:11:54 -0400, Stefan van Kessel said:
    >
    >> On 9/21/2010 8:03 PM, Pete Becker wrote:
    >>> On 2010-09-21 13:52:04 -0400, Paul said:
    >>>
    >>>> I have a path in a string ie: std::string s =
    >>>> "/usr/local/src/test.dat"
    >>>>
    >>>> Is there a string function that will locate the last "/" in a string
    >>>> and
    >>>> null terminate the string on that character?
    >>>>
    >>>
    >>> start with basic_string::rfind.
    >>>

    >>
    >> While rfind is perfectly fine I think find_last_of states in the
    >> intent ever so slightly clearer.

    >
    > Um, not hardly. And it's bigger and slower. rfind does exactly what's
    > needed.
    >


    I'm not sure why you are convinced that it's "bigger and slower". If
    there is more to it than the following, I would love to hear about it.
    The standard requires the same behavior of both:
    They both ought to behave as if they forward to their overload taking a
    basic_string containing that one char.
    (From 21.3.6:)
    - Effects: Determines the highest position xpos, if possible, such that
    both of the following conditions obtain:
    rfind:
    — xpos <= pos and xpos + str.size() <= size();
    — at(xpos+I) == str.at(I) for all elements I of the string controlled by
    str.
    find_last_of:
    — xpos <= pos and xpos < size();
    — at(xpos) == str.at(I) for some element I of the string controlled by str.

    With str.size() == 1 that amounts to the same.

    In practice both the implementations that I checked: msvc10's and gcc
    4.5's basic_string::find_last_of are a one line function, defined
    inline, that does nothing but forward the call to rfind.

    MSVC:
    size_type find_last_of(_Elem _Ch, size_type _Off = npos) const
    { // look for _Ch before _Off
    return (rfind((const _Elem *)&_Ch, _Off, 1));
    }

    While rfind('/') merely forwards to the same version of rfind, too:
    size_type rfind(_Elem _Ch, size_type _Off = npos) const
    { // look for _Ch before _Off
    return (rfind((const _Elem *)&_Ch, _Off, 1));
    }

    GCC:
    * Note: equivalent to rfind(c, pos).
    */
    size_type
    find_last_of(_CharT __c, size_type __pos = npos) const
    { return this->rfind(__c, __pos); }


    So find_last_of will not be faster than rfind but *usually* not slower
    either. Anybody who doesn't agree that find_last_of might state the
    intent clearer (and I don't feel strongly about that either; I admit
    that it's hardly more than a bikeshed issue anyway :/) absolutely should
    go with rfind but I'm not convinced that performance is a killer
    argument here.

    Have a nice day,
    Stefan
    Stefan van Kessel, Sep 22, 2010
    #3
  4. Stefan van Kessel

    James Kanze Guest

    On Sep 21, 10:14 pm, Pete Becker <> wrote:
    > On 2010-09-21 14:11:54 -0400, Stefan van Kessel said:


    > > On 9/21/2010 8:03 PM, Pete Becker wrote:
    > >> On 2010-09-21 13:52:04 -0400, Paul said:


    > >>> I have a path in a string ie: std::string s =
    > >>> "/usr/local/src/test.dat"


    > >>> Is there a string function that will locate the last "/"
    > >>> in a string and null terminate the string on that
    > >>> character?


    > >> start with basic_string::rfind.


    > > While rfind is perfectly fine I think find_last_of states in
    > > the intent ever so slightly clearer.


    > Um, not hardly. And it's bigger and slower. rfind does exactly
    > what's needed.


    Until he has to port to Windows, and find either '/' or '\' :).

    (I'll admit that I don't find anything using the std::string
    member functions "clearer". I have to know the algorithms in
    <algorithm> anyway, for the cases where I'm dealing with some
    other sort of container. Why should a learn a separate and
    distinct set just for std::string?)

    --
    James Kanze
    James Kanze, Sep 22, 2010
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Stimp
    Replies:
    2
    Views:
    625
    Stimp
    Oct 27, 2006
  2. Katie

    Smart String truncate

    Katie, Apr 20, 2007, in forum: Java
    Replies:
    2
    Views:
    729
    Daniel Pitts
    Apr 20, 2007
  3. Hongyu
    Replies:
    9
    Views:
    887
    James Kanze
    Aug 8, 2008
  4. MacRules
    Replies:
    2
    Views:
    298
  5. Alessio

    Truncate a string using printf

    Alessio, Nov 16, 2009, in forum: C Programming
    Replies:
    9
    Views:
    7,969
    Eric Sosman
    Nov 16, 2009
Loading...

Share This Page