string::npos + 1 ???

Discussion in 'C++' started by Derek, Apr 12, 2004.

  1. Derek

    Derek Guest

    A common technique for trimming leading and trailing spaces
    from std::string is the following:

    string s(" blah blah blah ");

    const char* ws= " \t\r";
    string::size_type not_white;

    // trim leading whitespace
    not_white = s.find_first_not_of(ws);
    s.erase(0, not_white);

    // trim trailing space
    not_white = s.find_last_not_of(ws);
    s.erase(not_white+1); /*** Is this safe? ***/
    // ^^^^^^^^^^^

    My question is about the underlined not_white+1. What if
    the find_last_not_of call returns string::npos, as would
    happen if s was a blank string. It seems to work with
    all of my compilers, but it seems dubious to increment
    string::npos.
    Derek, Apr 12, 2004
    #1
    1. Advertising

  2. Derek wrote:

    > A common technique for trimming leading and trailing spaces
    > from std::string is the following:
    >
    > string s(" blah blah blah ");
    >
    > const char* ws= " \t\r";
    > string::size_type not_white;
    >
    > // trim leading whitespace
    > not_white = s.find_first_not_of(ws);
    > s.erase(0, not_white);
    >
    > // trim trailing space
    > not_white = s.find_last_not_of(ws);
    > s.erase(not_white+1); /*** Is this safe? ***/
    > // ^^^^^^^^^^^
    >
    > My question is about the underlined not_white+1. What if
    > the find_last_not_of call returns string::npos, as would
    > happen if s was a blank string. It seems to work with
    > all of my compilers, but it seems dubious to increment
    > string::npos.


    npos is defined as -1 converted to string::size_type, which is an
    unsigned integral type. As per the rules of unsigned types, -1 becomes
    the largest representable value. Adding 1 causes this value to wrap
    around to 0. Therefore, the result will be equivalent to

    s.erase(0);

    As far as I can tell, there's nothing wrong with this. It should make
    's' empty (if it isn't already -- in your example it should already be).
    This seems to give the expected result in your code, but it may be a bit
    confusing. It may not be immediately obvious to someone reading the code
    that it is correctly handling this case, and therefore it might be
    worthwhile to make handling of it explicit. But that's your call.

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
    Kevin Goodsell, Apr 12, 2004
    #2
    1. Advertising

  3. Derek

    Siemel Naran Guest

    "Derek" <> wrote in message
    news:c5evd2$udmo$-

    > A common technique for trimming leading and trailing spaces
    > from std::string is the following:
    >
    > string s(" blah blah blah ");
    >
    > const char* ws= " \t\r";
    > string::size_type not_white;
    >
    > // trim leading whitespace
    > not_white = s.find_first_not_of(ws);
    > s.erase(0, not_white);
    >
    > // trim trailing space
    > not_white = s.find_last_not_of(ws);
    > s.erase(not_white+1); /*** Is this safe? ***/
    > // ^^^^^^^^^^^


    What happens here?

    std::string s;
    trimboth(s);
    Siemel Naran, Apr 14, 2004
    #3
  4. "Siemel Naran" <> wrote in message news:<6y3fc.28564$>...
    > "Derek" <> wrote in message
    > news:c5evd2$udmo$-
    >
    > > A common technique for trimming leading and trailing spaces
    > > from std::string is the following:
    > >
    > > string s(" blah blah blah ");
    > >
    > > const char* ws= " \t\r";
    > > string::size_type not_white;
    > >
    > > // trim leading whitespace
    > > not_white = s.find_first_not_of(ws);
    > > s.erase(0, not_white);
    > >
    > > // trim trailing space
    > > not_white = s.find_last_not_of(ws);
    > > s.erase(not_white+1); /*** Is this safe? ***/
    > > // ^^^^^^^^^^^

    >
    > What happens here?
    >
    > std::string s;
    > trimboth(s);


    Nothing?
    The typical implementation error for trimboth shows up when trimming
    " ", as the search from the front crosses the search from the end.
    In the empty string, the front and the back are equal and the search
    doesn't cross. Therefore you don't get negative distances to erase,
    you get a zero distance.

    The implementation above is correct, even with the " " testcase, as the
    second trim works on the trimmed interim result "".

    Regards,
    Michiel Salters
    Michiel Salters, Apr 14, 2004
    #4
  5. Derek

    Derek Guest

    Siemel Naran wrote:
    >>A common technique for trimming leading and trailing
    >>spaces from std::string is the following:
    >>
    >>string s(" blah blah blah ");
    >>
    >>const char* ws= " \t\r";
    >>string::size_type not_white;
    >>
    >>// trim leading whitespace
    >>not_white = s.find_first_not_of(ws);
    >>s.erase(0, not_white);
    >>
    >>// trim trailing space
    >>not_white = s.find_last_not_of(ws);
    >>s.erase(not_white+1); /*** Is this safe? ***/
    >>// ^^^^^^^^^^^

    >
    > What happens here?
    >
    > std::string s;
    > trimboth(s);


    It works as expected with the latest GCC and VC7.1, even
    when s is blank. When the string is blank, the case I'm
    concerned about, trimming the left side looks like this:

    not_white = s.find_first_of(ws); // returns npos
    s.erase(0, not_white); // fine

    And the left side:

    not_white = s.find_last_not_of(ws); // returns npos
    s.erase(npos + 1);

    As Kevin pointed out, the last line amounts to

    s.erase(0)

    which is fine. Of course if the string was not blank
    this sequence would have produced the expected trimmed
    string.
    Derek, Apr 14, 2004
    #5
  6. Derek

    Jorge Rivera Guest

    Derek wrote:
    > Siemel Naran wrote:
    > >>A common technique for trimming leading and trailing
    > >>spaces from std::string is the following:
    > >>
    > >>string s(" blah blah blah ");
    > >>
    > >>const char* ws= " \t\r";
    > >>string::size_type not_white;
    > >>
    > >>// trim leading whitespace
    > >>not_white = s.find_first_not_of(ws);
    > >>s.erase(0, not_white);
    > >>
    > >>// trim trailing space
    > >>not_white = s.find_last_not_of(ws);
    > >>s.erase(not_white+1); /*** Is this safe? ***/
    > >>// ^^^^^^^^^^^

    > >
    > > What happens here?
    > >
    > > std::string s;
    > > trimboth(s);

    >
    > It works as expected with the latest GCC and VC7.1, even
    > when s is blank. When the string is blank, the case I'm
    > concerned about, trimming the left side looks like this:
    >


    The fact that it works with current versions doesn't mean all that much
    to me in this case.

    If I understood the problem, the question is what happens
    std::string::npos is not equal to -1, as is the case in the compilers
    you mentioned?

    Is there a guarantee that npos == -1?, or is this just pure luck????
    Jorge Rivera, Apr 15, 2004
    #6
  7. Jorge Rivera wrote:

    >
    > If I understood the problem, the question is what happens
    > std::string::npos is not equal to -1, as is the case in the compilers
    > you mentioned?
    >
    > Is there a guarantee that npos == -1?, or is this just pure luck????


    It is required that basic_string::npos be the largest representable
    value for basic_string::size_type. In other words, it must be equal to
    static_cast<basic_string::size_type>(-1).

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
    Kevin Goodsell, Apr 15, 2004
    #7
  8. Jorge Rivera <> wrote in message news:<Vfmfc.26635$>...

    > Is there a guarantee that npos == -1?, or is this just pure luck????



    If it is not, the compiler would have a (serious) bug. That is no
    guarantee, if you read your EULA. However, this is too easy to spot
    and fix, so compiler vendors in practice get this right.

    ( technically, it's not -1 but (size_type) -1 which is positive )
    Michiel Salters, Apr 15, 2004
    #8
  9. Derek

    Jorge Rivera Guest

    > It is required that basic_string::npos be the largest representable
    > value for basic_string::size_type. In other words, it must be equal to
    > static_cast<basic_string::size_type>(-1).
    >
    > -Kevin


    Thanks,

    JLR
    Jorge Rivera, Apr 15, 2004
    #9
    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. Marcus Kwok
    Replies:
    7
    Views:
    413
    Duane Hebert
    Jan 27, 2006
  2. John Fly
    Replies:
    1
    Views:
    430
    Archmagus
    Feb 17, 2006
  3. Alien
    Replies:
    5
    Views:
    556
    Pete Becker
    Sep 18, 2006
  4. Adrian
    Replies:
    7
    Views:
    419
    Adrian
    Jul 12, 2007
  5. Christopher Pisz
    Replies:
    11
    Views:
    525
    James Kanze
    Jan 13, 2008
Loading...

Share This Page