Remove suffix from string

Discussion in 'C++' started by Spoon, Oct 24, 2006.

  1. Spoon

    Spoon Guest

    Hello,

    I'm writing code to remove .whatever from the end of a string.

    e.g. hello.world.foo.bar -> hello.world.foo

    The following code seems to work

    #include <string>
    #include <iostream>
    int main(int argc, char **argv)
    {
    std::string foo(argv[1]);
    foo.erase(foo.rfind('.'));
    std::cout << foo << std::endl;
    return 0;
    }

    $ ./a.out hello.world.foo.bar
    hello.world.foo

    but it crashes when rfind() returns npos

    $ ./a.out hello+world+foo+bar
    terminate called after throwing an instance of 'std::eek:ut_of_range'
    what(): basic_string::erase
    Aborted

    Is pos+1 valid, even when pos==npos?

    If so, I could write

    #include <string>
    #include <iostream>
    int main(int argc, char **argv)
    {
    std::string foo(argv[1]);
    foo.erase(foo.rfind('.')+1);
    std::cout << foo << std::endl;
    return 0;
    }

    Then I'd have to remove the trailing '.' and the entire string is erased
    if there is no '.' (which may be acceptable).

    Is there a better solution?

    Regards.
     
    Spoon, Oct 24, 2006
    #1
    1. Advertising

  2. Spoon

    Kai-Uwe Bux Guest

    Spoon wrote:

    > Hello,
    >
    > I'm writing code to remove .whatever from the end of a string.
    >
    > e.g. hello.world.foo.bar -> hello.world.foo
    >
    > The following code seems to work
    >
    > #include <string>
    > #include <iostream>
    > int main(int argc, char **argv)
    > {
    > std::string foo(argv[1]);
    > foo.erase(foo.rfind('.'));
    > std::cout << foo << std::endl;
    > return 0;
    > }
    >
    > $ ./a.out hello.world.foo.bar
    > hello.world.foo
    >
    > but it crashes when rfind() returns npos
    >
    > $ ./a.out hello+world+foo+bar
    > terminate called after throwing an instance of 'std::eek:ut_of_range'
    > what(): basic_string::erase
    > Aborted
    >
    > Is pos+1 valid, even when pos==npos?


    Yes: the result is of type string::size_type which is unsigned. Unsigned
    built-in arithmetic types wrap on overflow.

    However, since you have to ask, it relying on it may not be a good idea from
    a maintenance point of view: the programmer that comes after you might not
    know and get confused (notice that this could easily be yourself a few
    months down the road).

    >
    > If so, I could write
    >
    > #include <string>
    > #include <iostream>
    > int main(int argc, char **argv)
    > {
    > std::string foo(argv[1]);
    > foo.erase(foo.rfind('.')+1);
    > std::cout << foo << std::endl;
    > return 0;
    > }
    >
    > Then I'd have to remove the trailing '.' and the entire string is erased
    > if there is no '.' (which may be acceptable).
    >
    > Is there a better solution?


    What about

    foo.erase( std::min( foo.rfind('.'), foo.size() ) );


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Oct 24, 2006
    #2
    1. Advertising

  3. Spoon

    Salt_Peter Guest

    Spoon wrote:
    > Hello,
    >
    > I'm writing code to remove .whatever from the end of a string.
    >
    > e.g. hello.world.foo.bar -> hello.world.foo
    >
    > The following code seems to work
    >
    > #include <string>
    > #include <iostream>
    > int main(int argc, char **argv)
    > {
    > std::string foo(argv[1]);
    > foo.erase(foo.rfind('.'));


    instead:
    foo.assign(foo, 0, foo.rfind('.'));

    > std::cout << foo << std::endl;
    > return 0;
    > }
    >
    > $ ./a.out hello.world.foo.bar
    > hello.world.foo
    >
    > but it crashes when rfind() returns npos


    did you supply argv[1]? How about a check with argc in the code.
    also, erase(...) expects iterators. assign(...) takes a size_type.
    consult the header.

    >
    > $ ./a.out hello+world+foo+bar
    > terminate called after throwing an instance of 'std::eek:ut_of_range'
    > what(): basic_string::erase
    > Aborted
    >
    > Is pos+1 valid, even when pos==npos?
    >
    > If so, I could write
    >
    > #include <string>
    > #include <iostream>
    > int main(int argc, char **argv)
    > {
    > std::string foo(argv[1]);
    > foo.erase(foo.rfind('.')+1);
    > std::cout << foo << std::endl;
    > return 0;
    > }
    >
    > Then I'd have to remove the trailing '.' and the entire string is erased
    > if there is no '.' (which may be acceptable).
    >
    > Is there a better solution?
    >
    > Regards.
     
    Salt_Peter, Oct 24, 2006
    #3
  4. Spoon

    Spoon Guest

    Salt_Peter wrote:

    > Spoon wrote:
    >
    >> $ ./a.out hello.world.foo.bar
    >> hello.world.foo
    >>
    >> but it crashes when rfind() returns npos

    >
    > did you supply argv[1]?


    Errr... yes. (I provided the command and the output)

    > How about a check with argc in the code.


    This is but a toy example.

    > also, erase(...) expects iterators.


    This statement is inaccurate, as far as I can tell.

    A valid prototype for erase is

    basic_string& erase(size_type off = 0, size_type count = npos);

    > assign(...) takes a size_type.
    > consult the header.


    I will.

    >>$ ./a.out hello+world+foo+bar
    >>terminate called after throwing an instance of 'std::eek:ut_of_range'
    >> what(): basic_string::erase
    >>Aborted


    Regards.
     
    Spoon, Oct 24, 2006
    #4
  5. Spoon

    Salt_Peter Guest

    Spoon wrote:
    > Salt_Peter wrote:
    >
    > > Spoon wrote:
    > >
    > >> $ ./a.out hello.world.foo.bar
    > >> hello.world.foo
    > >>
    > >> but it crashes when rfind() returns npos

    > >
    > > did you supply argv[1]?

    >
    > Errr... yes. (I provided the command and the output)


    Ah, you need to run the program otherwise the arguement isn't injected.
    I checked the header... and... you're RIGHT. erase *does* have a
    version with size_type.

    Try:

    #include <iostream>
    #include <string>

    int main(int argc, char* argv[])
    {
    if(argc > 1)
    {
    std::string foo(argv[1]);
    foo.erase(foo.rfind('.'));
    std::cout << foo << std::endl;
    } else {
    std::cout << "argc = " << argc;
    std::cout << std::endl;
    }
    return 0;
    }

    If you see the argc = # ouput then run the program instead. I got the
    following with an arguement of test.txt
    /*
    test
    */
    and the following when debugging:
    /*
    argc = 1
    */

    Please accept my sincere apologees for misleading you.

    >
    > > How about a check with argc in the code.

    >
    > This is but a toy example.
    >
    > > also, erase(...) expects iterators.

    >
    > This statement is inaccurate, as far as I can tell.
    >
    > A valid prototype for erase is
    >
    > basic_string& erase(size_type off = 0, size_type count = npos);
    >
    > > assign(...) takes a size_type.
    > > consult the header.

    >
    > I will.
    >
    > >>$ ./a.out hello+world+foo+bar
    > >>terminate called after throwing an instance of 'std::eek:ut_of_range'
    > >> what(): basic_string::erase
    > >>Aborted

    >
    > Regards.
     
    Salt_Peter, Oct 24, 2006
    #5
  6. Spoon

    Pete Becker Guest

    Spoon wrote:
    >
    > Is there a better solution?
    >


    inline void erase_end(std::string& str, std::string::size_type pos)
    {
    if (pos != std::string::npos)
    erase(str, pos);
    }

    --

    -- Pete

    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." For more information about this book, see
    www.petebecker.com/tr1book.
     
    Pete Becker, Oct 24, 2006
    #6
    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. Victor Yuan

    URL without suffix in .Net

    Victor Yuan, Dec 30, 2004, in forum: ASP .Net
    Replies:
    7
    Views:
    891
    Dino Chiesa [Microsoft]
    Jan 5, 2005
  2. Green

    what the suffix of the file

    Green, Oct 27, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    2,211
    Steven Cheng[MSFT]
    Oct 28, 2004
  3. Joseph

    compressed suffix trie

    Joseph, Sep 22, 2004, in forum: Java
    Replies:
    1
    Views:
    547
    =?ISO-8859-1?Q?Daniel_Sj=F6blom?=
    Sep 22, 2004
  4. Andrea Desole

    Parsing double with suffix

    Andrea Desole, Jul 7, 2005, in forum: Java
    Replies:
    2
    Views:
    431
    Andrea Desole
    Jul 7, 2005
  5. royG
    Replies:
    2
    Views:
    257
    Larry Bates
    Mar 19, 2008
Loading...

Share This Page