tags:

views:

128

answers:

5
void trim(string &str)
{
    string::iterator it = str.begin();
    string::iterator end = str.end() - 1;

    // trim at the starting
    for(; it != str.end() && isspace(*it); it++)
        ;
    str.replace(str.begin(), it, "");

    // trim at the end
    for(; end >= str.begin() && isspace(*end); end--)
        ;
    str.replace(str.end(), end, ""); // i get the out_of_range exception here
}

I want to trim a string of spaces. First I trip spaces from the starting and it works fine and then I find the positions of spaces from the end and try to remove it and it throws exception.

Why?

+2  A: 

Iterators are only for sure valid until you modify the string. Once you change the string the end iterator surely gets invalidated.

You need to refetch the iterators after each action that could possibly modify the string.

sharptooth
he has his own end: string::iterator end = str.end() - 1;
celavek
what I mean is that he's not trying to dereference the string end() iterator in isspace(*end) he's taking a try at his own saved end (which might be invalid).
celavek
@Marius: True, fixed.
sharptooth
A: 

str.end() does not refer to any position with the string; hence, if you try to dereference it, you get an exception.

mganjoo
Xolve isn't dereferencing the end iterator. (Also, usually this wouldn't lead to an exception being thrown.)
sbi
+2  A: 

I'd suggest simply using boost::trim

Pieter
I don't see how this is such a good answer to the question. May-be a good comment. -1 from me.
UncleBens
@UncleBens because he explicitly states "I want to trim spaces", not "I'm learning my way around strings, this is some code I wrote, what's wrong with it?" or something similar
Pieter
+4  A: 

Changing a string invalidates iterators into the string. One way to fix this would be to modify the string only once. Incidentally, this might also be faster:

void trim(std::string &str)
{
    std::string::size_type begin=0;
    while(begin<str.size() && isspace(str[begin]))
      ++begin;
    std::string::size_type end=str.size()-1;
    while(end>begin && isspace(str[end]))
      --end;
    str = str.substr(begin, str.size()-end);
}
sbi
Haven't you made the variables too local?
UncleBens
@UncleBens: Yeah, dammit. Fixed now.
sbi
A: 

The problem is that you are storing an iterator to the last character in the string and use it only after you have (potentially) erased characters from the string, so the stored iterator is now invalid (not pointing to the last character any more).

It would help to declare variables as close to their first use as possible. In particular, iterators tend to become invalidated so easily, that you should generally avoid holding on to them any longer than necessary.

So, initialize the end iterator after you have erased the leading spaces. (One might also consider removing trailing spaces first.)


May I also suggest using the erase member function for erasing characters from the string.

There may be other errors in erasing trailing whitespace, but you can figure it out when you get there.

UncleBens