
Hi, I need to compare 2 strings in this format (a integer separator by '/': /1/1 /1/1/2 /1/1/3 so "/1/1" is less than "/1/1/2" and "/1/1/2" is less than " "/1/1/3". Is there anything in Boost string library to help me to write such a comparison? Is there a string iterator which literates base on the separator '/'? My idea is to find an iterator to loop thru the string based on separator '/'. Thanks for any idea.

Hi, Meryl Silverburgh wrote:
Hi,
I need to compare 2 strings in this format (a integer separator by '/': /1/1 /1/1/2 /1/1/3
so "/1/1" is less than "/1/1/2" and "/1/1/2" is less than " "/1/1/3".
Is there anything in Boost string library to help me to write such a comparison? Is there a string iterator which literates base on the separator '/'? My idea is to find an iterator to loop thru the string based on separator '/'.
There is a split_iterator which you can use. And there is a generic lexicographical_compare function. I've got an idea that might work. But it is a little elaborate. First, tokenize your string using split, but store the result to vector<iterator_range>. Then define a comparison function, that will take the two iterator_ranges and compare them. Note, that in this case, tha range should hold an integer string. Then simply use lexicographical_compare for the comparison. vector<iterator_range> vec1; split(vec, s1); vector<iterator_range> vec2; split(vec, s2); if(lexicographical_compare(vec1, vec2, integer_compare)) { // s1 is less } You can even throw away the vector, and directly create an iterator_range from the split_iterator. This way you may spare some unnecessary tokenization. typedef split_iterator<string::const_iterator> string_split; iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split()) iterator_range<string_split> r2( make_split_iterator(s2, is_any_of("/")), string_split()) if(lexicographical_compare(vec1, vec2, integer_compare)) { // s1 is less } Best Regards, Pavol.

Thanks for your idea. I have cases like this: /1/1 /1/2/3/2 Since the first string /1/1 is smaller than the /1/2 (1 is < 2) of the /1/2/3/2, I should able to stop comparison by looking at the 4th character (/1/2) of '/1/2/3/2'. So for cases like that, I would like to stop as soon as i can tell one string is shorter than the other, instead of splitting the whole string. On 2/17/07, Pavol Droba <droba@topmail.sk> wrote:
Hi,
Meryl Silverburgh wrote:
Hi,
I need to compare 2 strings in this format (a integer separator by '/': /1/1 /1/1/2 /1/1/3
so "/1/1" is less than "/1/1/2" and "/1/1/2" is less than " "/1/1/3".
Is there anything in Boost string library to help me to write such a comparison? Is there a string iterator which literates base on the separator '/'? My idea is to find an iterator to loop thru the string based on separator '/'.
There is a split_iterator which you can use. And there is a generic lexicographical_compare function.
I've got an idea that might work. But it is a little elaborate. First, tokenize your string using split, but store the result to vector<iterator_range>.
Then define a comparison function, that will take the two iterator_ranges and compare them. Note, that in this case, tha range should hold an integer string. Then simply use lexicographical_compare for the comparison.
vector<iterator_range> vec1; split(vec, s1); vector<iterator_range> vec2; split(vec, s2); if(lexicographical_compare(vec1, vec2, integer_compare)) { // s1 is less }
You can even throw away the vector, and directly create an iterator_range from the split_iterator. This way you may spare some unnecessary tokenization.
typedef split_iterator<string::const_iterator> string_split; iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split())
iterator_range<string_split> r2( make_split_iterator(s2, is_any_of("/")), string_split())
if(lexicographical_compare(vec1, vec2, integer_compare)) { // s1 is less }
Best Regards, Pavol. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

I may be overlooking something, and I hate to say it on the boost mailing list, but it seems to me that strcoll() C function does exactly what you need. Thanks, Boris ----- Original Message ----- From: "Meryl Silverburgh" <silverburgh.meryl@gmail.com> To: <boost-users@lists.boost.org> Sent: Saturday, February 17, 2007 8:52 PM Subject: Re: [Boost-users] Using Boost string library
Thanks for your idea.
I have cases like this:
/1/1 /1/2/3/2
Since the first string /1/1 is smaller than the /1/2 (1 is < 2) of the /1/2/3/2, I should able to stop comparison by looking at the 4th character (/1/2) of '/1/2/3/2'.
So for cases like that, I would like to stop as soon as i can tell one string is shorter than the other, instead of splitting the whole string.
On 2/17/07, Pavol Droba <droba@topmail.sk> wrote:
Hi,
Meryl Silverburgh wrote:
Hi,
I need to compare 2 strings in this format (a integer separator by '/': /1/1 /1/1/2 /1/1/3
so "/1/1" is less than "/1/1/2" and "/1/1/2" is less than " "/1/1/3".
Is there anything in Boost string library to help me to write such a comparison? Is there a string iterator which literates base on the separator '/'? My idea is to find an iterator to loop thru the string based on separator '/'.
There is a split_iterator which you can use. And there is a generic lexicographical_compare function.
I've got an idea that might work. But it is a little elaborate. First, tokenize your string using split, but store the result to vector<iterator_range>.
Then define a comparison function, that will take the two iterator_ranges and compare them. Note, that in this case, tha range should hold an integer string. Then simply use lexicographical_compare for the comparison.
vector<iterator_range> vec1; split(vec, s1); vector<iterator_range> vec2; split(vec, s2); if(lexicographical_compare(vec1, vec2, integer_compare)) { // s1 is less }
You can even throw away the vector, and directly create an iterator_range from the split_iterator. This way you may spare some unnecessary tokenization.
typedef split_iterator<string::const_iterator> string_split; iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split())
iterator_range<string_split> r2( make_split_iterator(s2, is_any_of("/")), string_split())
if(lexicographical_compare(vec1, vec2, integer_compare)) { // s1 is less }
Best Regards, Pavol. _______________________________________________ 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

Boris Gubenko wrote:
I may be overlooking something, and I hate to say it on the boost mailing list, but it seems to me that strcoll() C function does exactly what you need.
I think I know what I'm overlooking: the integers in your strings are not all single-digit integers as in your examples. If this is correct, I retract my strcoll() proposal. Sorry for the confusion. Boris ----- Original Message ----- From: "Boris Gubenko" <Boris.Gubenko@hp.com> To: <boost-users@lists.boost.org> Cc: "Boris Gubenko" <Boris.Gubenko@hp.com> Sent: Saturday, February 17, 2007 11:44 PM Subject: Re: [Boost-users] Using Boost string library
I may be overlooking something, and I hate to say it on the boost mailing list, but it seems to me that strcoll() C function does exactly what you need.
Thanks, Boris
----- Original Message ----- From: "Meryl Silverburgh" <silverburgh.meryl@gmail.com> To: <boost-users@lists.boost.org> Sent: Saturday, February 17, 2007 8:52 PM Subject: Re: [Boost-users] Using Boost string library
Thanks for your idea.
I have cases like this:
/1/1 /1/2/3/2
Since the first string /1/1 is smaller than the /1/2 (1 is < 2) of the /1/2/3/2, I should able to stop comparison by looking at the 4th character (/1/2) of '/1/2/3/2'.
So for cases like that, I would like to stop as soon as i can tell one string is shorter than the other, instead of splitting the whole string.
On 2/17/07, Pavol Droba <droba@topmail.sk> wrote:
Hi,
Meryl Silverburgh wrote:
Hi,
I need to compare 2 strings in this format (a integer separator by '/': /1/1 /1/1/2 /1/1/3
so "/1/1" is less than "/1/1/2" and "/1/1/2" is less than " "/1/1/3".
Is there anything in Boost string library to help me to write such a comparison? Is there a string iterator which literates base on the separator '/'? My idea is to find an iterator to loop thru the string based on separator '/'.
There is a split_iterator which you can use. And there is a generic lexicographical_compare function.
I've got an idea that might work. But it is a little elaborate. First, tokenize your string using split, but store the result to vector<iterator_range>.
Then define a comparison function, that will take the two iterator_ranges and compare them. Note, that in this case, tha range should hold an integer string. Then simply use lexicographical_compare for the comparison.
vector<iterator_range> vec1; split(vec, s1); vector<iterator_range> vec2; split(vec, s2); if(lexicographical_compare(vec1, vec2, integer_compare)) { // s1 is less }
You can even throw away the vector, and directly create an iterator_range from the split_iterator. This way you may spare some unnecessary tokenization.
typedef split_iterator<string::const_iterator> string_split; iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split())
iterator_range<string_split> r2( make_split_iterator(s2, is_any_of("/")), string_split())
if(lexicographical_compare(vec1, vec2, integer_compare)) { // s1 is less }
Best Regards, Pavol. _______________________________________________ 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
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Hi, Meryl Silverburgh wrote:
Thanks for your idea.
I have cases like this:
/1/1 /1/2/3/2
Since the first string /1/1 is smaller than the /1/2 (1 is < 2) of the /1/2/3/2, I should able to stop comparison by looking at the 4th character (/1/2) of '/1/2/3/2'.
So for cases like that, I would like to stop as soon as i can tell one string is shorter than the other, instead of splitting the whole string.
This is exactly what would happen you use the second approach I gave you. Constructing the iterator_range from the split iterator does not perform any actual searching, and lexicographical_compare stops on the first possible index (i.e on the first position where inputs are different).
You can even throw away the vector, and directly create an iterator_range from the split_iterator. This way you may spare some unnecessary tokenization.
typedef split_iterator<string::const_iterator> string_split; iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split())
iterator_range<string_split> r2( make_split_iterator(s2, is_any_of("/")), string_split())
if(lexicographical_compare(r1, r2, integer_compare)) { // s1 is less }
Regards, Pavol

On 2/18/07, Pavol Droba <droba@topmail.sk> wrote:
Hi,
Meryl Silverburgh wrote:
Thanks for your idea.
I have cases like this:
/1/1 /1/2/3/2
Since the first string /1/1 is smaller than the /1/2 (1 is < 2) of the /1/2/3/2, I should able to stop comparison by looking at the 4th character (/1/2) of '/1/2/3/2'.
So for cases like that, I would like to stop as soon as i can tell one string is shorter than the other, instead of splitting the whole string.
This is exactly what would happen you use the second approach I gave you. Constructing the iterator_range from the split iterator does not perform any actual searching, and lexicographical_compare stops on the first possible index (i.e on the first position where inputs are different).
You can even throw away the vector, and directly create an iterator_range from the split_iterator. This way you may spare some unnecessary tokenization.
typedef split_iterator<string::const_iterator> string_split; iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split())
iterator_range<string_split> r2( make_split_iterator(s2, is_any_of("/")), string_split())
if(lexicographical_compare(r1, r2, integer_compare)) { // s1 is less }
Regards, Pavol
Pavol, Thanks for your help. I am trying your second approach. But I am having compilation error in this line: iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split()); error: ../test.cpp:18: error: no matching function for call to `boost::algorithm::iterator_range<string_split>::iterator_range(boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> >
, string_split)' /usr/include/boost/algorithm/string/iterator_range.hpp:89: note: candidates are: boost::algorithm::iterator_range<IteratorT>::iterator_range(const boost::algorithm::iterator_range<IteratorT>&) [with IteratorT = string_split] /usr/include/boost/algorithm/string/iterator_range.hpp:85: note:
Complete program: #include <iostream> #include <string> #include "boost/algorithm/string/find_iterator.hpp" #include "boost/algorithm/string/classification.hpp" using namespace std; using namespace boost::algorithm; typedef split_iterator<string::const_iterator> string_split; int main(int argc, char **argv) { cout << "hello world" << endl; string s1("/1/1/2"); string s2("/1/1/3"); iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split()); iterator_range<string_split> r2( make_split_iterator(s2, is_any_of("/")), string_split()); if(lexicographical_compare(r1, r2, integer_compare)) { cout << " s1 is less " << endl; } else { cout << " s2 is less " << endl; } } } complete error: **** Build of configuration Debug for project str **** make -k all Building file: ../test.cpp Invoking: GCC C++ Compiler g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"test.d" -MT"test.d" -o"test.o" "../test.cpp" ../test.cpp: In function `int main(int, char**)': ../test.cpp:18: error: no matching function for call to `boost::algorithm::iterator_range<string_split>::iterator_range(boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> >
, string_split)' /usr/include/boost/algorithm/string/iterator_range.hpp:89: note: candidates are: boost::algorithm::iterator_range<IteratorT>::iterator_range(const boost::algorithm::iterator_range<IteratorT>&) [with IteratorT = string_split] /usr/include/boost/algorithm/string/iterator_range.hpp:85: note: boost::algorithm::iterator_range<IteratorT>::iterator_range(const std::pair<_ForwardIterator, _ForwardIterator>&) [with IteratorT = string_split] /usr/include/boost/algorithm/string/iterator_range.hpp:81: note: boost::algorithm::iterator_range<IteratorT>::iterator_range(IteratorT, IteratorT) [with IteratorT = string_split] /usr/include/boost/algorithm/string/iterator_range.hpp:77: note: boost::algorithm::iterator_range<IteratorT>::iterator_range() [with IteratorT = string_split] ../test.cpp:21: error: no matching function for call to `boost::algorithm::iterator_range<string_split>::iterator_range(boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > , string_split)' /usr/include/boost/algorithm/string/iterator_range.hpp:89: note: candidates are: boost::algorithm::iterator_range<IteratorT>::iterator_range(const boost::algorithm::iterator_range<IteratorT>&) [with IteratorT = string_split] /usr/include/boost/algorithm/string/iterator_range.hpp:85: note: boost::algorithm::iterator_range<IteratorT>::iterator_range(const std::pair<_ForwardIterator, _ForwardIterator>&) [with IteratorT = string_split] /usr/include/boost/algorithm/string/iterator_range.hpp:81: note: boost::algorithm::iterator_range<IteratorT>::iterator_range(IteratorT, IteratorT) [with IteratorT = string_split] /usr/include/boost/algorithm/string/iterator_range.hpp:77: note: boost::algorithm::iterator_range<IteratorT>::iterator_range() [with IteratorT = string_split] ../test.cpp:23: error: `integer_compare' was not declared in this scope ../test.cpp:23: warning: unused variable 'integer_compare' ../test.cpp: At global scope: ../test.cpp:31: error: expected declaration before '}' token /usr/include/boost/function/function_template.hpp: In static member function `static R boost::detail::function::function_obj_invoker2<FunctionObj, R, T0, T1>::invoke(boost::detail::function::any_pointer, T0, T1) [with FunctionObj = boost::algorithm::detail::is_any_ofF<char>, R = boost::algorithm::iterator_range<__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > , T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, T1 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >]': /usr/include/boost/function/function_template.hpp:482: instantiated from `void boost::function2<R, T0, T1, Allocator>::assign_to(FunctionObj, boost::detail::function::function_obj_tag) [with FunctionObj = boost::algorithm::detail::is_any_ofF<char>, R = boost::algorithm::iterator_range<__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > , T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, T1 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Allocator = std::allocator<boost::function_base>]' /usr/include/boost/function/function_template.hpp:433: instantiated from `void boost::function2<R, T0, T1, Allocator>::assign_to(Functor) [with Functor = boost::algorithm::detail::is_any_ofF<char>, R = boost::algorithm::iterator_range<__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > , T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, T1 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Allocator = std::allocator<boost::function_base>]' /usr/include/boost/function/function_template.hpp:289: instantiated from `boost::function2<R, T0, T1, Allocator>::function2(Functor, typename boost::enable_if_c< boost::type_traits::ice_not< boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::algorithm::detail::is_any_ofF<char>, R = boost::algorithm::iterator_range<__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > , T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, T1 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Allocator = std::allocator<boost::function_base>]' /usr/include/boost/algorithm/string/detail/find_iterator.hpp:50: instantiated from `boost::algorithm::detail::find_iterator_base<IteratorT>::find_iterator_base(FinderT, int) [with FinderT = boost::algorithm::detail::is_any_ofF<char>, IteratorT = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > ]' /usr/include/boost/algorithm/string/find_iterator.hpp:262: instantiated from `boost::algorithm::split_iterator<IteratorT>::split_iterator(IteratorT, IteratorT, FinderT) [with FinderT = boost::algorithm::detail::is_any_ofF<char>, IteratorT = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >]' /usr/include/boost/algorithm/string/find_iterator.hpp:351: instantiated from `boost::algorithm::split_iterator<typename boost::algorithm::result_iterator_of<C>::type> boost::algorithm::make_split_iterator(CollectionT&, FinderT) [with CollectionT = std::string, FinderT = boost::algorithm::detail::is_any_ofF<char>]' ../test.cpp:18: instantiated from here /usr/include/boost/function/function_template.hpp:111: error: no match for call to `(boost::algorithm::detail::is_any_ofF<char>) (__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&)' make: *** [test.o] Error 1 make: Target `all' not remade because of errors. Build complete for project str
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Meryl Silverburgh wrote:
On 2/18/07, Pavol Droba <droba@topmail.sk> wrote:
Hi,
Meryl Silverburgh wrote:
Thanks for your idea.
I have cases like this:
/1/1 /1/2/3/2
Since the first string /1/1 is smaller than the /1/2 (1 is < 2) of the /1/2/3/2, I should able to stop comparison by looking at the 4th character (/1/2) of '/1/2/3/2'.
So for cases like that, I would like to stop as soon as i can tell one string is shorter than the other, instead of splitting the whole string.
This is exactly what would happen you use the second approach I gave you. Constructing the iterator_range from the split iterator does not perform any actual searching, and lexicographical_compare stops on the first possible index (i.e on the first position where inputs are different).
You can even throw away the vector, and directly create an iterator_range from the split_iterator. This way you may spare some unnecessary tokenization.
typedef split_iterator<string::const_iterator> string_split; iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split())
iterator_range<string_split> r2( make_split_iterator(s2, is_any_of("/")), string_split())
if(lexicographical_compare(r1, r2, integer_compare)) { // s1 is less } Regards, Pavol
Pavol,
Thanks for your help. I am trying your second approach. But I am having compilation error in this line: iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split()); error: ../test.cpp:18: error: no matching function for call to `boost::algorithm::iterator_range<string_split>::iterator_range(boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> >
, string_split)' /usr/include/boost/algorithm/string/iterator_range.hpp:89: note: candidates are: boost::algorithm::iterator_range<IteratorT>::iterator_range(const boost::algorithm::iterator_range<IteratorT>&) [with IteratorT = string_split] /usr/include/boost/algorithm/string/iterator_range.hpp:85: note:
Complete program: #include <iostream> #include <string>
#include "boost/algorithm/string/find_iterator.hpp" #include "boost/algorithm/string/classification.hpp" using namespace std; using namespace boost::algorithm;
typedef split_iterator<string::const_iterator> string_split;
int main(int argc, char **argv) { cout << "hello world" << endl;
string s1("/1/1/2"); string s2("/1/1/3");
iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split());
iterator_range<string_split> r2( make_split_iterator(s2, is_any_of("/")), string_split());
if(lexicographical_compare(r1, r2, integer_compare)) { cout << " s1 is less " << endl; } else { cout << " s2 is less " << endl; } }
}
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. I have not included it in may mail. Please, don't take my code as 100% correct. I didn't actualy compile it, I just wanted to gived you an idea which way to go. Anyway, I'll be glad to help you if you have any further questions. Regards, Pavol.

On 2/19/07, Pavol Droba <droba@topmail.sk> wrote:
Meryl Silverburgh wrote:
On 2/18/07, Pavol Droba <droba@topmail.sk> wrote:
Hi,
Meryl Silverburgh wrote:
Thanks for your idea.
I have cases like this:
/1/1 /1/2/3/2
Since the first string /1/1 is smaller than the /1/2 (1 is < 2) of the /1/2/3/2, I should able to stop comparison by looking at the 4th character (/1/2) of '/1/2/3/2'.
So for cases like that, I would like to stop as soon as i can tell one string is shorter than the other, instead of splitting the whole string.
This is exactly what would happen you use the second approach I gave you. Constructing the iterator_range from the split iterator does not perform any actual searching, and lexicographical_compare stops on the first possible index (i.e on the first position where inputs are different).
You can even throw away the vector, and directly create an iterator_range from the split_iterator. This way you may spare some unnecessary tokenization.
typedef split_iterator<string::const_iterator> string_split; iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split())
iterator_range<string_split> r2( make_split_iterator(s2, is_any_of("/")), string_split())
if(lexicographical_compare(r1, r2, integer_compare)) { // s1 is less } Regards, Pavol
Pavol,
Thanks for your help. I am trying your second approach. But I am having compilation error in this line: iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split()); error: ../test.cpp:18: error: no matching function for call to `boost::algorithm::iterator_range<string_split>::iterator_range(boost::algorithm::split_iterator<__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> >
, string_split)' /usr/include/boost/algorithm/string/iterator_range.hpp:89: note: candidates are: boost::algorithm::iterator_range<IteratorT>::iterator_range(const boost::algorithm::iterator_range<IteratorT>&) [with IteratorT = string_split] /usr/include/boost/algorithm/string/iterator_range.hpp:85: note:
Complete program: #include <iostream> #include <string>
#include "boost/algorithm/string/find_iterator.hpp" #include "boost/algorithm/string/classification.hpp" using namespace std; using namespace boost::algorithm;
typedef split_iterator<string::const_iterator> string_split;
int main(int argc, char **argv) { cout << "hello world" << endl;
string s1("/1/1/2"); string s2("/1/1/3");
iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split());
iterator_range<string_split> r2( make_split_iterator(s2, is_any_of("/")), string_split());
if(lexicographical_compare(r1, r2, integer_compare)) { cout << " s1 is less " << endl; } else { cout << " s2 is less " << endl; } }
}
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?
Please, don't take my code as 100% correct. I didn't actualy compile it, I just wanted to gived you an idea which way to go. Anyway, I'll be glad to help you if you have any further questions.
Regards, Pavol. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

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>) For string '/1/1/5', following ranges will be returned <begin, begin) == "" <begin+1, begin+2) == "1" <begin+3, begin+4) == "1" <begin+5, begin+6) == "5" A naive approach would be to convert the range to a string using copy_range<string>(r1) and then simply convert the string to a number. I'm sure a more effective way can be designed that does not involve the copying. There is one thing you should be aware of. If your sequence starts with a separator, first token returned by the split_iterator is acutaly an empty token (i.e everything from the start of the string to the first separator == nothing). So make sure that you can handle this in your predicate and that your strings are uniform in this regards. Regards, Pavol.

On 2/19/07, Pavol Droba <droba@topmail.sk> wrote:
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>)
For string '/1/1/5', following ranges will be returned <begin, begin) == "" <begin+1, begin+2) == "1" <begin+3, begin+4) == "1" <begin+5, begin+6) == "5"
A naive approach would be to convert the range to a string using copy_range<string>(r1) and then simply convert the string to a number. I'm sure a more effective way can be designed that does not involve the copying.
There is one thing you should be aware of. If your sequence starts with a separator, first token returned by the split_iterator is acutaly an empty token (i.e everything from the start of the string to the first separator == nothing). So make sure that you can handle this in your predicate and that your strings are uniform in this regards.
Thanks for your help. I am getting the following error. I haven't implemented integer_compare(), but I still can't get what I have to compile: ../test.cpp:40:2: warning: no newline at end of file /usr/include/boost/function/function_template.hpp: In static member function `static R boost::detail::function::function_obj_invoker2<FunctionObj, R, T0, T1>::invoke(boost::detail::function::any_pointer, T0, T1) [with FunctionObj = boost::algorithm::detail::is_any_ofF<char>, R = boost::algorithm::iterator_range<__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> >
, T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, T1 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >]': /usr/include/boost/function/function_template.hpp:482: instantiated from `void boost::function2<R, T0, T1, Allocator>::assign_to(FunctionObj, boost::detail::function::function_obj_tag) [with FunctionObj = boost::algorithm::detail::is_any_ofF<char>, R = boost::algorithm::iterator_range<__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > , T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, T1 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Allocator = std::allocator<boost::function_base>]' /usr/include/boost/function/function_template.hpp:433: instantiated from `void boost::function2<R, T0, T1, Allocator>::assign_to(Functor) [with Functor = boost::algorithm::detail::is_any_ofF<char>, R = boost::algorithm::iterator_range<__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > , T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, T1 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Allocator = std::allocator<boost::function_base>]' /usr/include/boost/function/function_template.hpp:289: instantiated from `boost::function2<R, T0, T1, Allocator>::function2(Functor, typename boost::enable_if_c< boost::type_traits::ice_not< boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::algorithm::detail::is_any_ofF<char>, R = boost::algorithm::iterator_range<__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > , T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, T1 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Allocator = std::allocator<boost::function_base>]' /usr/include/boost/algorithm/string/detail/find_iterator.hpp:50: instantiated from `boost::algorithm::detail::find_iterator_base<IteratorT>::find_iterator_base(FinderT, int) [with FinderT = boost::algorithm::detail::is_any_ofF<char>, IteratorT = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > ]' /usr/include/boost/algorithm/string/find_iterator.hpp:262: instantiated from `boost::algorithm::split_iterator<IteratorT>::split_iterator(IteratorT, IteratorT, FinderT) [with FinderT = boost::algorithm::detail::is_any_ofF<char>, IteratorT = __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >]' /usr/include/boost/algorithm/string/find_iterator.hpp:351: instantiated from `boost::algorithm::split_iterator<typename boost::algorithm::result_iterator_of<C>::type> boost::algorithm::make_split_iterator(CollectionT&, FinderT) [with CollectionT = std::string, FinderT = boost::algorithm::detail::is_any_ofF<char>]' ../test.cpp:25: instantiated from here /usr/include/boost/function/function_template.hpp:111: error: no match for call to `(boost::algorithm::detail::is_any_ofF<char>) (__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&)' make: *** [test.o] Error 1 make: Target `all' not remade because of errors. Build complete for project str
#include <iostream> #include <string> #include "boost/algorithm/string/find_iterator.hpp" #include "boost/algorithm/string/classification.hpp" using namespace std; using namespace boost::algorithm; typedef split_iterator<string::iterator> string_split; class integer_compare { public: bool operator() (const string_split::value_type &a, const string_split::value_type &b) { return true; } }; int main(int argc, char **argv) { cout << "hello world" << endl; string s1("/1/11/2"); string s2("/1/1/3"); iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split()); iterator_range<string_split> r2( make_split_iterator(s2, 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

Hi, Meryl Silverburgh wrote:
On 2/19/07, Pavol Droba <droba@topmail.sk> wrote: <snip>
Thanks for your help. I am getting the following error. I haven't implemented integer_compare(), but I still can't get what I have to compile:
Build complete for project str
#include <iostream> #include <string>
#include "boost/algorithm/string/find_iterator.hpp" #include "boost/algorithm/string/classification.hpp" using namespace std; using namespace boost::algorithm;
typedef split_iterator<string::iterator> string_split;
class integer_compare { public: bool operator() (const string_split::value_type &a, const string_split::value_type &b) { return true; } };
int main(int argc, char **argv) { cout << "hello world" << endl;
string s1("/1/11/2"); string s2("/1/1/3");
iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split());
iterator_range<string_split> r2( make_split_iterator(s2, 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; }
}
So I forgot something else again. Shame on me. In the make_split_iterator call you have to specify a finder. I somehow forgot this. So the correct syntax is: make_split_iterator(s1, token_finder(is_any_of("/")) In addition there is a problem in using directives. I suggest you don't use using namespace boost::algorithms, but rather using namespace boost; In the current state, iterator_range is not available since it is in the namespace boost. It is actualy defined in boost.range library in in the string algorithms itself. All relevant string algorithms are pulled to namespace boost as well. Also, add another include #include <boost/algorithm/string/predicate.hpp> for lexicographical_compare. With these modification, I have tried and compiled the code successfully. Best Regards, Pavol.

On 2/20/07, Pavol Droba <droba@topmail.sk> wrote:
Hi,
Meryl Silverburgh wrote:
On 2/19/07, Pavol Droba <droba@topmail.sk> wrote: <snip>
Thanks for your help. I am getting the following error. I haven't implemented integer_compare(), but I still can't get what I have to compile:
Build complete for project str
#include <iostream> #include <string>
#include "boost/algorithm/string/find_iterator.hpp" #include "boost/algorithm/string/classification.hpp" using namespace std; using namespace boost::algorithm;
typedef split_iterator<string::iterator> string_split;
class integer_compare { public: bool operator() (const string_split::value_type &a, const string_split::value_type &b) { return true; } };
int main(int argc, char **argv) { cout << "hello world" << endl;
string s1("/1/11/2"); string s2("/1/1/3");
iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split());
iterator_range<string_split> r2( make_split_iterator(s2, 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; }
}
So I forgot something else again. Shame on me. In the make_split_iterator call you have to specify a finder. I somehow forgot this. So the correct syntax is: make_split_iterator(s1, token_finder(is_any_of("/"))
In addition there is a problem in using directives. I suggest you don't use using namespace boost::algorithms, but rather using namespace boost; In the current state, iterator_range is not available since it is in the namespace boost. It is actualy defined in boost.range library in in the string algorithms itself. All relevant string algorithms are pulled to namespace boost as well.
Also, add another include #include <boost/algorithm/string/predicate.hpp> for lexicographical_compare.
With these modification, I have tried and compiled the code successfully.
Thanks for your help again. However, I still have compilation error. It still does not like make_split_iterator: g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"stringCompare.d" -MT"stringCompare.d" -o"stringCompare.o" "../stringCompare.cpp" ../stringCompare.cpp:44:2: warning: no newline at end of file ../stringCompare.cpp: In function 'int main(int, char**)': ../stringCompare.cpp:29: error: no matching function for call to 'make_split_iterator(std::string&, boost::algorithm::detail::token_finderF<boost::algorithm::detail::is_any_ofF<char>
, string_split)' ../stringCompare.cpp:32: error: no matching function for call to 'make_split_iterator(std::string&, boost::algorithm::detail::token_finderF<boost::algorithm::detail::is_any_ofF<char> , string_split)' make: *** [stringCompare.o] Error 1 make: Target `all' not remade because of errors. Build complete for project sandbox
#include <iostream> #include <string> #include "boost/algorithm/string/find_iterator.hpp" #include "boost/algorithm/string/classification.hpp" #include "boost/algorithm/string/predicate.hpp" using namespace std; using namespace boost; typedef split_iterator<string::iterator> string_split; class integer_compare { public: bool operator() (const string_split::value_type &a, const string_split::value_type &b) { return true; } }; int main(int argc, char **argv) { cout << "hello world" << endl; string s1("/1/11/2"); string s2("/1/1/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; } }
Best Regards, Pavol. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On 2/20/07, Meryl Silverburgh <silverburgh.meryl@gmail.com> wrote:
On 2/20/07, Pavol Droba <droba@topmail.sk> wrote:
Hi,
Meryl Silverburgh wrote:
On 2/19/07, Pavol Droba <droba@topmail.sk> wrote: <snip>
Thanks for your help. I am getting the following error. I haven't implemented integer_compare(), but I still can't get what I have to compile:
Build complete for project str
#include <iostream> #include <string>
#include "boost/algorithm/string/find_iterator.hpp" #include "boost/algorithm/string/classification.hpp" using namespace std; using namespace boost::algorithm;
typedef split_iterator<string::iterator> string_split;
class integer_compare { public: bool operator() (const string_split::value_type &a, const string_split::value_type &b) { return true; } };
int main(int argc, char **argv) { cout << "hello world" << endl;
string s1("/1/11/2"); string s2("/1/1/3");
iterator_range<string_split> r1( make_split_iterator(s1, is_any_of("/")), string_split());
iterator_range<string_split> r2( make_split_iterator(s2, 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; }
}
So I forgot something else again. Shame on me. In the make_split_iterator call you have to specify a finder. I somehow forgot this. So the correct syntax is: make_split_iterator(s1, token_finder(is_any_of("/"))
In addition there is a problem in using directives. I suggest you don't use using namespace boost::algorithms, but rather using namespace boost; In the current state, iterator_range is not available since it is in the namespace boost. It is actualy defined in boost.range library in in the string algorithms itself. All relevant string algorithms are pulled to namespace boost as well.
Also, add another include #include <boost/algorithm/string/predicate.hpp> for lexicographical_compare.
With these modification, I have tried and compiled the code successfully.
Thanks for your help again. However, I still have compilation error. It still does not like make_split_iterator:
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"stringCompare.d" -MT"stringCompare.d" -o"stringCompare.o" "../stringCompare.cpp" ../stringCompare.cpp:44:2: warning: no newline at end of file ../stringCompare.cpp: In function 'int main(int, char**)': ../stringCompare.cpp:29: error: no matching function for call to 'make_split_iterator(std::string&, boost::algorithm::detail::token_finderF<boost::algorithm::detail::is_any_ofF<char>
, string_split)' ../stringCompare.cpp:32: error: no matching function for call to 'make_split_iterator(std::string&, boost::algorithm::detail::token_finderF<boost::algorithm::detail::is_any_ofF<char> , string_split)' make: *** [stringCompare.o] Error 1 make: Target `all' not remade because of errors. Build complete for project sandbox
#include <iostream> #include <string>
#include "boost/algorithm/string/find_iterator.hpp" #include "boost/algorithm/string/classification.hpp" #include "boost/algorithm/string/predicate.hpp"
using namespace std; using namespace boost;
typedef split_iterator<string::iterator> string_split;
class integer_compare { public: bool operator() (const string_split::value_type &a, const string_split::value_type &b) { return true; } };
int main(int argc, char **argv) { cout << "hello world" << endl;
string s1("/1/11/2"); string s2("/1/1/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; }
}
i have added '#include "boost/algorithm/string/finder.hpp"' but it still does not solve my error.
Best Regards, Pavol. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Meryl Silverburgh wrote:
#include <iostream> #include <string>
#include "boost/algorithm/string/find_iterator.hpp" #include "boost/algorithm/string/classification.hpp" #include "boost/algorithm/string/predicate.hpp"
using namespace std; using namespace boost;
typedef split_iterator<string::iterator> string_split;
class integer_compare { public: bool operator() (const string_split::value_type &a, const string_split::value_type &b) { return true; } };
int main(int argc, char **argv) { cout << "hello world" << endl;
string s1("/1/11/2"); string s2("/1/1/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; }
}
i have added '#include "boost/algorithm/string/finder.hpp"' but it still does not solve my error.
A missing parenthesis is missing there. Instead of iterator_range<string_split> r1( make_split_iterator(s1, token_finder(is_any_of("/")), string_split()); you should write: iterator_range<string_split> r1( make_split_iterator(s1, token_finder(is_any_of("/"))), string_split()); parenthesis is missing just after token_finder. Regards, Pavol.
participants (3)
-
Boris Gubenko
-
Meryl Silverburgh
-
Pavol Droba