Gordon Igor
Gordon Igor

Reputation: 35

Bsearch function issue in C

I am trying to use bsearch but the result of search keep staying NULL.My array of names is sorted alphabetically.I am new in C and need your help to understand where am I wrong.

Here is an array

// arrays of children's names
char *chBamba[] = { "Bambale1", "Bamb2", "Bamb3", "Bambook4", "Bambookle5" };
char *chBisli[] = { "Bislile1", "Bischick2", "Bislile3", "Bis4" };
int nBamba = sizeof(chBamba) / sizeof(*chBamba);
int nBisli = sizeof(chBisli) / sizeof(*chBisli);
// array of workers
Worker a[] = { { "Printf", 10, NULL, 0 } ,{ "Bisli", 20, chBisli, nBisli },
{ "TapooChips", 3, chBamba, nBamba },{ "Bamba", 19, chBamba, nBamba } };

This is struct

typedef struct{
char name[LEN]; // worker's name
int salary; // worker's salary
char **childArr; // array of children names
int numChildren; // number of children}Worker;

Compare function

int compareNames(const void* child1, const void* child2){
  char* ch1 = (char*)child1;
  char* ch2 = (char*)child2;
  return strcmp(ch1, ch2);
}

And the bsearch

  char childName[10];
  char* nameFound;
  printf("Please enter a child name to search for :");
  scanf("%s",childName);

  for (i = 0; i < 4; i++)
  {
    nameFound =(char*) bsearch(childName,a[i].childArr, a[i].numChildren, sizeof(a[i].childArr)/ sizeof(a[i].childArr[0]), compareNames);
  }

It is C not C++.That what I am learning right now.I am using VS 2015 and it works for both C and C++.I am editing some changes to get it work correctly and compile. So compare is

int compareNames(const void * s1, const void * s2){
const char *key = (char*)s1;
const char * const *arg = (char**)s2;
return strcmp(key, *arg);

}

and the bsearch is

nameFound = (char*)bsearch(childName,a[i].childArr, a[i].numChildren, sizeof(char*), compareNames);

Upvotes: 0

Views: 630

Answers (1)

alk
alk

Reputation: 70941

The compare function is being passed pointers to the array's elements.

From man bsearch:

The compar routine is expected to have two arguments which point to the key object and to an array member ....

The array's elements are of type char *, so the compare function should look like this:

int compareNames(const void * pvchild1, const void * pvchild2)
{
  const char ** ppc1 = (const char **) pvchild1; // casting necessary with C++
  const char ** ppc2 = (const char **) pvchild2; // casting necessary with C++

  return strcmp(*ppc1, *ppc2);
}

To additionally cover the case that the array contained null-pointer values you could do:

  ...

  return strcmp(ppc1 ?*ppc1 :"", ppc2 ?*ppc2 :"");
}

Call bsearch() like this:

  char * p = childName;
  nameFound =(char*) bsearch( // casting necessary with C++
    &p,
    a[i].childArr, 
    a[i].numChildren, 
    sizeof *(a[i].childArr), 
    compareNames
  );

Also as a side note: The code you show defintily isn't C but C++, as this

Worker a[] = { 
 { "Printf", 10, NULL, 0 } ,{ "Bisli", 20, chBisli, nBisli },
 { "TapooChips", 3, chBamba, nBamba },{ "Bamba", 19, chBamba, nBamba }  
};

won't compile in C, but give the error:

error: initializer element is not constant

Upvotes: 1

Related Questions