Search only one column of a multi-dimensional array

Discussion in 'C++' started by Angus, Mar 7, 2011.

  1. Angus

    Angus Guest

    Hi

    using lower_bound I want to pass a 2-dimensional array eg like this:
    static const int tbl[5][3] = {
    1000, 800, 801,
    1001, 802, 803,
    1002, 804, 805,
    1003, 806, 807,
    1004, 808, 809
    };

    I want to search in only the first column - eg the numbers 1000-1004.
    I am trying to find the position in this 2-dimensional array, and then
    once located I can access elements[position][1] and elements[position]
    [2].

    I tried this:
    int arrsize = sizeof(tbl)/sizeof(tbl[0]);
    low=lower_bound(tbl[0], tbl[0]+arrsize, 7);

    But get compile error C2440 cannot convert from 'const int *' to 'int
    *'

    How can I do this?

    Angus
     
    Angus, Mar 7, 2011
    #1
    1. Advertising

  2. On 3/7/2011 12:17 PM, Angus wrote:
    > using lower_bound I want to pass a 2-dimensional array eg like this:
    > static const int tbl[5][3] = {
    > 1000, 800, 801,
    > 1001, 802, 803,
    > 1002, 804, 805,
    > 1003, 806, 807,
    > 1004, 808, 809
    > };
    >
    > I want to search in only the first column - eg the numbers 1000-1004.
    > I am trying to find the position in this 2-dimensional array, and then
    > once located I can access elements[position][1] and elements[position]
    > [2].
    >
    > I tried this:
    > int arrsize = sizeof(tbl)/sizeof(tbl[0]);
    > low=lower_bound(tbl[0], tbl[0]+arrsize, 7);
    >
    > But get compile error C2440 cannot convert from 'const int *' to 'int
    > *'
    >
    > How can I do this?


    You should probably provide your own iterator, which when incremented
    will skip the rest of the "row".

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Mar 7, 2011
    #2
    1. Advertising

  3. Angus

    Angus Guest

    On Mar 7, 6:05 pm, Victor Bazarov <> wrote:
    > On 3/7/2011 12:17 PM, Angus wrote:
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > > using lower_bound I want to pass a 2-dimensional array eg like this:
    > >     static const int tbl[5][3] = {
    > >        1000, 800, 801,
    > >        1001, 802, 803,
    > >        1002, 804, 805,
    > >        1003, 806, 807,
    > >        1004, 808, 809
    > >     };

    >
    > > I want to search in only the first column - eg the numbers 1000-1004.
    > > I am trying to find the position in this 2-dimensional array, and then
    > > once located I can access elements[position][1] and elements[position]
    > > [2].

    >
    > > I tried this:
    > >     int arrsize = sizeof(tbl)/sizeof(tbl[0]);
    > >     low=lower_bound(tbl[0], tbl[0]+arrsize, 7);

    >
    > > But get compile error C2440 cannot convert from 'const int *' to 'int
    > > *'

    >
    > > How can I do this?

    >
    > You should probably provide your own iterator, which when incremented
    > will skip the rest of the "row".
    >
    > V
    > --
    > I do not respond to top-posted replies, please don't ask


    Are you suggesting it 'jump' over the other items in row. Eg if there
    were five columns of ints it would jump 5 int's worth on each
    iteration?

    Can you provide an outline example? Or place to find something like
    this?
     
    Angus, Mar 7, 2011
    #3
  4. On 3/7/2011 1:16 PM, Angus wrote:
    > On Mar 7, 6:05 pm, Victor Bazarov<> wrote:
    >> On 3/7/2011 12:17 PM, Angus wrote:
    >>
    >>
    >>
    >>
    >>
    >>
    >>
    >>
    >>
    >>> using lower_bound I want to pass a 2-dimensional array eg like this:
    >>> static const int tbl[5][3] = {
    >>> 1000, 800, 801,
    >>> 1001, 802, 803,
    >>> 1002, 804, 805,
    >>> 1003, 806, 807,
    >>> 1004, 808, 809
    >>> };

    >>
    >>> I want to search in only the first column - eg the numbers 1000-1004.
    >>> I am trying to find the position in this 2-dimensional array, and then
    >>> once located I can access elements[position][1] and elements[position]
    >>> [2].

    >>
    >>> I tried this:
    >>> int arrsize = sizeof(tbl)/sizeof(tbl[0]);
    >>> low=lower_bound(tbl[0], tbl[0]+arrsize, 7);

    >>
    >>> But get compile error C2440 cannot convert from 'const int *' to 'int
    >>> *'

    >>
    >>> How can I do this?

    >>
    >> You should probably provide your own iterator, which when incremented
    >> will skip the rest of the "row".
    >>
    >> V
    >> --
    >> I do not respond to top-posted replies, please don't ask

    >
    > Are you suggesting it 'jump' over the other items in row. Eg if there
    > were five columns of ints it would jump 5 int's worth on each
    > iteration?


    Yes, that's exactly what I'm suggesting.

    > Can you provide an outline example? Or place to find something like
    > this?


    Something like this:

    template<class T, size_type N, size_type M>
    class arr_col_iter_t
    {
    T (&arr)[N][M];
    size_type col;
    size_type ind;
    public:
    arr_col_iter_t(T (&a)[N][M], size_type c, size_type ind0)
    : arr(a), col(c), ind(ind0) {}

    T& operator *() { return arr[ind][col]; }
    arr_col_iter_t& operator++() { ++ind; return *this; }
    arr_col_iter_t operator++(int) {
    arr_col_iter_t temp(*this);
    ++ind; return temp;
    }

    bool operator!=(arr_col_iter_t const& other) const
    {
    assert(&arr == &other.arr
    && col == other.col); // same array, same col
    return ind != other.ind;
    }
    };

    template<class T, size_type N, size_type M>
    arr_col_iter_t<T,N,M> arr_iter(T (&arr)[N][M], size_type c,
    size_type ind0 = 0)
    {
    return arr_col_iter_t<T,N,M>(arr, c, ind0);
    }
    ...
    // to iterate over "column 0" from 0 to arrsize-1:
    lower_boundary(arr_iter(tbl, 0), arr_iter(tb, 0, arrsize), 7);

    There are undoubtedly holes in that (not to mention that it's not a
    fully fledged iterator according to Standard's requirements - no tag, no
    value_type, etc.)

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Mar 7, 2011
    #4
  5. Angus

    James Kanze Guest

    On Mar 7, 6:05 pm, Victor Bazarov <> wrote:
    > On 3/7/2011 12:17 PM, Angus wrote:
    > > using lower_bound I want to pass a 2-dimensional array eg like this:
    > > static const int tbl[5][3] = {
    > > 1000, 800, 801,
    > > 1001, 802, 803,
    > > 1002, 804, 805,
    > > 1003, 806, 807,
    > > 1004, 808, 809
    > > };


    > > I want to search in only the first column - eg the numbers 1000-1004.
    > > I am trying to find the position in this 2-dimensional array, and then
    > > once located I can access elements[position][1] and elements[position]
    > > [2].


    > > I tried this:
    > > int arrsize = sizeof(tbl)/sizeof(tbl[0]);
    > > low=lower_bound(tbl[0], tbl[0]+arrsize, 7);


    > > But get compile error C2440 cannot convert from 'const int *' to 'int
    > > *'


    That's because you're passing tbl[0], instead of just tbl.

    Of course, if you pass tbl, tbl+arrsize, you'll still get an
    error when lower_bound trys to do int[3] < 7. Or something like
    that: C style arrays are pretty broken, and you can get some
    strange effects from them. I recently had to do something
    similar, but with several different arrays with different
    numbers of rows. The template function to handle this was
    something like:

    template <size_t N, size_t M>
    std::string const (&
    findIt(std::string const(&target)[N][M],
    int id_column,
    std::string const& key)
    )[M]
    {
    // ...
    }

    (From memory, so it might not be exact.)

    Anyway, what you need to do is pass tbl and tbl + arrsize (type
    int (*)[3]), and provide a less than operator along the lines of

    struct LessThanFirstOfThree
    {
    bool operator()(int (&arr)[3], int other) const
    {
    return arr[0] < other;
    }
    bool operator()(int other, int (&arr)[3]) const
    {
    return other < arr[0];
    }
    };

    (That's without trying it, so there are likely some typos or
    other errors, but that's the general idea.)

    > > How can I do this?


    > You should probably provide your own iterator, which when incremented
    > will skip the rest of the "row".


    I'm not sure that that's the solution. He has an array of [] of
    [3] int; an iterator into it will designate and array of [3]
    int. Doing this with C style arrays and pointers can lead to
    some very unnatural syntax, but is doable. Typedef's can help a
    lot. (In my example above, I couldn't use a typedef because it
    was a template, but my earlier versions, before it became a
    template, used typedef's, and weren't that bad.) Something
    like:

    typedef int Row[3];
    Row const array[] = { ... };

    Row const& element = std::lower_bound( begin( array ),
    end( array ),
    int key,
    CompareFirst() );

    (with CompareFirst something like the above.)

    --
    James Kanze
     
    James Kanze, Mar 7, 2011
    #5
  6. Angus

    Angus Guest

    On Mar 7, 10:32 pm, James Kanze <> wrote:
    > On Mar 7, 6:05 pm, Victor Bazarov <> wrote:
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > > On 3/7/2011 12:17 PM, Angus wrote:
    > > > using lower_bound I want to pass a 2-dimensional array eg like this:
    > > >     static const int tbl[5][3] = {
    > > >        1000, 800, 801,
    > > >        1001, 802, 803,
    > > >        1002, 804, 805,
    > > >        1003, 806, 807,
    > > >        1004, 808, 809
    > > >     };
    > > > I want to search in only the first column - eg the numbers 1000-1004.
    > > > I am trying to find the position in this 2-dimensional array, and then
    > > > once located I can access elements[position][1] and elements[position]
    > > > [2].
    > > > I tried this:
    > > >     int arrsize = sizeof(tbl)/sizeof(tbl[0]);
    > > >     low=lower_bound(tbl[0], tbl[0]+arrsize, 7);
    > > > But get compile error C2440 cannot convert from 'const int *' to 'int
    > > > *'

    >
    > That's because you're passing tbl[0], instead of just tbl.
    >
    > Of course, if you pass tbl, tbl+arrsize, you'll still get an
    > error when lower_bound trys to do int[3] < 7.  Or something like
    > that: C style arrays are pretty broken, and you can get some
    > strange effects from them.  I recently had to do something
    > similar, but with several different arrays with different
    > numbers of rows.  The template function to handle this was
    > something like:
    >
    >     template <size_t N, size_t M>
    >     std::string const (&
    >             findIt(std::string const(&target)[N][M],
    >                    int id_column,
    >                    std::string const& key)
    >         )[M]
    >     {
    >         //  ...
    >     }
    >
    > (From memory, so it might not be exact.)
    >
    > Anyway, what you need to do is pass tbl and tbl + arrsize (type
    > int (*)[3]), and provide a less than operator along the lines of
    >
    >     struct LessThanFirstOfThree
    >     {
    >         bool operator()(int (&arr)[3], int other) const
    >         {
    >             return arr[0] < other;
    >         }
    >         bool operator()(int other, int (&arr)[3]) const
    >         {
    >             return other < arr[0];
    >         }
    >     };
    >
    > (That's without trying it, so there are likely some typos or
    > other errors, but that's the general idea.)
    >
    > > > How can I do this?

    > > You should probably provide your own iterator, which when incremented
    > > will skip the rest of the "row".

    >
    > I'm not sure that that's the solution.  He has an array of [] of
    > [3] int; an iterator into it will designate and array of [3]
    > int.  Doing this with C style arrays and pointers can lead to
    > some very unnatural syntax, but is doable.  Typedef's can help a
    > lot.  (In my example above, I couldn't use a typedef because it
    > was a template, but my earlier versions, before it became a
    > template, used typedef's, and weren't that bad.)  Something
    > like:
    >
    >     typedef int Row[3];
    >     Row const array[] = { ... };
    >
    >     Row const& element = std::lower_bound( begin( array ),
    >                                            end( array ),
    >                                            int key,
    >                                            CompareFirst() );
    >
    > (with CompareFirst something like the above.)
    >
    > --
    > James Kanze


    Hello

    I am trying to progress with code as simple as possible as a learning
    exercise.

    Here is my code which finds if code in column 1, but not if number
    searched is less than any item in first column.

    What am I doing wrong?

    Here is code:

    #pragma warning(disable: 4786)

    #include <iostream>
    #include <algorithm>

    using namespace std;

    struct errorinfo
    {
    errorinfo() : category(0), error(0) {}
    int category;
    int error;
    };

    bool lessthanrow1(const int (&arr)[3], const int other)
    {
    return arr[0] < other;
    }


    bool mapBW2CSTAError(const int bw_error, errorinfo& csta_error)
    {
    const int cols = 3;
    //in real life much bigger array.
    static const int tbl[6][cols] = {
    1000, 10, 0,
    1001, 11, 1,
    1200, 12, 2,
    4002, 13, 3,
    8090, 14, 4,
    121105, 15, 5
    };

    int tblsize = sizeof(tbl) /( sizeof(int) * cols);

    int* result = (int*)lower_bound(tbl, tbl+tblsize, bw_error,
    lessthanrow1);
    int idx = ((result - (int*)tbl) / cols);

    if(idx != tblsize){
    csta_error.category = tbl[idx][1];
    csta_error.error = tbl[idx][2];
    } else {
    cout << "item not found\n";
    return false;
    }

    cout << "Your error: " << bw_error << " category=" << tbl[idx][1]
    << " errcode=" << tbl[idx][2] << endl;

    return true;
    }

    int main(){
    //4002 found ok. 90 returns first element in array. large number
    is ok.

    errorinfo err;
    if(mapBW2CSTAError(4002, err))
    cout << "error code used for lookup: " << 4002 << ", type: " <<
    err.category << ", specific error code: " << err.error << endl;
    else
    cout << "error 4002 not recognised\n";


    if(mapBW2CSTAError(90, err))
    cout << "error code used for lookup: " << 90 << ", type: " <<
    err.category << ", specific error code: " << err.error << endl;
    else
    cout << "error 90 not recognised\n";

    if(mapBW2CSTAError(999999, err))
    cout << "error code used for lookup: " << 999999 << ", type: "
    << err.category << ", specific error code: " << err.error << endl;
    else
    cout << "error 999999 not recognised\n";


    return 0;
    }
     
    Angus, Mar 9, 2011
    #6
  7. Angus

    Angus Guest

    On Mar 7, 10:32 pm, James Kanze <> wrote:
    > On Mar 7, 6:05 pm, Victor Bazarov <> wrote:
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > > On 3/7/2011 12:17 PM, Angus wrote:
    > > > using lower_bound I want to pass a 2-dimensional array eg like this:
    > > >     static const int tbl[5][3] = {
    > > >        1000, 800, 801,
    > > >        1001, 802, 803,
    > > >        1002, 804, 805,
    > > >        1003, 806, 807,
    > > >        1004, 808, 809
    > > >     };
    > > > I want to search in only the first column - eg the numbers 1000-1004.
    > > > I am trying to find the position in this 2-dimensional array, and then
    > > > once located I can access elements[position][1] and elements[position]
    > > > [2].
    > > > I tried this:
    > > >     int arrsize = sizeof(tbl)/sizeof(tbl[0]);
    > > >     low=lower_bound(tbl[0], tbl[0]+arrsize, 7);
    > > > But get compile error C2440 cannot convert from 'const int *' to 'int
    > > > *'

    >
    > That's because you're passing tbl[0], instead of just tbl.
    >
    > Of course, if you pass tbl, tbl+arrsize, you'll still get an
    > error when lower_bound trys to do int[3] < 7.  Or something like
    > that: C style arrays are pretty broken, and you can get some
    > strange effects from them.  I recently had to do something
    > similar, but with several different arrays with different
    > numbers of rows.  The template function to handle this was
    > something like:
    >
    >     template <size_t N, size_t M>
    >     std::string const (&
    >             findIt(std::string const(&target)[N][M],
    >                    int id_column,
    >                    std::string const& key)
    >         )[M]
    >     {
    >         //  ...
    >     }
    >
    > (From memory, so it might not be exact.)
    >
    > Anyway, what you need to do is pass tbl and tbl + arrsize (type
    > int (*)[3]), and provide a less than operator along the lines of
    >
    >     struct LessThanFirstOfThree
    >     {
    >         bool operator()(int (&arr)[3], int other) const
    >         {
    >             return arr[0] < other;
    >         }
    >         bool operator()(int other, int (&arr)[3]) const
    >         {
    >             return other < arr[0];
    >         }
    >     };
    >
    > (That's without trying it, so there are likely some typos or
    > other errors, but that's the general idea.)
    >
    > > > How can I do this?

    > > You should probably provide your own iterator, which when incremented
    > > will skip the rest of the "row".

    >
    > I'm not sure that that's the solution.  He has an array of [] of
    > [3] int; an iterator into it will designate and array of [3]
    > int.  Doing this with C style arrays and pointers can lead to
    > some very unnatural syntax, but is doable.  Typedef's can help a
    > lot.  (In my example above, I couldn't use a typedef because it
    > was a template, but my earlier versions, before it became a
    > template, used typedef's, and weren't that bad.)  Something
    > like:
    >
    >     typedef int Row[3];
    >     Row const array[] = { ... };
    >
    >     Row const& element = std::lower_bound( begin( array ),
    >                                            end( array ),
    >                                            int key,
    >                                            CompareFirst() );
    >
    > (with CompareFirst something like the above.)
    >
    > --
    > James Kanze


    I have had a go as below. But there is a problem if lookup value is
    smaller than any code in first column. What am I doing wrong? I
    assume my predicate is not quite correct?


    #pragma warning(disable: 4786)

    #include <iostream>
    #include <algorithm>

    using namespace std;

    struct errorinfo
    {
    errorinfo() : category(0), error(0) {}
    int category;
    int error;
    };

    bool lessthanrow1(const int (&arr)[3], const int other)
    {
    return arr[0] < other;
    }


    bool maperror2code(const int bw_error, errorinfo& csta_error)
    {
    const int cols = 3;
    //in real life much bigger array.
    static const int tbl[6][cols] = {
    1000, 10, 0,
    1001, 11, 1,
    1200, 12, 2,
    4002, 13, 3,
    8090, 14, 4,
    121105, 15, 5
    };

    int tblsize = sizeof(tbl) /( sizeof(int) * cols);

    int* result = (int*)lower_bound(tbl, tbl+tblsize, bw_error,
    lessthanrow1);
    int idx = ((result - (int*)tbl) / cols);

    if(idx != tblsize){
    csta_error.category = tbl[idx][1];
    csta_error.error = tbl[idx][2];
    } else {
    cout << "item not found\n";
    return false;
    }

    cout << "Your error: " << bw_error << " category=" << tbl[idx][1]
    << " errcode=" << tbl[idx][2] << endl;

    return true;
    }

    int main(){
    //4002 found ok. 90 returns first element in array. large number
    is ok.

    errorinfo err;
    if(maperror2code(4002, err))
    cout << "error code used for lookup: " << 4002 << ", type: " <<
    err.category << ", specific error code: " << err.error << endl;
    else
    cout << "error 4002 not recognised\n";


    if(maperror2code(90, err))
    cout << "error code used for lookup: " << 90 << ", type: " <<
    err.category << ", specific error code: " << err.error << endl;
    else
    cout << "error 90 not recognised\n";

    if(maperror2code(999999, err))
    cout << "error code used for lookup: " << 999999 << ", type: "
    << err.category << ", specific error code: " << err.error << endl;
    else
    cout << "error 999999 not recognised\n";


    return 0;
    }
     
    Angus, Mar 9, 2011
    #7
  8. On 3/9/2011 8:48 AM, Angus wrote:
    > I have had a go as below. But there is a problem if lookup value is
    > smaller than any code in first column. What am I doing wrong? I
    > assume my predicate is not quite correct?
    >
    >
    > #pragma warning(disable: 4786)
    >
    > #include<iostream>
    > #include<algorithm>
    >
    > using namespace std;
    >
    > struct errorinfo
    > {
    > errorinfo() : category(0), error(0) {}
    > int category;
    > int error;
    > };
    >
    > bool lessthanrow1(const int (&arr)[3], const int other)
    > {
    > return arr[0]< other;
    > }
    >
    >
    > bool maperror2code(const int bw_error, errorinfo& csta_error)
    > {
    > const int cols = 3;
    > //in real life much bigger array.
    > static const int tbl[6][cols] = {
    > 1000, 10, 0,
    > 1001, 11, 1,
    > 1200, 12, 2,
    > 4002, 13, 3,
    > 8090, 14, 4,
    > 121105, 15, 5
    > };
    >
    > int tblsize = sizeof(tbl) /( sizeof(int) * cols);
    >
    > int* result = (int*)lower_bound(tbl, tbl+tblsize, bw_error,
    > lessthanrow1);


    Microsoft C++ 2008 and Comeau C++ (online) refuse to compile the line
    above. How did you manage to run your program (if you did)? What
    compiler allows you to use 'tbl' and 'tbl+tblsize' for the first and the
    second arguments of 'lower_bound'?

    > int idx = ((result - (int*)tbl) / cols);
    >
    > if(idx != tblsize){
    > csta_error.category = tbl[idx][1];
    > csta_error.error = tbl[idx][2];
    > } else {
    > cout<< "item not found\n";
    > return false;
    > }
    >
    > cout<< "Your error: "<< bw_error<< " category="<< tbl[idx][1]
    > << " errcode="<< tbl[idx][2]<< endl;
    >
    > return true;
    > }
    >
    > int main(){
    > //4002 found ok. 90 returns first element in array. large number
    > is ok.
    >
    > errorinfo err;
    > if(maperror2code(4002, err))
    > cout<< "error code used for lookup: "<< 4002<< ", type: "<<
    > err.category<< ", specific error code: "<< err.error<< endl;
    > else
    > cout<< "error 4002 not recognised\n";
    >
    >
    > if(maperror2code(90, err))
    > cout<< "error code used for lookup: "<< 90<< ", type: "<<
    > err.category<< ", specific error code: "<< err.error<< endl;
    > else
    > cout<< "error 90 not recognised\n";
    >
    > if(maperror2code(999999, err))
    > cout<< "error code used for lookup: "<< 999999<< ", type:"
    > << err.category<< ", specific error code: "<< err.error<< endl;
    > else
    > cout<< "error 999999 not recognised\n";
    >
    >
    > return 0;
    > }


    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Mar 9, 2011
    #8
  9. Angus

    Angus Guest

    On Mar 9, 2:28 pm, Victor Bazarov <> wrote:
    > On 3/9/2011 8:48 AM, Angus wrote:
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > > I have had a go as below.  But there is a problem if lookup value is
    > > smaller than any code in first column.  What am I doing wrong?  I
    > > assume my predicate is not quite correct?

    >
    > > #pragma warning(disable: 4786)

    >
    > > #include<iostream>
    > > #include<algorithm>

    >
    > > using namespace std;

    >
    > > struct errorinfo
    > > {
    > >     errorinfo() : category(0), error(0) {}
    > >     int category;
    > >     int error;
    > > };

    >
    > > bool lessthanrow1(const int (&arr)[3], const int other)
    > > {
    > >     return arr[0]<  other;
    > > }

    >
    > > bool maperror2code(const int bw_error, errorinfo&  csta_error)
    > > {
    > >     const int cols = 3;
    > >     //in real life much bigger array.
    > >     static const int tbl[6][cols] = {
    > >        1000, 10, 0,
    > >        1001, 11, 1,
    > >        1200, 12, 2,
    > >        4002, 13, 3,
    > >        8090, 14, 4,
    > >      121105, 15, 5
    > >     };

    >
    > >     int tblsize = sizeof(tbl) /( sizeof(int) * cols);

    >
    > >     int* result = (int*)lower_bound(tbl, tbl+tblsize, bw_error,
    > > lessthanrow1);

    >
    > Microsoft C++ 2008 and Comeau C++ (online) refuse to compile the line
    > above.  How did you manage to run your program (if you did)?  What
    > compiler allows you to use 'tbl' and 'tbl+tblsize' for the first and the
    > second arguments of 'lower_bound'?
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >     int idx = ((result - (int*)tbl) / cols);

    >
    > >     if(idx != tblsize){
    > >        csta_error.category = tbl[idx][1];
    > >        csta_error.error = tbl[idx][2];
    > >     } else {
    > >        cout<<  "item not found\n";
    > >        return false;
    > >     }

    >
    > >     cout<<  "Your error: "<<  bw_error<<  " category="<<  tbl[idx][1]
    > > <<  " errcode="<<  tbl[idx][2]<<  endl;

    >
    > >     return true;
    > > }

    >
    > > int main(){
    > >     //4002 found ok.  90 returns first element in array.  largenumber
    > > is ok.

    >
    > >     errorinfo err;
    > >     if(maperror2code(4002, err))
    > >        cout<<  "error code used for lookup: "<<  4002<<  ", type: "<<
    > > err.category<<  ", specific error code: "<<  err.error<<  endl;
    > >     else
    > >        cout<<  "error 4002 not recognised\n";

    >
    > >     if(maperror2code(90, err))
    > >        cout<<  "error code used for lookup: "<<  90<<  ",type: "<<
    > > err.category<<  ", specific error code: "<<  err.error<<  endl;
    > >     else
    > >        cout<<  "error 90 not recognised\n";

    >
    > >     if(maperror2code(999999, err))
    > >        cout<<  "error code used for lookup: "<<  999999<<  ", type:"
    > > <<  err.category<<  ", specific error code: "<<  err.error<<  endl;
    > >     else
    > >        cout<<  "error 999999 not recognised\n";

    >
    > >     return 0;
    > > }

    >
    > V
    > --
    > I do not respond to top-posted replies, please don't ask


    That works on VC++ v6. Otherwise can use lower_bound(&tbl[0],
    (&tbl[0]+sizeof(tbl)/sizeof(tbl[0])) etc
     
    Angus, Mar 9, 2011
    #9
  10. On 3/9/2011 11:12 AM, Angus wrote:
    > On Mar 9, 2:28 pm, Victor Bazarov<> wrote:
    >> On 3/9/2011 8:48 AM, Angus wrote:
    >>
    >>
    >>
    >>
    >>
    >>
    >>
    >>
    >>
    >>> I have had a go as below. But there is a problem if lookup value is
    >>> smaller than any code in first column. What am I doing wrong? I
    >>> assume my predicate is not quite correct?

    >>
    >>> #pragma warning(disable: 4786)

    >>
    >>> #include<iostream>
    >>> #include<algorithm>

    >>
    >>> using namespace std;

    >>
    >>> struct errorinfo
    >>> {
    >>> errorinfo() : category(0), error(0) {}
    >>> int category;
    >>> int error;
    >>> };

    >>
    >>> bool lessthanrow1(const int (&arr)[3], const int other)
    >>> {
    >>> return arr[0]< other;
    >>> }

    >>
    >>> bool maperror2code(const int bw_error, errorinfo& csta_error)
    >>> {
    >>> const int cols = 3;
    >>> //in real life much bigger array.
    >>> static const int tbl[6][cols] = {
    >>> 1000, 10, 0,
    >>> 1001, 11, 1,
    >>> 1200, 12, 2,
    >>> 4002, 13, 3,
    >>> 8090, 14, 4,
    >>> 121105, 15, 5
    >>> };

    >>
    >>> int tblsize = sizeof(tbl) /( sizeof(int) * cols);

    >>
    >>> int* result = (int*)lower_bound(tbl, tbl+tblsize, bw_error,
    >>> lessthanrow1);

    >>
    >> Microsoft C++ 2008 and Comeau C++ (online) refuse to compile the line
    >> above. How did you manage to run your program (if you did)? What
    >> compiler allows you to use 'tbl' and 'tbl+tblsize' for the first and the
    >> second arguments of 'lower_bound'?
    >> [..]

    >
    > That works on VC++ v6. Otherwise can use lower_bound(&tbl[0],
    > (&tbl[0]+sizeof(tbl)/sizeof(tbl[0])) etc


    That doesn't work either. You're using a compiler that was released
    before the original language standard. That compiler has enormous
    problems with templates. I seriously doubt you're going to be
    successful in learning the language and the standard library if you
    continue using the compiler released so long ago. Not to mention type
    casts like that.

    Get yourself at least somewhat up to date VC++ 2010 Express Edition.
    It's free. And get a good book on the standard library. Nicolai
    Josuttis' work is recommended highly.

    Good luck!

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Mar 9, 2011
    #10
  11. Angus

    Angus Guest

    On Mar 9, 4:36 pm, Victor Bazarov <> wrote:
    > On 3/9/2011 11:12 AM, Angus wrote:
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > > On Mar 9, 2:28 pm, Victor Bazarov<>  wrote:
    > >> On 3/9/2011 8:48 AM, Angus wrote:

    >
    > >>> I have had a go as below.  But there is a problem if lookup value is
    > >>> smaller than any code in first column.  What am I doing wrong?  I
    > >>> assume my predicate is not quite correct?

    >
    > >>> #pragma warning(disable: 4786)

    >
    > >>> #include<iostream>
    > >>> #include<algorithm>

    >
    > >>> using namespace std;

    >
    > >>> struct errorinfo
    > >>> {
    > >>>      errorinfo() : category(0), error(0) {}
    > >>>      int category;
    > >>>      int error;
    > >>> };

    >
    > >>> bool lessthanrow1(const int (&arr)[3], const int other)
    > >>> {
    > >>>      return arr[0]<    other;
    > >>> }

    >
    > >>> bool maperror2code(const int bw_error, errorinfo&    csta_error)
    > >>> {
    > >>>      const int cols = 3;
    > >>>      //in real life much bigger array.
    > >>>      static const int tbl[6][cols] = {
    > >>>         1000, 10, 0,
    > >>>         1001, 11, 1,
    > >>>         1200, 12, 2,
    > >>>         4002, 13, 3,
    > >>>         8090, 14, 4,
    > >>>       121105, 15, 5
    > >>>      };

    >
    > >>>      int tblsize = sizeof(tbl) /( sizeof(int) * cols);

    >
    > >>>      int* result = (int*)lower_bound(tbl, tbl+tblsize, bw_error,
    > >>> lessthanrow1);

    >
    > >> Microsoft C++ 2008 and Comeau C++ (online) refuse to compile the line
    > >> above.  How did you manage to run your program (if you did)?  What
    > >> compiler allows you to use 'tbl' and 'tbl+tblsize' for the first and the
    > >> second arguments of 'lower_bound'?
    > >>  [..]

    >
    > > That works on VC++ v6.  Otherwise can use lower_bound(&tbl[0],
    > > (&tbl[0]+sizeof(tbl)/sizeof(tbl[0])) etc

    >
    > That doesn't work either.  You're using a compiler that was released
    > before the original language standard.  That compiler has enormous
    > problems with templates.  I seriously doubt you're going to be
    > successful in learning the language and the standard library if you
    > continue using the compiler released so long ago.  Not to mention type
    > casts like that.
    >
    > Get yourself at least somewhat up to date VC++ 2010 Express Edition.
    > It's free.  And get a good book on the standard library.  Nicolai
    > Josuttis' work is recommended highly.
    >
    > Good luck!
    >
    > V
    > --
    > I do not respond to top-posted replies, please don't ask


    I am reading this book. I agree it is very good. I am not sure about
    your comment however on the compiler. Yes it might be old but you can
    get most template code working.

    Anyway, in the end I used a simple compare predicate:
    class CmpCode {
    public:
    bool operator()(const errorinfo& a, const errorinfo& b) const
    { return a.code < b.code; }
    };

    And checked both for end of array AND that correct value found.
    ie:
    if(it == TABLE_END(tbl) || code_to_find != it->code)
    return false;

    Then it accurately returns false if value not found.
     
    Angus, Mar 9, 2011
    #11
  12. Angus

    James Kanze Guest

    On Mar 9, 1:48 pm, Angus <> wrote:
    > On Mar 7, 10:32 pm, James Kanze <> wrote:
    > > On Mar 7, 6:05 pm, Victor Bazarov <> wrote:


    [...]
    > I have had a go as below. But there is a problem if lookup value is
    > smaller than any code in first column. What am I doing wrong? I
    > assume my predicate is not quite correct?


    I've not analysed your code completely, but a couple of things
    do stick out.

    > #pragma warning(disable: 4786)


    > #include <iostream>
    > #include <algorithm>


    > using namespace std;


    > struct errorinfo
    > {
    > errorinfo() : category(0), error(0) {}
    > int category;
    > int error;
    > };


    > bool lessthanrow1(const int (&arr)[3], const int other)
    > {
    > return arr[0] < other;
    > }


    I'm not sure what the standard says on the issue, but I could
    easily imagine the implementation trying to do the less than in
    both directions: entry < key, and key < entry, When both have
    the same type, no problem, but when they don't... That's why I
    always define a functional object which supports the comparison
    in both directions.

    > bool maperror2code(const int bw_error, errorinfo& csta_error)
    > {
    > const int cols = 3;
    > //in real life much bigger array.
    > static const int tbl[6][cols] = {
    > 1000, 10, 0,
    > 1001, 11, 1,
    > 1200, 12, 2,
    > 4002, 13, 3,
    > 8090, 14, 4,
    > 121105, 15, 5
    > };
    >
    > int tblsize = sizeof(tbl) /( sizeof(int) * cols);
    >
    > int* result = (int*)lower_bound(tbl, tbl+tblsize, bw_error,
    > lessthanrow1);


    Why the cast? The results will be an int (*)[3]; thats what you
    should use.

    > int idx = ((result - (int*)tbl) / cols);


    If you used the correct type, you wouldn't need all the casts,
    nor the division.

    Of course, there's really no need to calculate the index at all.
    You can do everything you need with pointers (as iterators).

    > if(idx != tblsize){


    Check what lower_bound returns when it doesn't find the element.
    It's *not* a pointer to end. In general, lower_bound is a lot
    more complex to use than find; avoid it unless the profiler says
    you really have to.

    > csta_error.category = tbl[idx][1];
    > csta_error.error = tbl[idx][2];
    > } else {
    > cout << "item not found\n";
    > return false;
    > }


    > cout << "Your error: " << bw_error << " category=" << tbl[idx][1]
    > << " errcode=" << tbl[idx][2] << endl;


    > return true;
    > }


    > int main(){
    > //4002 found ok. 90 returns first element in array. large number
    > is ok.


    In general, anything less than the last value will be "found" by
    the code you've written. lower_bound returns an iterator to
    where you should insert the new element in order to maintain
    order. It's not really a lookup function.

    Note that your code would be a lot cleaner if you used a few
    typedef's (e.g. typedef int Row[cols]), if you used the usual
    begin and end template functions for returning the corresponding
    pointers to a C style array, and, since you're using the STL, if
    you stuck with pointers (aka iterators), rather than switching
    to indexes in mid field.

    --
    James Kanze
     
    James Kanze, Mar 9, 2011
    #12
  13. Angus

    James Kanze Guest

    On Mar 9, 2:28 pm, Victor Bazarov <> wrote:
    > On 3/9/2011 8:48 AM, Angus wrote:


    [...]
    > > bool lessthanrow1(const int (&arr)[3], const int other)
    > > {
    > > return arr[0]< other;
    > > }


    [...]
    > > bool maperror2code(const int bw_error, errorinfo& csta_error)
    > > {
    > > const int cols = 3;
    > > //in real life much bigger array.
    > > static const int tbl[6][cols] = {
    > > 1000, 10, 0,
    > > 1001, 11, 1,
    > > 1200, 12, 2,
    > > 4002, 13, 3,
    > > 8090, 14, 4,
    > > 121105, 15, 5
    > > };


    > > int tblsize = sizeof(tbl) /( sizeof(int) * cols);


    > > int* result = (int*)lower_bound(tbl, tbl+tblsize, bw_error,
    > > lessthanrow1);


    > Microsoft C++ 2008 and Comeau C++ (online) refuse to compile the line
    > above. How did you manage to run your program (if you did)? What
    > compiler allows you to use 'tbl' and 'tbl+tblsize' for the first and the
    > second arguments of 'lower_bound'?


    What compiler doesn't? Both expressions have type int(*)[cols],
    which is a valid random access iterator. If the code doesn't
    compile, it's more likely because somewhere in the
    implementation of lower_bound, the code has an int (*iter)[cols]
    iterator, and tries to call lessthanrow1(bw_error, iter). (The
    most obvious implementation of a binary search will have
    something like:

    if (cmp(*iter, key))
    // ...
    else if (cmp(key, *iter))
    // ...
    else
    // ...

    somewhere in its inner loop.

    --
    James Kanze
     
    James Kanze, Mar 9, 2011
    #13
  14. On 3/9/2011 4:52 PM, James Kanze wrote:
    > On Mar 9, 2:28 pm, Victor Bazarov<> wrote:
    >> Microsoft C++ 2008 and Comeau C++ (online) refuse to compile the line
    >> above. How did you manage to run your program (if you did)? What
    >> compiler allows you to use 'tbl' and 'tbl+tblsize' for the first and the
    >> second arguments of 'lower_bound'?

    >
    > What compiler doesn't?


    Let me repeat: Microsoft C++ 2008 and Comeau C++ (online).

    > [..]


    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Mar 9, 2011
    #14
  15. Angus

    James Kanze Guest

    On Mar 9, 10:01 pm, Victor Bazarov <> wrote:
    > On 3/9/2011 4:52 PM, James Kanze wrote:


    > > On Mar 9, 2:28 pm, Victor Bazarov<> wrote:
    > >> Microsoft C++ 2008 and Comeau C++ (online) refuse to compile the line
    > >> above. How did you manage to run your program (if you did)? What
    > >> compiler allows you to use 'tbl' and 'tbl+tblsize' for the first and the
    > >> second arguments of 'lower_bound'?


    > > What compiler doesn't?


    > Let me repeat: Microsoft C++ 2008 and Comeau C++ (online).


    What's the error message?

    Although... now that I think of it, tbl and tbl+tblsize are pointers
    to
    the same type, and so conceptually random access iterators. Whose
    value_type is an array, and thus, neither copiable nor assignable. So
    formally, there may be undefined behavior (although I can't imagine
    why
    lower_bound would copy or assign anything in the sequence).

    --
    James Kanze
     
    James Kanze, Mar 10, 2011
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Yu Cao
    Replies:
    0
    Views:
    475
    Yu Cao
    Jul 1, 2003
  2. Venkat
    Replies:
    4
    Views:
    1,018
    Venkat
    Dec 5, 2003
  3. Larry R
    Replies:
    1
    Views:
    397
    marss
    Jun 8, 2007
  4. Replies:
    123
    Views:
    2,118
    Tim Rentsch
    Oct 9, 2008
  5. Wirianto Djunaidi
    Replies:
    2
    Views:
    229
    Wirianto Djunaidi
    Apr 29, 2008
Loading...

Share This Page