Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Checking the available range while iterating through a string

Reply
Thread Tools

Checking the available range while iterating through a string

 
 
Ángel José Riesgo
Guest
Posts: n/a
 
      02-16-2011
Hi,

I'm writing some code that parses a string and tries to find some
tokens and extract some data from the string. The problem is simple
and the code I've just written works fine. However, I need some ugly
casts to get rid of a signed/unsigned mismatch warning, and I was
wondering if there may be a more elegant way of doing this. A dumbed
down version of my code follows:

#include <string>

const std::string kToken = "TOKEN";

void FindToken(std::string::const_iterator& position,
std::string::const_iterator end)
{
std::string::size_type tokenLength = kToken.length();
if(tokenLength <= (end - position)) // <- Signed - unsigned
conversion warning here.
{
std::string expectedToken(position, position + tokenLength);
if(expectedToken == kToken)
position += tokenLength; // The token has been found and the
iterator is advanced before returning.
}
}

Basically, I've moved the bit of code I'm interested in to the above
function FindToken, which tries to find a certain token ("TOKEN"), and
advances the "position" iterator by the token's length if it is found.
Otherwise, the function returns quietly leaving the iterator
unchanged. In the actual code, I can assume that the two iterators
come from the same string object and that position <= end.

Now the problem with the above code (building it with MSVC 10) is that
I get a warning because of the conversion between the signed type
returned by the (end - position) iterator subtraction and the
std::string::size_type unsigned integer type. I can
static_cast<std::string::size_type> the warning away, of course, but
it's a bit ugly, so I was wondering if anyone knows of a way of doing
this sort of thing without either warnings or casts.

Thanks in advance,

Ángel José Riesgo
 
Reply With Quote
 
 
 
 
itaj sherman
Guest
Posts: n/a
 
      02-16-2011
On Feb 16, 9:41 pm, Ángel José Riesgo <(E-Mail Removed)> wrote:
> Hi,
>
> I'm writing some code that parses a string and tries to find some
> tokens and extract some data from the string. The problem is simple
> and the code I've just written works fine. However, I need some ugly
> casts to get rid of a signed/unsigned mismatch warning, and I was
> wondering if there may be a more elegant way of doing this. A dumbed
> down version of my code follows:
>
> #include <string>
>
> const std::string kToken = "TOKEN";
>
> void FindToken(std::string::const_iterator& position,
> std::string::const_iterator end)
> {
> std::string::size_type tokenLength = kToken.length();
> if(tokenLength <= (end - position)) // <- Signed - unsigned
> conversion warning here.
> {
> std::string expectedToken(position, position + tokenLength);
> if(expectedToken == kToken)
> position += tokenLength; // The token has been found and the
> iterator is advanced before returning.
> }
>
> }
>


I think you should either work with indexs or with iterators. You're
trying to mix both.

With indexs use:
string::length()
string::at()
string::size_type

with indexs use:
string::begin()
string::end()
string::iterator
string::iterator::difference_type

Most of the code uses iterators. You just need to fix 1 line:

//std::string::size_type tokenLength = kToken.length();
std::string::const_iterator::difference_type const tokenLength
= ( kToken.end() - kToken.begin() );

Then your concepts will match, and you won't be needing any type
conversions.

itaj
 
Reply With Quote
 
 
 
 
itaj sherman
Guest
Posts: n/a
 
      02-16-2011
On Feb 17, 12:42 am, itaj sherman <(E-Mail Removed)> wrote:
> On Feb 16, 9:41 pm, Ángel José Riesgo <(E-Mail Removed)> wrote:
>


>
> With indexs use:
> string::length()
> string::at()
> string::size_type
>
> with indexs use:


Yeah, obviously I meant "with iterators use:"

> string::begin()
> string::end()
> string::iterator
> string::iterator::difference_type
>


itaj
 
Reply With Quote
 
itaj sherman
Guest
Posts: n/a
 
      02-16-2011

On Feb 17, 12:42 am, itaj sherman <(E-Mail Removed)> wrote:
> On Feb 16, 9:41 pm, Ángel José Riesgo <(E-Mail Removed)> wrote:
>
>


Sorry, I type faster than I think:

>
> string::iterator::difference_type
>


that's std::string::difference_type

>
> //std::string::size_type tokenLength = kToken.length();
> std::string::const_iterator::difference_type const tokenLength
> = ( kToken.end() - kToken.begin() );
>


that's
std::string::difference_type const tokenLength
= ( kToken.end() - kToken.begin() );


Oh, and I don't mean always ever use either iteroator or indexes. I
mean don't mix them in wrong ways.

itaj
 
Reply With Quote
 
Ángel José Riesgo
Guest
Posts: n/a
 
      02-17-2011
On Feb 16, 10:17*pm, Leigh Johnston <(E-Mail Removed)> wrote:
> On 16/02/2011 20:11, Paavo Helde wrote:
>
>
>
>
>
>
>
>
>
> > Ingel José Riesgo<(E-Mail Removed)> *wrote in
> >news:(E-Mail Removed):

>
> >> Hi,

>
> >> I'm writing some code that parses a string and tries to find some
> >> tokens and extract some data from the string. The problem is simple
> >> and the code I've just written works fine. However, I need some ugly
> >> casts to get rid of a signed/unsigned mismatch warning, and I was
> >> wondering if there may be a more elegant way of doing this. A dumbed
> >> down version of my code follows:

>
> >> #include<string>

>
> >> const std::string kToken = "TOKEN";

>
> >> void FindToken(std::string::const_iterator& *position,
> >> std::string::const_iterator end)
> >> {
> >> * * * std::string::size_type tokenLength = kToken.length();
> >> * * * if(tokenLength<= (end - position)) //<- Signed - unsigned
> >> conversion warning here.
> >> * * * {
> >> * * * * * *std::string expectedToken(position, position + tokenLength);
> >> * * * * * *if(expectedToken == kToken)
> >> * * * * * * * * position += tokenLength; // The token has been found
> >> * * * * * * * * and the
> >> iterator is advanced before returning.
> >> * * * }
> >> }

>
> >> Basically, I've moved the bit of code I'm interested in to the above
> >> function FindToken, which tries to find a certain token ("TOKEN"), and
> >> advances the "position" iterator by the token's length if it is found.
> >> Otherwise, the function returns quietly leaving the iterator
> >> unchanged. In the actual code, I can assume that the two iterators
> >> come from the same string object and that position<= end.

>
> >> Now the problem with the above code (building it with MSVC 10) is that
> >> I get a warning because of the conversion between the signed type
> >> returned by the (end - position) iterator subtraction and the
> >> std::string::size_type unsigned integer type. I can
> >> static_cast<std::string::size_type> *the warning away, of course, but
> >> it's a bit ugly, so I was wondering if anyone knows of a way of doing
> >> this sort of thing without either warnings or casts.

>
> >> Thanks in advance,

>
> > The warning can be avoided by writing:

>
> > * *if(position+tokenLength<= end)

>
> This looks dubious: position + tokenLength could be an invalid iterator
> if it is past std::string::end(). *The static_cast version is fine as
> there is nothing wrong with using the C++ style casts.
>


Thanks for your suggestions. I forgot to mention that I had actually
tried the if(position+tokenLength<= end) approach. That compiles
without any warnings, but then I was bitten by a run-time assertion
coming from the checked iterators because, as Leigh explains, the
addition operation was taking the value past the end iterator when the
available range was too short.

The C++ static_casts are not too bad, but I always feel that casts are
somehow telling me that I'm being sloppy with the types. In another
answer in this thread, itaj sherman has recommended comparing the
iterator subtraction with another iterator subtraction (kToken.end() -
kToken.begin()) so that the types match. I like the consistency of
that approach, so I'm going to try that.

>
> > However, I would redesign this function so I could use
> > std::string::compare() and avoid this explicit check and also a needless
> > construction of the temporary string expectedToken.

>
> I agree.
>
> /Leigh


I will look into that. Anyway, I'm not too worried about the temporary
string. As long as the code is readable and robust (this is not a
performance-intensive thing), it should be fine.

Ángel José Riesgo
 
Reply With Quote
 
Ángel José Riesgo
Guest
Posts: n/a
 
      02-17-2011
On Feb 16, 11:59*pm, itaj sherman <(E-Mail Removed)> wrote:
> On Feb 17, 12:42 am, itaj sherman <(E-Mail Removed)> wrote:
>
> > On Feb 16, 9:41 pm, Ángel José Riesgo <(E-Mail Removed)> wrote:

>
> Sorry, I type faster than I think:
>
>
>
> > string::iterator::difference_type

>
> that's std::string::difference_type
>
>
>
> > //std::string::size_type tokenLength = kToken.length();
> > std::string::const_iterator::difference_type const tokenLength
> > * = ( kToken.end() - kToken.begin() );

>
> that's
> std::string::difference_type const tokenLength
> * = ( kToken.end() - kToken.begin() );
>
> Oh, and I don't mean always ever use either iteroator or indexes. I
> mean don't mix them in wrong ways.
>
> itaj


Thanks. That's the sort of consistency I was looking for. Now that you
mention it, it seems quite straightforward: comparing a subtraction of
iterators with, well, a subtraction of iterators. It makes perfect
sense.

Ángel José Riesgo
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      02-17-2011
On Feb 16, 7:41 pm, Ángel José Riesgo <(E-Mail Removed)> wrote:

> I'm writing some code that parses a string and tries to find some
> tokens and extract some data from the string. The problem is simple
> and the code I've just written works fine. However, I need some ugly
> casts to get rid of a signed/unsigned mismatch warning, and I was
> wondering if there may be a more elegant way of doing this. A dumbed
> down version of my code follows:


> #include <string>


> const std::string kToken = "TOKEN";


> void FindToken(std::string::const_iterator& position,
> std::string::const_iterator end)
> {
> std::string::size_type tokenLength = kToken.length();
> if(tokenLength <= (end - position)) // <- Signed - unsigned
> conversion warning here.
> {
> std::string expectedToken(position, position + tokenLength);
> if(expectedToken == kToken)
> position += tokenLength; // The token has been found and the
> iterator is advanced before returning.
> }
> }


> Basically, I've moved the bit of code I'm interested in to the above
> function FindToken, which tries to find a certain token ("TOKEN"), and
> advances the "position" iterator by the token's length if it is found.
> Otherwise, the function returns quietly leaving the iterator
> unchanged. In the actual code, I can assume that the two iterators
> come from the same string object and that position <= end.


> Now the problem with the above code (building it with MSVC 10) is that
> I get a warning because of the conversion between the signed type
> returned by the (end - position) iterator subtraction and the
> std::string::size_type unsigned integer type. I can
> static_cast<std::string::size_type> the warning away, of course, but
> it's a bit ugly, so I was wondering if anyone knows of a way of doing
> this sort of thing without either warnings or casts.


Using int instead of std::string::size_type should get rid of
the error. But you're doing a lot of extra work; my version
would be just:

if ( static_cast<size_t>(end - position) >= kToken.size()
&& std::equal(kToken.begin(), kToken.end(), position) )
position += kToken.size();

(Here, you need the static_cast, because of a design flaw in the
standard library; kToken.size() should return int.)

--
James Kanze
 
Reply With Quote
 
itaj sherman
Guest
Posts: n/a
 
      02-17-2011
On Feb 17, 6:18*pm, James Kanze <(E-Mail Removed)> wrote:
> On Feb 16, 7:41 pm, Ángel José Riesgo <(E-Mail Removed)> wrote:
>
>
>
> > I'm writing some code that parses a string and tries to find some
> > tokens and extract some data from the string. The problem is simple
> > and the code I've just written works fine. However, I need some ugly
> > casts to get rid of a signed/unsigned mismatch warning, and I was
> > wondering if there may be a more elegant way of doing this. A dumbed
> > down version of my code follows:
> > #include <string>
> > const std::string kToken = "TOKEN";
> > void FindToken(std::string::const_iterator& position,
> > std::string::const_iterator end)
> > {
> > * * * * std::string::size_type tokenLength = kToken.length();
> > * * * * if(tokenLength <= (end - position)) // <- Signed - unsigned
> > conversion warning here.
> > * * * * {
> > * * * * * * * * std::string expectedToken(position, position + tokenLength);
> > * * * * * * * * if(expectedToken == kToken)
> > * * * * * * * * * * * * position += tokenLength; // The token has been found and the
> > iterator is advanced before returning.
> > * * * * }
> > }
> > Basically, I've moved the bit of code I'm interested in to the above
> > function FindToken, which tries to find a certain token ("TOKEN"), and
> > advances the "position" iterator by the token's length if it is found.
> > Otherwise, the function returns quietly leaving the iterator
> > unchanged. In the actual code, I can assume that the two iterators
> > come from the same string object and that position <= end.
> > Now the problem with the above code (building it with MSVC 10) is that
> > I get a warning because of the conversion between the signed type
> > returned by the (end - position) iterator subtraction and the
> > std::string::size_type unsigned integer type. I can
> > static_cast<std::string::size_type> the warning away, of course, but
> > it's a bit ugly, so I was wondering if anyone knows of a way of doing
> > this sort of thing without either warnings or casts.

>
> Using int instead of std::string::size_type should get rid of
> the error. *But you're doing a lot of extra work; my version
> would be just:
>
> * * if ( static_cast<size_t>(end - position) >= kToken.size()
> * * * * * * && std::equal(kToken.begin(), kToken.end(), position) )
> * * * * position += kToken.size();
>
> (Here, you need the static_cast, because of a design flaw in the
> standard library; kToken.size() should return int.)
>
> --
> James Kanze


On Feb 17, 6:18 pm, James Kanze <(E-Mail Removed)> wrote:
> On Feb 16, 7:41 pm, Ángel José Riesgo <(E-Mail Removed)> wrote:
>


>
> (Here, you need the static_cast, because of a design flaw in the
> standard library; kToken.size() should return int.)
>


kToken.size() should return int specifically?
What if int is smaller than std::string::difference_type?

Does in mean there shouldn't be a container::size_type, and it should
all be container::difference_type?
Is there any good reason why there is such a distinction in the
standard containers?

itaj
 
Reply With Quote
 
itaj sherman
Guest
Posts: n/a
 
      02-17-2011
On Feb 17, 6:47 pm, Leigh Johnston <(E-Mail Removed)> wrote:
> On 17/02/2011 16:44, itaj sherman wrote:
>
> Kanze is trolling; ignore him.
>
> /Leigh


When I read comp.lang.c++.*, Kanze is one of the few people that I go
around looking specifically for their posts. I usually find his
answers and opinions ingeniously accurate and effective.

I hope he ellaborates on what I asked about his post here.

I don't see how your posts in this thread do any of that.
I've noticed your "Troll meets Monolith" thread, and I think they fit
better in that thread.
If Kanze is a troll as you say I'm sure he would join your thread and
you can converse about it there.

itaj

 
Reply With Quote
 
itaj sherman
Guest
Posts: n/a
 
      02-17-2011
On Feb 17, 7:07*pm, Leigh Johnston <(E-Mail Removed)> wrote:
> On 17/02/2011 16:59, itaj sherman wrote:
>
>
> > I don't see how your posts in this thread do any of that.

>
> In this thread I pointed out an error that somebody made whilst trying
> to avoid a cast which is kind of ironic. *There is nothing wrong with
> using the C++ style casts.
>


I was refferring to your replies under Kanze's answer, not to your
first one.

itaj
 
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
OK to delete hash pairs while iterating through it? Jerry Krinock Perl Misc 7 09-12-2008 08:00 PM
Erasing in a vector while iterating through it =?iso-8859-1?q?Erik_Wikstr=F6m?= C++ 3 06-11-2007 04:10 PM
modifying a list while iterating through dustin.getz@gmail.com Python 4 02-26-2007 10:21 PM
Good practice? modifying vector while iterating through it Alan C++ 5 02-19-2007 05:28 AM
getting the index while iterating through a list Fernando Rodríguez Python 4 05-12-2004 03:30 PM



Advertisments