split_iterator<string::iterator> example

hi, Can someone please tell me where I can find example of split_iterator<string::iterator> If I have 2 split_iterator<string::iterator>s, how can I compare the 2 strings that the split_iterator pointing to? Thank you.

Hi, There is realy no magic there. You just need to realize, that you are not getting a string, rather a range. Range is a generalization of a pair of iterators. In case of split_iterator, these iterators point to first and one past the last character of the current token. Example can be found in /boost/libs/algorithm/string/example/split_example.cpp Regards, Pavol. Meryl Silverburgh wrote:
hi,
Can someone please tell me where I can find example of split_iterator<string::iterator>
If I have 2 split_iterator<string::iterator>s, how can I compare the 2 strings that the split_iterator pointing to?
Thank you. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On 2/20/07, Pavol Droba <droba@topmail.sk> wrote:
Hi,
There is realy no magic there. You just need to realize, that you are not getting a string, rather a range. Range is a generalization of a pair of iterators.
In case of split_iterator, these iterators point to first and one past the last character of the current token.
Example can be found in /boost/libs/algorithm/string/example/split_example.cpp
Regards, Pavol.
Thanks for your help. I have another question, how can I can i terminate the for loop when loop using string_split? class integer_compare { public: bool operator() (const string_split::value_type &a, const string_split::value_type &b) { // how can I iterate thru the string? how can i terminate the for loop? for (const string_split sitr = a; sitr != ???; sitr++) { // print out each substring (after '/' is stripped out) cout << copy_range<std::string>(*sitr) << endl; } return true; } };
Meryl Silverburgh wrote:
hi,
Can someone please tell me where I can find example of split_iterator<string::iterator>
If I have 2 split_iterator<string::iterator>s, how can I compare the 2 strings that the split_iterator pointing to?
Thank you. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Meryl Silverburgh wrote:
On 2/20/07, Pavol Droba <droba@topmail.sk> wrote:
Hi,
There is realy no magic there. You just need to realize, that you are not getting a string, rather a range. Range is a generalization of a pair of iterators.
In case of split_iterator, these iterators point to first and one past the last character of the current token.
Example can be found in /boost/libs/algorithm/string/example/split_example.cpp
Regards, Pavol.
Thanks for your help. I have another question, how can I can i terminate the for loop when loop using string_split?
class integer_compare { public: bool operator() (const string_split::value_type &a, const string_split::value_type &b) { // how can I iterate thru the string? how can i terminate the for loop?
for (const string_split sitr = a; sitr != ???; sitr++) {
// print out each substring (after '/' is stripped out) cout << copy_range<std::string>(*sitr) << endl;
} return true; } };
First of all, I don't understand your example. string_split::value_type is definitely not another split_iterator. it's type is (as I have mentioned in some previous mail) iterator_range<string::iterator>. As for the loop termination, default-initialized split_iterator (i.e. string_split) functions as a terminator. Alternatively you can check the eof() method. Regards, Pavol.

On 2/20/07, Pavol Droba <droba@topmail.sk> wrote:
Meryl Silverburgh wrote:
On 2/20/07, Pavol Droba <droba@topmail.sk> wrote:
Hi,
There is realy no magic there. You just need to realize, that you are not getting a string, rather a range. Range is a generalization of a pair of iterators.
In case of split_iterator, these iterators point to first and one past the last character of the current token.
Example can be found in /boost/libs/algorithm/string/example/split_example.cpp
Regards, Pavol.
Thanks for your help. I have another question, how can I can i terminate the for loop when loop using string_split?
class integer_compare { public: bool operator() (const string_split::value_type &a, const string_split::value_type &b) { // how can I iterate thru the string? how can i terminate the for loop?
for (const string_split sitr = a; sitr != ???; sitr++) {
// print out each substring (after '/' is stripped out) cout << copy_range<std::string>(*sitr) << endl;
} return true; } };
First of all, I don't understand your example. string_split::value_type is definitely not another split_iterator. it's type is (as I have mentioned in some previous mail) iterator_range<string::iterator>.
Pavol, Thank for your help. I thought you said 'The question marks can be substituted by string_split::value_type'. In one of our previous exchange. That is why I am using 'string_split::value_type' not 'iterator_range<string::iterator>' Sorry if I mis-understand what you teach me. From: Pavol Droba <droba@topmail.sk> Date: Feb 19, 2007 5:17 PM Subject: Re: [Boost-users] Using Boost string library To: boost-users@lists.boost.org Hi, Meryl Silverburgh wrote: <snip>
The problem is with template instantiation. Since you are passing "string" and not "const string" as an argument to make_split_iterator, the resulting type is actualy split_iterator<string::iterator>. This is not the same (nor convertible) to split_iterator<string::const_iterator>.
So the simple fix would be to change the definition of the string_split to split_iterator<string::iterator>.
In addition, you will need to implement integer_compare.
In addition, you will need to implement integer_compare. I have not included it in may mail.
Thanks. I notice that. Can you please help me understand how to implement integer_compare (a predicate comparision object)?
What are the input type? bool operator() (const ? &a, const ? &b) ?
and if the input strings are '/1/1/5' and '1/1/10' what will be passed to the integer_compare?
It is an element comparison predicate therefore its arguments should be able to accept elements from the input sequence. So you have guessed the signature right. The question marks can be substituted by string_split::value_type. And that is an iterator_range pointing to a match found in the input string (iterator_range<string::iterator>)
As for the loop termination, default-initialized split_iterator (i.e. string_split) functions as a terminator. Alternatively you can check the eof() method.
Regards, Pavol. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Pavol,
Thank for your help. I thought you said 'The question marks can be substituted by string_split::value_type'. In one of our previous exchange.
That is why I am using 'string_split::value_type' not 'iterator_range<string::iterator>'
Sorry if I mis-understand what you teach me.
No worries. There is no problem with using string_split::value_type. It is just a typedef to iterator_range<string::iterator>. In your code, you misplaced it with string_split itself. Regards, Pavol.

On 2/20/07, Pavol Droba <droba@topmail.sk> wrote:
Pavol,
Thank for your help. I thought you said 'The question marks can be substituted by string_split::value_type'. In one of our previous exchange.
That is why I am using 'string_split::value_type' not 'iterator_range<string::iterator>'
Sorry if I mis-understand what you teach me.
No worries.
There is no problem with using string_split::value_type. It is just a typedef to iterator_range<string::iterator>. In your code, you misplaced it with string_split itself.
I change the integer_compare class to use iterator_range<string::iterator>&. And I am trying to loop thru the iterator_range inside the function() of integer_compare: bool operator() (const iterator_range<string::iterator>& a, const iterator_range<string::iterator>& b) { cout << "calling integer_compare " << endl; // expect to print out "", "1", "1", "2" for a string of "/1/1/2" for (string::iterator sitr = a.begin(); sitr != a.end(); sitr++) { cout << copy_range<std::string>(*sitr) << endl; } return true; } But I get the following error saying I cant' instantiate 'boost::range_const_iterator<char>'. Any more help is appreciated. g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"stringCompare.d" -MT"stringCompare.d" -o"stringCompare.o" "../stringCompare.cpp" ../stringCompare.cpp:58:2: warning: no newline at end of file /usr/include/boost/range/const_iterator.hpp: In instantiation of 'boost::range_const_iterator<char>': /usr/include/boost/range/iterator_range.hpp:576: instantiated from 'SeqT boost::copy_range(const Range&) [with SeqT = std::basic_string<char, std::char_traits<char>, std::allocator<char>
, Range = char]' ../stringCompare.cpp:28: instantiated from here /usr/include/boost/range/const_iterator.hpp:36: error: 'char' is not a class, struct, or union type /usr/include/boost/range/iterator.hpp: In instantiation of 'boost::range_iterator<char>': /usr/include/boost/range/iterator_range.hpp:576: instantiated from 'SeqT boost::copy_range(const Range&) [with SeqT = std::basic_string<char, std::char_traits<char>, std::allocator<char> , Range = char]' ../stringCompare.cpp:28: instantiated from here /usr/include/boost/range/iterator.hpp:37: error: 'char' is not a class, struct, or union type /usr/include/boost/range/iterator_range.hpp: In function 'SeqT boost::copy_range(const Range&) [with SeqT = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Range = char]': ../stringCompare.cpp:28: instantiated from here /usr/include/boost/range/iterator_range.hpp:576: error: no matching function for call to 'begin(const char&)' /usr/include/boost/range/iterator_range.hpp:576: error: no matching function for call to 'end(const char&)' make: *** [stringCompare.o] Error 1 make: Target `all' not remade because of errors.
Regards, Pavol. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Hi, Meryl Silverburgh wrote:
On 2/20/07, Pavol Droba <droba@topmail.sk> wrote:
Pavol,
Thank for your help. I thought you said 'The question marks can be substituted by string_split::value_type'. In one of our previous exchange.
That is why I am using 'string_split::value_type' not 'iterator_range<string::iterator>'
Sorry if I mis-understand what you teach me.
No worries.
There is no problem with using string_split::value_type. It is just a typedef to iterator_range<string::iterator>. In your code, you misplaced it with string_split itself.
I change the integer_compare class to use iterator_range<string::iterator>&.
And I am trying to loop thru the iterator_range inside the function() of integer_compare:
bool operator() (const iterator_range<string::iterator>& a,
const iterator_range<string::iterator>& b) { cout << "calling integer_compare " << endl;
// expect to print out "", "1", "1", "2" for a string of "/1/1/2" for (string::iterator sitr = a.begin(); sitr != a.end(); sitr++) {
cout << copy_range<std::string>(*sitr) << endl;
} return true; }
Please, see the iterator_range documentation: http://www.boost.org/libs/range/doc/utility_class.html#iter_range Although you changed the names of parameters, you are still using iterator_range as if it was a split_iterator. copy_range copies a *range* to a given container. when you dereference a string::iterator, you will not get a *range*, rather a single character. Instead of "for" loop you should use just cout << copy_range<std::string>(a) << endl; Regards, Pavol.

On 2/20/07, Pavol Droba <droba@topmail.sk> wrote:
Hi,
Meryl Silverburgh wrote:
On 2/20/07, Pavol Droba <droba@topmail.sk> wrote:
Pavol,
Thank for your help. I thought you said 'The question marks can be substituted by string_split::value_type'. In one of our previous exchange.
That is why I am using 'string_split::value_type' not 'iterator_range<string::iterator>'
Sorry if I mis-understand what you teach me.
No worries.
There is no problem with using string_split::value_type. It is just a typedef to iterator_range<string::iterator>. In your code, you misplaced it with string_split itself.
I change the integer_compare class to use iterator_range<string::iterator>&.
And I am trying to loop thru the iterator_range inside the function() of integer_compare:
bool operator() (const iterator_range<string::iterator>& a,
const iterator_range<string::iterator>& b) { cout << "calling integer_compare " << endl;
// expect to print out "", "1", "1", "2" for a string of "/1/1/2" for (string::iterator sitr = a.begin(); sitr != a.end(); sitr++) {
cout << copy_range<std::string>(*sitr) << endl;
} return true; }
Please, see the iterator_range documentation: http://www.boost.org/libs/range/doc/utility_class.html#iter_range
Although you changed the names of parameters, you are still using iterator_range as if it was a split_iterator.
copy_range copies a *range* to a given container. when you dereference a string::iterator, you will not get a *range*, rather a single character.
Instead of "for" loop you should use just cout << copy_range<std::string>(a) << endl;
Thanks, I did try just doing this cout << copy_range<std::string>(a) << endl; cout << copy_range<std::string>(b) << endl; But I find out that 'integer_compare' just call once, and it is an empty string. My input strings were "/1/11/2", "1/9/2". From your previous message, I understand the first time return an empty string, but I do expect integer_compare will call again and again like "1", "11", "2", "1", "9" ,"2".... But it did not happens. class integer_compare { public: // bool operator() (const string_split::value_type &a, const //string_split::value_type &b) { bool operator() (const iterator_range<string::iterator>& a, const iterator_range<string::iterator>& b) { cout << "calling integer_compare " << endl; cout << copy_range<std::string>(a) << endl; cout << copy_range<std::string>(b) << endl; /* for (string::iterator sitr = a.begin(); sitr != a.end(); sitr++) { cout << copy_range<std::string>(*sitr) << endl; }*/ return true; } }; int main(int argc, char **argv) { cout << "hello world" << endl; string s1("/1/11/2"); string s2("/1/9/3"); iterator_range<string_split> r1( make_split_iterator(s1, token_finder(is_any_of("/"))), string_split()); iterator_range<string_split> r2( make_split_iterator(s2, token_finder(is_any_of("/"))), string_split()); if(lexicographical_compare(r1.begin(), r1.end(), r2.begin(), r2.end(), integer_compare())) { cout << " s1 is less " << endl; } else { cout << " s2 is less " << endl; } }
Regards, Pavol. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Thanks, I did try just doing this cout << copy_range<std::string>(a) << endl; cout << copy_range<std::string>(b) << endl;
But I find out that 'integer_compare' just call once, and it is an empty string.
My input strings were "/1/11/2", "1/9/2". From your previous message, I understand the first time return an empty string, but I do expect integer_compare will call again and again like "1", "11", "2", "1", "9" ,"2".... But it did not happens.
Great, we are getting to the finish ;) There is just one slight problem, that I have overlooked in your code. lexicographical_compare simply forwards the call to std::lexicographical_compare http://www.sgi.com/tech/stl/lexicographical_compare.html So the given predicate (integer_compare) functions as *isless*. It means, that it should return true if the first argument is *less* then the second one. In case of equality it should return false. In your case, lexicographical_compare stopped on the first tokens, since the predicate reported that one is less then other. No other comparison was necessary to get the result. Try to change the result to false. You should be seeing the output from whole inputs. Best regards, Pavol.

On 2/20/07, Pavol Droba <droba@topmail.sk> wrote:
Thanks, I did try just doing this cout << copy_range<std::string>(a) << endl; cout << copy_range<std::string>(b) << endl;
But I find out that 'integer_compare' just call once, and it is an empty string.
My input strings were "/1/11/2", "1/9/2". From your previous message, I understand the first time return an empty string, but I do expect integer_compare will call again and again like "1", "11", "2", "1", "9" ,"2".... But it did not happens.
Great, we are getting to the finish ;) There is just one slight problem, that I have overlooked in your code.
lexicographical_compare simply forwards the call to std::lexicographical_compare http://www.sgi.com/tech/stl/lexicographical_compare.html
So the given predicate (integer_compare) functions as *isless*. It means, that it should return true if the first argument is *less* then the second one. In case of equality it should return false.
In your case, lexicographical_compare stopped on the first tokens, since the predicate reported that one is less then other. No other comparison was necessary to get the result.
Try to change the result to false. You should be seeing the output from whole inputs.
Best regards, Pavol.
Pavol, Thank you very much for your effort/time/help. Yes, I do see the output. But still one question, why my function integer_compare is being call 2 times for every sub-string? my input strings are string s1("/1/11/2"), string s2("/1/9/3"); Here is my output: calling integer_compare () () calling integer_compare () () calling integer_compare (1) (1) calling integer_compare (1) (1) calling integer_compare (11) (9) calling integer_compare (9) (11) calling integer_compare (2) (3) calling integer_compare (3) (2)
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Meryl Silverburgh wrote:
On 2/20/07, Pavol Droba <droba@topmail.sk> wrote:
Thanks, I did try just doing this cout << copy_range<std::string>(a) << endl; cout << copy_range<std::string>(b) << endl;
But I find out that 'integer_compare' just call once, and it is an empty string.
My input strings were "/1/11/2", "1/9/2". From your previous message, I understand the first time return an empty string, but I do expect integer_compare will call again and again like "1", "11", "2", "1", "9" ,"2".... But it did not happens.
Great, we are getting to the finish ;) There is just one slight problem, that I have overlooked in your code.
lexicographical_compare simply forwards the call to std::lexicographical_compare http://www.sgi.com/tech/stl/lexicographical_compare.html
So the given predicate (integer_compare) functions as *isless*. It means, that it should return true if the first argument is *less* then the second one. In case of equality it should return false.
In your case, lexicographical_compare stopped on the first tokens, since the predicate reported that one is less then other. No other comparison was necessary to get the result.
Try to change the result to false. You should be seeing the output from whole inputs.
Best regards, Pavol.
Pavol,
Thank you very much for your effort/time/help. Yes, I do see the output. But still one question, why my function integer_compare is being call 2 times for every sub-string?
my input strings are string s1("/1/11/2"), string s2("/1/9/3");
Here is my output:
calling integer_compare () () calling integer_compare () () calling integer_compare (1) (1) calling integer_compare (1) (1) calling integer_compare (11) (9) calling integer_compare (9) (11) calling integer_compare (2) (3) calling integer_compare (3) (2)
If you look better, you see that the arguments are reversed in the second call. because the interger_compare implements only '<' operation, we need actualy to call it twise to get ==. Anyway, if you find lexicographical_compare insufficient in some regards, I'm sure you can now implement version that suits your needs. Regards, Pavol.

On 2/20/07, Pavol Droba <droba@topmail.sk> wrote:
Meryl Silverburgh wrote:
On 2/20/07, Pavol Droba <droba@topmail.sk> wrote:
Thanks, I did try just doing this cout << copy_range<std::string>(a) << endl; cout << copy_range<std::string>(b) << endl;
But I find out that 'integer_compare' just call once, and it is an empty string.
My input strings were "/1/11/2", "1/9/2". From your previous message, I understand the first time return an empty string, but I do expect integer_compare will call again and again like "1", "11", "2", "1", "9" ,"2".... But it did not happens.
Great, we are getting to the finish ;) There is just one slight problem, that I have overlooked in your code.
lexicographical_compare simply forwards the call to std::lexicographical_compare http://www.sgi.com/tech/stl/lexicographical_compare.html
So the given predicate (integer_compare) functions as *isless*. It means, that it should return true if the first argument is *less* then the second one. In case of equality it should return false.
In your case, lexicographical_compare stopped on the first tokens, since the predicate reported that one is less then other. No other comparison was necessary to get the result.
Try to change the result to false. You should be seeing the output from whole inputs.
Best regards, Pavol.
Pavol,
Thank you very much for your effort/time/help. Yes, I do see the output. But still one question, why my function integer_compare is being call 2 times for every sub-string?
my input strings are string s1("/1/11/2"), string s2("/1/9/3");
Here is my output:
calling integer_compare () () calling integer_compare () () calling integer_compare (1) (1) calling integer_compare (1) (1) calling integer_compare (11) (9) calling integer_compare (9) (11) calling integer_compare (2) (3) calling integer_compare (3) (2)
If you look better, you see that the arguments are reversed in the second call. because the interger_compare implements only '<' operation, we need actualy to call it twise to get ==.
Anyway, if you find lexicographical_compare insufficient in some regards, I'm sure you can now implement version that suits your needs.
I guess a bigger problem for me for using lexicographical_compare is I will get opposite result depends on the order of the input string: For example, if I have string s1("/1/9"), string s2("/1/9/3"); the compare will return true, but if I have string s1("/1/9/3"), string s2("/1/9"); it will return false. But for my case, I always want "/1/9" less than "/1/9/3" I guess I can compare the length of the 2 string and always put s1 to be the shorter one, and s2 to be the longer one. if there is an more efficient/cleaner idea, please let me know.
Regards, Pavol. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Meryl Silverburgh wrote: <snip>
I guess a bigger problem for me for using lexicographical_compare is I will get opposite result depends on the order of the input string: For example, if I have string s1("/1/9"), string s2("/1/9/3");
the compare will return true,
but if I have
string s1("/1/9/3"), string s2("/1/9");
it will return false.
But for my case, I always want "/1/9" less than "/1/9/3"
I guess I can compare the length of the 2 string and always put s1 to be the shorter one, and s2 to be the longer one.
if there is an more efficient/cleaner idea, please let me know.
Here is an excert from the lexicographica_compare documentation in msdn: <quote> A lexicographical comparison between sequences compares them element by element until: It finds two corresponding elements unequal, and the result of their comparison is taken as the result of the comparison between sequences. No inequalities are found, but one sequence has more elements than the other, and the shorter sequence is considered less than the longer sequence. No inequalities are found and the sequences have the same number of elements, and so the sequences are equal and the result of the comparison is false. </quote> So the lexicographical_compare does indeed take the lenght of sequences into account. The problem you see, is due to the nature it handles you the result. If lexc(a,b) returns true, you know that a<b, but if lexc(b,a) returns false, you get weaker condition a<=b. If this is not sufficient for you, I would suggest to reimplement lexicographical_compare to return more detailed result (for example -1,0,1). Look into the sources of lexicographical_compare in boost and in your standard library. The implementation should be quite straighforward. Regards, Pavol.
participants (2)
-
Meryl Silverburgh
-
Pavol Droba