Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Remove suffix from string

Reply
Thread Tools

Remove suffix from string

 
 
Spoon
Guest
Posts: n/a
 
      10-24-2006
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: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.
 
Reply With Quote
 
 
 
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      10-24-2006
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: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

 
Reply With Quote
 
 
 
 
Salt_Peter
Guest
Posts: n/a
 
      10-24-2006

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: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.


 
Reply With Quote
 
Spoon
Guest
Posts: n/a
 
      10-24-2006
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:ut_of_range'
>> what(): basic_string::erase
>>Aborted


Regards.
 
Reply With Quote
 
Salt_Peter
Guest
Posts: n/a
 
      10-24-2006

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:ut_of_range'
> >> what(): basic_string::erase
> >>Aborted

>
> Regards.


 
Reply With Quote
 
Pete Becker
Guest
Posts: n/a
 
      10-24-2006
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.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
how to remove suffix from filename royG Python 2 03-19-2008 06:02 PM
ICS suffix MS Wireless Networking 0 08-11-2005 11:26 AM
URL without suffix in .Net Victor Yuan ASP .Net 7 01-05-2005 03:17 AM
Firefox: Default suffix/regional Fr Jack Firefox 10 12-15-2004 08:10 PM
Assigning connection suffix from Radius Matt Cisco 0 10-20-2004 01:43 PM



Advertisments