bsearch() doesn't find my item

438 views Asked by At

could anybody tell me why bsearch() in the following code does NOT find the item "getwidth" in the list? I tried several compilers and it works with none of them so it must be a bug in my code. However, I really don't see what's wrong there. The callback passed to bsearch() always returns something that is != 0 but still, it is only called 5 times and then NULL is returned by bsearch() although it didn't iterate over all items. Why is that?

Here is the code:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

typedef struct wxLuaBindMethod
{
    const char *name;
    int method_type;
    void *wxluacfuncs;
    int wxluacfuncs_n;
    void *basemethod;
} wxLuaBindMethod;

#define WXLUAMETHOD_CONSTRUCTOR 0x0001
#define WXLUAMETHOD_METHOD 0x0002
#define WXLUAMETHOD_DELETE 0x2000

wxLuaBindMethod wxSize_methods[] = {
    { "DecBy", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "DecTo", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "GetHeight", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "GetWidth", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "IncBy", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "IncTo", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "IsFullySpecified", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "Scale", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "Set", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "SetDefaults", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "SetHeight", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "SetWidth", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "delete", WXLUAMETHOD_METHOD|WXLUAMETHOD_DELETE, NULL, 1, NULL},
    { "op_add", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "op_div", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "op_eq", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "op_iadd", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "op_idiv", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "op_imul", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "op_isub", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "op_mul", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "op_ne", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "op_set", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "op_sub", WXLUAMETHOD_METHOD, NULL, 1, NULL},
    { "wxSize", WXLUAMETHOD_CONSTRUCTOR, NULL, 1, NULL},
    { 0, 0, 0, 0 },
}; 

int wxLuaBindMethod_CompareByNameFnGet(const void *p1, const void *p2)
{
    int v = strcasecmp(((const wxLuaBindMethod*)p1)->name, ((const wxLuaBindMethod*)p2)->name);

    printf("CMP: %s = %s? --> %d\n", ((const wxLuaBindMethod*)p1)->name, ((const wxLuaBindMethod*)p2)->name, v);

    return v;
}

int main(int argc, char *argv[])
{
    wxLuaBindMethod methodItem = { "getwidth", 10, 0, 0, 0 };
    wxLuaBindMethod *wxlMethod;

    wxlMethod = (wxLuaBindMethod *)bsearch(&methodItem, wxSize_methods, 25, sizeof(wxLuaBindMethod), wxLuaBindMethod_CompareByNameFnGet);

    printf("RESULT: %p\n", wxlMethod);

    return 0;                                                       
} 

And here is the output this program generates:

CMP: getwidth = delete? --> 3
CMP: getwidth = op_isub? --> -8
CMP: getwidth = op_iadd? --> -8
CMP: getwidth = op_div? --> -8
CMP: getwidth = op_add? --> -8
RESULT: 0x0

I really don't see why it doesn't work although it's really only a few lines. Can somebody shed some light onto this strange behaviour? Thanks!

2

There are 2 answers

1
3xian On BEST ANSWER

Because wxSize_methods is not sorted by case-insensitive alphabetic order. You should sort wxSize_methods by strcasecmp before binary search.

0
Ingo Leonhardt On

You compare the method names using strcasecmp() but according to that your list is not properly sorted (e.g. "delete" < "GetWidth"). Use strcmp() instead or sort your list.