std::string, subscripting, and npos

Discussion in 'C++' started by Marcus Kwok, Jan 27, 2006.

  1. Marcus Kwok

    Marcus Kwok Guest

    std::string::npos is described in _TC++PL:SE_ (Section 20.3.4) as the
    "all characters" marker. I tried to use it this way, but my program
    crashes:

    #include <iostream>
    #include <string>

    int main()
    {
    std::string s = "hi/hello/now";
    std::cout << s << '\n';

    for (std::string::size_type i = 0; i != std::string::npos; ++i) {
    if (s == '/') {
    s = '\\';
    }
    }

    std::cout << s << '\n';
    }


    If I change "std::string::npos" to "s.length()" then of course the
    program works correctly. Why doesn't std::string::npos work in this
    context?


    --
    Marcus Kwok
    Marcus Kwok, Jan 27, 2006
    #1
    1. Advertising

  2. On Fri, 27 Jan 2006 21:06:31 +0000 (UTC),
    (Marcus Kwok) wrote:

    >std::string::npos is described in _TC++PL:SE_ (Section 20.3.4) as the
    >"all characters" marker. I tried to use it this way, but my program
    >crashes:
    >
    >#include <iostream>
    >#include <string>
    >
    >int main()
    >{
    > std::string s = "hi/hello/now";
    > std::cout << s << '\n';
    >
    > for (std::string::size_type i = 0; i != std::string::npos; ++i) {
    > if (s == '/') {
    > s = '\\';
    > }
    > }
    >
    > std::cout << s << '\n';
    >}
    >
    >
    >If I change "std::string::npos" to "s.length()" then of course the
    >program works correctly. Why doesn't std::string::npos work in this
    >context?


    std::string::npos is usually just an alias for ((unsigned)(-1)). You
    are therefore incrementing i way past the end of the string's length.

    std::string::npos is returned by most string functions which involve
    some kind of find, and which would normally return the index or
    position of the element being sought. Since there can never be such a
    position, this value was chosen to indicate "not found" or not
    present.

    --
    Bob Hairgrove
    Bob Hairgrove, Jan 27, 2006
    #2
    1. Advertising

  3. Marcus Kwok wrote:
    > std::string::npos is described in _TC++PL:SE_ (Section 20.3.4) as the
    > "all characters" marker. I tried to use it this way, but my program
    > crashes:
    >
    > #include <iostream>
    > #include <string>
    >
    > int main()
    > {
    > std::string s = "hi/hello/now";
    > std::cout << s << '\n';
    >
    > for (std::string::size_type i = 0; i != std::string::npos; ++i) {
    > if (s == '/') {
    > s = '\\';
    > }
    > }
    >
    > std::cout << s << '\n';
    > }
    >
    >
    > If I change "std::string::npos" to "s.length()" then of course the
    > program works correctly. Why doesn't std::string::npos work in this
    > context?


    'npos' is a constant usually defined as (size_type)(-1). Its specific
    purpose is to indicate "not found" condition when returning from 'find'
    members and the "end" position when using 'substr'.

    You mistakenly used it as if it is different for every 'string' object.
    It's not. IIRC it's a static member.

    V
    Victor Bazarov, Jan 27, 2006
    #3
  4. Marcus Kwok

    Mike Wahler Guest

    "Marcus Kwok" <> wrote in message
    news:dre20n$9e3$...
    > std::string::npos is described in _TC++PL:SE_ (Section 20.3.4) as the
    > "all characters" marker.


    Its meaning depends upon context. It's most often used to
    indicate 'not found' with e.g. 'find()'.

    > I tried to use it this way, but my program
    > crashes:
    >
    > #include <iostream>
    > #include <string>
    >
    > int main()
    > {
    > std::string s = "hi/hello/now";
    > std::cout << s << '\n';
    >
    > for (std::string::size_type i = 0; i != std::string::npos; ++i) {


    'npos' is not a valid index for a string. Even if you use the
    meaning 'all characters', what would that value as an index
    mean? The book doesn't say 'how many characters' does it? :)
    (and even if it did, then the highest valid index would be
    'how many, less one' (because first index is 0).)

    The valid index values are those integers in the set beginning with
    zero and ending with 'string::size() - 1', inclusive.

    'size() - 1' can never be equal to 'npos'. That's part of
    'npos's definition. The value of 'npos' must be chosen by
    an implementation to be some value that is *not* a valid
    index. That's how e.g. 'find()' (which returns an index
    value), can distinguish between a found element and 'not found'.

    Once 'i's value passes 'size() - 1', using it as an index
    will give undefined behavior. (The 'at()' member functinon
    would throw an exception).

    Write this instead:

    for (std::string::size_type i = 0; i != s.size(); ++i) {

    > if (s == '/') {
    > s = '\\';
    > }
    > }
    >
    > std::cout << s << '\n';
    > }
    >
    >
    > If I change "std::string::npos" to "s.length()"


    Note that 'size()' and 'length()' are two functions which
    have exactly the same effect.

    > then of course the
    > program works correctly. Why doesn't std::string::npos work in this
    > context?


    Because you're trying to use it for something other than
    it's defined purpose. Like trying to cut a watermelon with
    a feather. :)

    -Mike
    Mike Wahler, Jan 27, 2006
    #4
  5. Marcus Kwok

    Mike Wahler Guest

    "Victor Bazarov" <> wrote in message
    news:ebwCf.394$01.us.to.verio.net...
    >> If I change "std::string::npos" to "s.length()" then of course the
    >> program works correctly. Why doesn't std::string::npos work in this
    >> context?

    >
    > 'npos' is a constant usually defined as (size_type)(-1). Its specific
    > purpose is to indicate "not found" condition when returning from 'find'
    > members and the "end" position when using 'substr'.
    >
    > You mistakenly used it as if it is different for every 'string' object.
    > It's not. IIRC it's a static member.


    I suspect that Marcus misunderstood after seeing npos used in
    a different context, e.g. 'string::substr()'s second parameter
    specifies a default value of 'npos', meaning 'all'.

    std::string s("hello");
    std::string sub(s.substr(0)); // now s == sub

    -Mike
    Mike Wahler, Jan 27, 2006
    #5
  6. Marcus Kwok

    Marcus Kwok Guest

    Bob Hairgrove <> wrote:
    > On Fri, 27 Jan 2006 21:06:31 +0000 (UTC),
    > (Marcus Kwok) wrote:
    >
    >>std::string::npos is described in _TC++PL:SE_ (Section 20.3.4) as the
    >>"all characters" marker. I tried to use it this way, but my program
    >>crashes:
    >>
    >>#include <iostream>
    >>#include <string>
    >>
    >>int main()
    >>{
    >> std::string s = "hi/hello/now";
    >> std::cout << s << '\n';
    >>
    >> for (std::string::size_type i = 0; i != std::string::npos; ++i) {
    >> if (s == '/') {
    >> s = '\\';
    >> }
    >> }
    >>
    >> std::cout << s << '\n';
    >>}
    >>
    >>
    >>If I change "std::string::npos" to "s.length()" then of course the
    >>program works correctly. Why doesn't std::string::npos work in this
    >>context?

    >
    > std::string::npos is usually just an alias for ((unsigned)(-1)). You
    > are therefore incrementing i way past the end of the string's length.
    >
    > std::string::npos is returned by most string functions which involve
    > some kind of find, and which would normally return the index or
    > position of the element being sought. Since there can never be such a
    > position, this value was chosen to indicate "not found" or not
    > present.


    Thanks. I was thinking maybe it would be similar to the .end()
    iterator (as in, 1 greater than the last element).

    --
    Marcus Kwok
    Marcus Kwok, Jan 27, 2006
    #6
  7. Marcus Kwok

    David Harmon Guest

    On Fri, 27 Jan 2006 21:06:31 +0000 (UTC) in comp.lang.c++,
    (Marcus Kwok) wrote,
    >std::string::npos is described in _TC++PL:SE_ (Section 20.3.4) as the
    >"all characters" marker.


    That statement refers specifically to the use of npos as an argument
    to the string constructor that creates a substring of an existing
    string. Your code is not doing anything even slightly resembling
    that. Give me a break.
    David Harmon, Jan 27, 2006
    #7
  8. Marcus Kwok

    Duane Hebert Guest

    > Thanks. I was thinking maybe it would be similar to the .end()
    > iterator (as in, 1 greater than the last element).


    You could always just use an iterator.
    Duane Hebert, Jan 27, 2006
    #8
    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. Derek

    string::npos + 1 ???

    Derek, Apr 12, 2004, in forum: C++
    Replies:
    8
    Views:
    4,665
    Jorge Rivera
    Apr 15, 2004
  2. Marcus Kwok
    Replies:
    9
    Views:
    409
    Marcus Kwok
    Jul 2, 2007
  3. Adrian
    Replies:
    7
    Views:
    422
    Adrian
    Jul 12, 2007
  4. Christopher Pisz
    Replies:
    11
    Views:
    527
    James Kanze
    Jan 13, 2008
  5. Hendrik Schober
    Replies:
    11
    Views:
    868
    Hendrik Schober
    Sep 24, 2008
Loading...

Share This Page