Range - Char literal question

Hi, I need to iterate thru strings (For various reasons, I can't use string or vector<char> containers). I found that boost::range exactly fits the bill for me. I get all the convenience of an iterator (from as_literal.hpp). I have a piece of code char* char_s = "I am fine"; char *cp; std::size_t sz = strlen(char_s); const char* str_end1 = str_begin( char_s ) + sz; for (cp = str_begin(char_s); cp != str_end(char_s); ++cp) cout << *cp; I have couple of questions: 1. In the loop, boost::range seems to be calling strlen every iteration. This is an overhead. I was wondering if there's a way I can pass in the length myself so that boost::range would use it and avoid calling strlen(). 2. If it's not possible, is there a way for me to use iterators (boost or non-boost) over char strings? Thanks so much in advance for your help, Anant The information contained in this email message and its attachments is intended only for the private and confidential use of the recipient(s) named above, unless the sender expressly agrees otherwise. Transmission of email over the Internet is not a secure communications medium. If you are requesting or have requested the transmittal of personal data, as defined in applicable privacy laws by means of email or in an attachment to email, you must select a more secure alternate means of transmittal that supports your obligations to protect such personal data. If the reader of this message is not the intended recipient and/or you have received this email in error, you must take no action based on the information in this email and you are hereby notified that any dissemination, misuse or copying or disclosure of this communication is strictly prohibited. If you have received this communication in error, please notify us immediately by email and delete the original message.

On Mon, Oct 18, 2010 at 9:24 PM, Rao, Anant
Hi,
I need to iterate thru strings (For various reasons, I can’t use string or vector<char> containers).
I found that boost::range exactly fits the bill for me. I get all the convenience of an iterator (from as_literal.hpp).
I have a piece of code
char* char_s = "I am fine";
char *cp;
std::size_t sz = strlen(char_s);
const char* str_end1 = str_begin( char_s ) + sz;
for (cp = str_begin(char_s); cp != str_end(char_s); ++cp)
cout << *cp;
I have couple of questions:
1. In the loop, boost::range seems to be calling strlen every iteration. This is an overhead. I was wondering if there’s a way I can pass in the length myself so that boost::range would use it and avoid calling strlen().
2. If it’s not possible, is there a way for me to use iterators (boost or non-boost) over char strings?
I'm not entirely sure I understand your question, but does this meet your needs... std::for_each( boost::begin(char_s), boost::end(char_s), your_functor ); or even BOOST_FOREACH( char c, char_s ) { cout << c; } HTH - Rob.

On Mon, Oct 18, 2010 at 9:24 PM, Rao, Anant
Hi,
I need to iterate thru strings (For various reasons, I can’t use string or vector<char> containers).
I found that boost::range exactly fits the bill for me. I get all the convenience of an iterator (from as_literal.hpp).
I have a piece of code
char* char_s = "I am fine";
char *cp;
std::size_t sz = strlen(char_s);
const char* str_end1 = str_begin( char_s ) + sz;
for (cp = str_begin(char_s); cp != str_end(char_s); ++cp)
cout << *cp;
I have couple of questions:
1. In the loop, boost::range seems to be calling strlen every iteration. This is an overhead. I was wondering if there’s a way I can pass in the length myself so that boost::range would use it and avoid calling strlen().
Indeed in the code snippet provided it would be called every iteration.
Since you could simply store the end and compare of course.
However the issue is a little artifical because you would normally have an
algorithm which you which to apply to a range. In your example, your
algorithm is simply to stream each character. This can be achieved by a
number of different approaches.
The most direct standard approach is:
std::cout << char_s;
The most direct range-based approach available in boost 1.43 and greater is:
#include <ostream>
#include
or non-boost) over char strings?
It is possible to use iterators over char strings. This does not require Boost.Range or even Boost. The C++ standard carefully designed iterators such that pointers are models of the Random Access Iterator Concept. Hence you can do this: #include <algorithm> #include <iostream> const char* char_s = "abcd"; std::copy( char_s, char_s + strlen(char_s), std::ostream_iterator<int>(std::cout) );
Thanks so much in advance for your help,
Anant
I hope this answers your question satisfactorily. Are you avoiding string and vector<char> to eliminate heap operations for small strings? Decent implementations of string with the small buffer optimization are fast enough for almost all purposes. Otherwise it might be worth implementing or using a fixed string. I would like to stress though that the final container type of a Boost.Range idiomatic design would be unimportant to the algorithm. The algorithm would merely deal in models of the Range Concepts, please see http://www.boost.org/doc/libs/1_44_0/libs/range/doc/html/range/concepts.html.
The power of this separation is exemplified by your example. If you decide to implement a new fixed string class you would still be able to utilise the string algorithms within Boost.Algorithm despite these never having been designed for use with your new class. Best wishes, Neil Groves

Hi, I have a 'char *'. I need to be able to traverse thru the string in both fwd and reverse directions. Say, I have a string 'world'. I will start with a fwd iter pointing at 'w' and start traversing. When I reach the letter 'r', I might need to start traversing in the backward direction i.e., the next char should be 'o' and I might again need to traverse fwd. In other words, the iter should be easily convertible between the two directions. (If it could be done with relatively low cost, that's all the more better.) Thanks so much in advance, Anant Ps: I looked at range - str_rbegin, str_rend. Also, David Abraham et al's pdf doc on reverse iterator. I still didn't understand how to get a nice iter that traverses both directions easily. I have a big gap in the understanding - I am not sure if I need to use a range here or boost::reverse_iterator or ... Thanks again. The information contained in this email message and its attachments is intended only for the private and confidential use of the recipient(s) named above, unless the sender expressly agrees otherwise. Transmission of email over the Internet is not a secure communications medium. If you are requesting or have requested the transmittal of personal data, as defined in applicable privacy laws by means of email or in an attachment to email, you must select a more secure alternate means of transmittal that supports your obligations to protect such personal data. If the reader of this message is not the intended recipient and/or you have received this email in error, you must take no action based on the information in this email and you are hereby notified that any dissemination, misuse or copying or disclosure of this communication is strictly prohibited. If you have received this communication in error, please notify us immediately by email and delete the original message.

2010/11/1 Rao, Anant
Hi, I have a ‘char *’. I need to be able to traverse thru the string in both fwd and reverse directions. Say, I have a string ‘world’. I will start with a fwd iter pointing at ‘w’ and start traversing. When I reach the letter ‘r’, I might need to start traversing in the backward direction i.e., the next char should be ‘o’ and I might again need to traverse fwd.
How will You be traversing? Won't operators ++ and -- on a plain iterator/char* suffice? Regards Kris

Thanks Krzysztof, Patrick! While it’s true that a char* seems to be equivalent to an iterator (in this case), I prefer the iterator/reverse_iterator much better. For example, if I use an iterator and it reaches end(), I can do --it to get to the last char. In a char * model, once I reach the NULL ptr (at the end of the string), I can’t back-track. Similarly, rbegin()/reverse_iter. Maintaining a sentinel value for the start of a string is more difficult (other than indices). IMHO, those are the solid advantages I see with an iterator. I re-read the article published by David Abrahams et al on ‘reverse_iterator’ (http://www.boost.org/doc/libs/1_44_0/libs/iterator/doc/reverse_iterator.html...) and felt it’s adequate for my purposes. Basically, I will use that reverse_iterator for both fwd and reverse traversals by using ++ and --. A couple of simple questions I have: - Why is it not possible to define a boost::iterator as easily as a boost::reverse_iterator on a char * string as in the above web link? (Again, it doesn’t block me – as I mentioned, I’ll just use a reverse_iter and use ++ and – on it to satisfy my needs. More of curiosity). - Looks like boost::reverse_iterator can’t be assigned to; can only be created. If I need to define it as a class member that needs to be made to point to diff strings as the program progresses, it doesn’t seem to be possible. So, I’m thinking of using a ptr to a boost::reverse_iterator so that I can re-seat the reverse_iterator to diff strings. Is this a convoluted approach or correct approach (given my needs)? If former, what’d be the correct approach? Thanks again, Anant From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Patrick Horgan Sent: Monday, November 01, 2010 4:34 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] [Iterators] iterators over char * On 11/01/2010 01:16 PM, Rao, Anant wrote: Hi, I have a ‘char *’. I need to be able to traverse thru the string in both fwd and reverse directions. A char* is a reversible iterator already. Reversible iterators are modeled to look like pointers. Patrick The information contained in this email message and its attachments is intended only for the private and confidential use of the recipient(s) named above, unless the sender expressly agrees otherwise. Transmission of email over the Internet is not a secure communications medium. If you are requesting or have requested the transmittal of personal data, as defined in applicable privacy laws by means of email or in an attachment to email, you must select a more secure alternate means of transmittal that supports your obligations to protect such personal data. If the reader of this message is not the intended recipient and/or you have received this email in error, you must take no action based on the information in this email and you are hereby notified that any dissemination, misuse or copying or disclosure of this communication is strictly prohibited. If you have received this communication in error, please notify us immediately by email and delete the original message.

2010/11/2 Rao, Anant
While it’s true that a char* seems to be equivalent to an iterator (in this case), I prefer the iterator/reverse_iterator much better. For example, if I use an iterator and it reaches end(), I can do --it to get to the last char. In a char * model, once I reach the NULL ptr (at the end of the string), I can’t back-track.
I think You are confusing NULL pointer with null character.
Similarly, rbegin()/reverse_iter. Maintaining a sentinel value for the start of a string is more difficult (other than indices). IMHO, those are the solid advantages I see with an iterator.
I re-read the article published by David Abrahams et al on ‘reverse_iterator’ (http://www.boost.org/doc/libs/1_44_0/libs/iterator/doc/reverse_iterator.html...)
and felt it’s adequate for my purposes. Basically, I will use that reverse_iterator for both fwd and reverse traversals by using ++ and --.
I think You are confusing bidirectional iterator with reverse iterator
A couple of simple questions I have:
- Why is it not possible to define a boost::iterator as easily as a boost::reverse_iterator on a char * string as in the above web link? (Again, it doesn’t block me – as I mentioned, I’ll just use a reverse_iter and use ++ and – on it to satisfy my needs. More of curiosity).
Because char* is an iterator itself.
- Looks like boost::reverse_iterator can’t be assigned to; can only be created. If I need to define it as a class member that needs to be made to point to diff strings as the program progresses, it doesn’t seem to be possible. So, I’m thinking of using a ptr to a boost::reverse_iterator so that I can re-seat the reverse_iterator to diff strings. Is this a convoluted approach or correct approach (given my needs)? If former, what’d be the correct approach?
I think it can be assigned to, but that is irrelevant, because You don't seem to need it anyway. Regards, Kris.

Hi,
I need to iterate over a char string and I wrote the code as follows:
char *s = "abcdefg";
iterator_range

2010/12/10 Rao, Anant
char *s = "abcdefg";
iterator_range
ir( &s[0], &s[ strlen(s) ] ); char *cp;
boost::range_reverse_iterator< char*>::type irb = boost::rbegin( ir );
boost::range_reverse_iterator< char*>::type ire = boost::rend( ir );
for (; irb != ire; ++irb)
{
cout << "reverse cp [" << *irb << "]\n";
}
This works like a charm – both in fwd and reverse traversal.
However, what I want is – in reverse traversal also, I want to use the same pointer (“cp” in this case). In other words, I want to use the same pointer to traverse in both directions.
Here’s what I want to be able to write, but get a compile error with both attempts and I was wondering if you could help.
Option 1:
for (cp = boost::rbegin(ir); cp != boost::rend(ir); ++cp)
{
cout << "cp reverse in ri [" << *cp << "]\n";
}
Option 2:
while( cp != ire )
{
//Do something
cp++
}
I think You can't do neither. Why do You want to do that? Regards, Kris

Hi Kris,
Thanks for a quick response!
This is part of a larger issue that I'm addressing.
So, there's absolutely no way to use the same ptr to traverse backwards? I tried the options based on my limited knowledge, but if there're other options, please let me know (using the same ptr).
It's ironic a simple pointer could go fwd, but not back.
Anant
From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Krzysztof Czainski
Sent: Friday, December 10, 2010 9:00 AM
To: boost-users@lists.boost.org
Subject: Re: [Boost-users] Range_iterator - char* - reverse
2010/12/10 Rao, Anant

De : Rao, Anant
So, there's absolutely no way to use the same ptr to traverse backwards? I tried the options based on my limited knowledge, but if there're other options, please let me know (using the same ptr).
It's ironic a simple pointer could go fwd, but not back.
Well, it can go forward or back, but you have to ask it. "++" to go forward, "--" to go back.
char *cp; boost::range_reverse_iterator< char*>::type irb = boost::rbegin( ir ); boost::range_reverse_iterator< char*>::type ire = boost::rend( ir ); for (; irb != ire; ++irb) { cout << "reverse cp [" << *irb << "]\n"; }
This works like a charm - both in fwd and reverse traversal.
This works because irb is a reverse iterator, with operator++ defined to go "backwards". That behavior will not change because the initial value happens to come from a reverse_iterator. A char* is a char*, regardless of the source of its initial value.
Option 1: for (cp = boost::rbegin(ir); cp != boost::rend(ir); ++cp) { cout << "cp reverse in ri [" << *cp << "]\n"; }
cp is a char* here, and "++" on a char* is defined to increment it, moving it "forward". To move it "backward", use "--"

Hi Eric,
Yes, it was a typo on my part to use ++ when I shd have had a --.
But, I was talking about the compile error. That is, even if I had a '--', it would still complain.
The offending line is:
while( cp != ire )
{
//Do something
cp--;
}
Please bear with me as I (hopefully) make my requirement statement more precise:
Fwd:
iterator_range
So, there's absolutely no way to use the same ptr to traverse backwards? I tried the options based on my limited knowledge, but if there're other options, please let me know (using the same ptr).
It's ironic a simple pointer could go fwd, but not back.
Well, it can go forward or back, but you have to ask it. "++" to go forward, "--" to go back.
char *cp; boost::range_reverse_iterator< char*>::type irb = boost::rbegin( ir ); boost::range_reverse_iterator< char*>::type ire = boost::rend( ir ); for (; irb != ire; ++irb) { cout << "reverse cp [" << *irb << "]\n"; }
This works like a charm - both in fwd and reverse traversal.
This works because irb is a reverse iterator, with operator++ defined to go "backwards". That behavior will not change because the initial value happens to come from a reverse_iterator. A char* is a char*, regardless of the source of its initial value.
Option 1: for (cp = boost::rbegin(ir); cp != boost::rend(ir); ++cp) { cout << "cp reverse in ri [" << *cp << "]\n"; }
cp is a char* here, and "++" on a char* is defined to increment it, moving it "forward". To move it "backward", use "--" _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users The information contained in this email message and its attachments is intended only for the private and confidential use of the recipient(s) named above, unless the sender expressly agrees otherwise. Transmission of email over the Internet is not a secure communications medium. If you are requesting or have requested the transmittal of personal data, as defined in applicable privacy laws by means of email or in an attachment to email, you must select a more secure alternate means of transmittal that supports your obligations to protect such personal data. If the reader of this message is not the intended recipient and/or you have received this email in error, you must take no action based on the information in this email and you are hereby notified that any dissemination, misuse or copying or disclosure of this communication is strictly prohibited. If you have received this communication in error, please notify us immediately by email and delete the original message.

2010/12/10 Rao, Anant
Hi Eric, Yes, it was a typo on my part to use ++ when I shd have had a --. But, I was talking about the compile error. That is, even if I had a '--', it would still complain. The offending line is:
while( cp != ire ) { //Do something cp--; }
Please bear with me as I (hopefully) make my requirement statement more precise:
Fwd: iterator_range
ir( &s[0], &s[ strlen(s) ] ); for (cp = (char*)ir.begin(); cp != (char*)ir.end(); ++cp) { cout << "cp in ri [" << *cp << "]\n"; }
I want similar code (using 'cp') to traverse backwards using 'ir' or another container-in-reverse mode.
The thing is, a pointer is an iterator, but an iterator is not necessarily a
pointer. The iterator returned by boost::begin(ir) happens to be char*,
because ir is an iterator_range
participants (7)
-
Eric MALENFANT
-
Igor R
-
Krzysztof Czainski
-
Neil Groves
-
Patrick Horgan
-
Rao, Anant
-
Robert Jones