Search only one column of a multi-dimensional array

A

Angus

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
 
V

Victor Bazarov

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
 
A

Angus

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

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?
 
V

Victor Bazarov

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

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
 
J

James Kanze

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.)
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.)
 
A

Angus

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.)
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.)

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;
}
 
A

Angus

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.)
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.)

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;
}
 
V

Victor Bazarov

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
 
A

Angus

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)

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

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

Victor Bazarov

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)

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
 
A

Angus

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 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.
 
J

James Kanze

On Mar 7, 6:05 pm, Victor Bazarov <[email protected]> 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.
 
J

James Kanze

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.
 
J

James Kanze

On 3/9/2011 4:52 PM, James Kanze wrote:
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).
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top