Reputation: 21813
I assume the following doesn't compile because I am mixing forward and reverse iterators. Why can't I mix them like this? How can I get it to work? I want to remove the first and last quote of the string, but leave any internal quotes present.
temp.assign(find(value.begin(), value.end(), '\"'), find(value.rbegin(), value.rend(), '\"'));
I cannot even do this. What is the point of reverse iterators?
value.erase(find(value.begin(), value.end(), '\"'));
value.erase(find(value.rbegin(), value.rend(), '\"'));
Upvotes: 0
Views: 2107
Reputation: 6240
How about this?
void stripLeadingAndTrailingQuotes(std::string& s) {
if (s[0] == '\"')
s.erase(0, 1);
size_t last = s.length() - 1;
if (s[last] == '\"')
s.erase(last, 1);
}
Iterators are valid but I think the above is a lot more readable.
Upvotes: 0
Reputation: 5470
I think the problem is that erase expects a forward iterator, not a reverse iterator. As others have pointed out you can just use .base() on the result of find to convert them.
You could also use find_end instead.
Upvotes: 0
Reputation: 154047
The assign function (regardless of the type of temp
) requires
two iterators of the same type. A reverse iterator doesn't have
the same type as a normal iterator. You can get at the
underlying normal iterator using the base()
function on the
reverse iterator, but be careful; it is one behind the position the
reverse iterator is pointing to. For example, if you write
temp.assign( find( value.begin(), value.end(), '\"' ),
find( value.rbegin(), value.rend(), '\"').base() );
, the trailing '"'
will be part of the resulting string.
This particular behavior is often what you want when you're using the results as a beginning iterator:
std::string( std::find( fn.rbegin(), fn.rend(), '.' ), fn.end() )
, for example, will give you all of the text after the last
'.'
. When using the results of a find with reverse iterators
as the end criteron, you'll usually need to save it in
a variable, and "correct" it in some way.
Finally, you should be extremely cautious about using the
results of two finds to define a range, like you do above. If
there's no '"'
in your text, for example, you'll end up with
the equivalent of:
temp.assign( value.end(), value.begin() );
, which isn't going to work.
As an example, if you don't want the '"'
characters, I think the
following should work:
// Returns an empty string if there are not two " chars.
std::string
extractQuoted( std::string const& original )
{
// end points to one after the last '"', or begin() if no '"'.
std::string::const_iterator end
= std::find( original.rbegin(), original.rend(), '"' ).base();
if ( end != original.begin() ) {
-- end; // Since we don't want the '"' in the final string
}
return std::string( std::find( original.begin(), end, '"' ), end );
}
(It's off the top of my head, so no guarantees, but it should get you started in the right direction.)
Upvotes: 3
Reputation:
You can also use
value.erase(0, value.find('\"') + 1);
value.erase(value.rfind('\"'), value.size());
Assuming the string will always contain atleast two "
s
Upvotes: 0
Reputation: 7776
If you want to use reverse_itertators, call .base() on them to the underlying iterator type. e.g.
value.erase(find(value.begin(), value.end(), '\"'));
value.erase(find(value.rbegin(), value.rend(), '\"').base());
might do the trick.
Upvotes: 1