Bsearch function issue in C - 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);

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

Related

2D arrays as arguments

I have read a book about C, and I did try, so please be soft with me.
I am trying to understand how memory really works.
I would like to have some words array like this ( in C) :
char builts[20][10]={"light","temp"}; //should it looks like this ?
Then, I would like to pass that array to a function (in another class)
//some class
char *builtinFunctions;
void Intepreter::setBuiltIns( char *builtins)
{
// here - should I save a copy to builtinFunctions ?? how ?
}
The other class need to have access to that array of words all the time.
Why this is gives error : intepreter.setBuiltIns(&builts); ?
How would one declare builtinFunctions ? as a pointer or array ? should it be copied to?
How exactly the whole thing should look like ??
There are multiple ways to pass a 2D array to a function:
The parameter is a 2D array
int array[10][10];
void passFunc(int a[][10])
{
// ...
}
passFunc(array);
The parameter is an array containing pointers
int *array[10];
for(int i = 0; i < 10; i++)
array[i] = (int*)malloc(40); //array[i] = new int[10];
void passFunc(int *a[10]) //Array containing pointers
{
// ...
}
passFunc(array);
The parameter is a pointer to a pointer
int **array;
array = (int*)malloc(40);//array = new int *[10];
for(int i = 0; i <10; i++)
array[i] = (int*)malloc(40); //array[i] = new int[10];
void passFunc(int **a)
{
// ...
}
passFunc(array);
When passing a simple array to a function, you pass it as a pointer (array name is decayed as a pointer to the first element of the array), like this :
int foo[3] = { 3, 2, 1 };
bar(foo);
So your function takes a pointer to an int as parameter :
void bar(int *data) { }
Here you have an array which contains NULL terminated string of length 10 which are arrays too. So, builts is a pointer to his first element so a pointer to an array of 10 char :
char builts[20][10] = {"light", "temp"};
char (*foo)[10] = builts; // This is valid, foo is a pointer to an array of 10 char
So, your function must take an argument of type char (*)[10], because you pass a pointer to an array of 10 char :
void bar(char (*data)[10]) { }
You can pass the 2 day array by just using its name while calling a function, like:
test_2d(builts);
You can either pass the total number of words as a separate argument, or alternatively, you can make a special word to indicate end of your array. For instance, I have used a special word "\0" to indicate that this marks the end of array. Overall the code looks like.
#include<stdio.h>
#include<string.h>
int main(void)
{
char builts[20][10]={"light","temp", "\0"};
test_2d(builts); /* without passing total number of args; depends on special word at the end */
test_2d_num(builts, 2); /* also pass total num of elements as argument */
return 0;
}
/* This needs a special word at the end to indicate the end */
void test_2d(char builts[][10])
{
int i;
char tmp[10];
/* just print the words from word array */
for (i=0; *builts[i] != '\0'; i++ )
printf("%s\n", builts[i]);
/* also try copy words to a tmp word and print */
for (i=0; *builts[i] != '\0'; i++ ) {
strcpy(tmp, builts[i]);
printf("%s\n", tmp);
}
/* Do something */
}
/* Also get total number of elements as a parameter */
void test_2d_num(char builts[][10], int tot_elem)
{
int i;
/* Process each word from the array */
for (i = 0; i < tot_elem; i++) {
printf("%s\n", builts[i]);
/* Do something */
}
}
Note that this function can only process arrays like, builts[][10], and not builts[][11], or builts[][9].
If you want want a generic function, then you need to store the addresses of individual words in an char *arr[] and pass this array to the function. Like
int main()
{
/* store the addresses of individual words in an `char *arr[] */
char *arr[] = {"hello", "this", "that", NULL};
test_2d_gen(arr);
return 0;
}
void test_2d_gen(char *arr[])
{
int i;
/* process each word */
for (i = 0; arr[i] != NULL; i++) {
printf("%s\n", arr[i]);
/* Do something */
}
}

Send struct with char[] in MPI

I'm trying to send some data from workers to a master (ranked 0) in a MPI program in C++. The goal is to pass 2 strings and an integer. To do that, I've created a struct.
The struct
It is called word and defined as follows:
struct word
{
char word_name[str_size];
char url[str_size];
int counter;
};
/* Some important variables to the question */
MPI_Datatype mpi_word_type;
const int str_size = 200;
Previously I was trying this through char * but it doesn't work, since the processes don't share the same memory space.
By now, I'm able to send the struct if I change the variables from char[] to a simple char and try with an example. With this as it is above, I cannot get rid of Segmentation fault errors.
Sending Part - Workers
I start by creating and filling an example struct and then sending the size of the struct first and the struct itself, secondly. Like this:
word word_col;
std::string tmp = "somename";
strcpy(word_col.word_name, tmp.c_str());
std::string tmp2 = "someurl";
strcpy(word_col.url, tmp2.c_str());
word_col.counter = 10;
int size = sizeof(word_col);
MPI::COMM_WORLD.Send(&size, 1, MPI::INT, 0, 1);
MPI::COMM_WORLD.Send(&word_col, size, mpi_word_type, 0, 1);
Receiving Part - Master
const int nitems = 3;
int blocklengths[3] = { str_size, str_size, 1 };
MPI_Datatype types[3] = { MPI::CHAR, MPI::CHAR, MPI::INT };
MPI_Aint offsets[3];
offsets[0] = (MPI_Aint) offsetof(struct word, word_name);
offsets[1] = (MPI_Aint) offsetof(struct word, url);
offsets[2] = (MPI_Aint) offsetof(struct word, counter);
MPI_Type_create_struct(nitems, blocklengths, offsets, types, &mpi_word_type);
MPI_Type_commit(&mpi_word_type);
...
for(...)
{
word word_col;
int size;
MPI::COMM_WORLD.Recv(&size, 1, MPI::INT, MPI::ANY_TAG, 1, status);
MPI::COMM_WORLD.Recv(&word_col, size, mpi_word_type, MPI::ANY_TAG, 1, status);
}
I've been struggling with this for hours and I've seen many examples and another questions about this, but I couldn't figure out what is the problem here.
This is erroneous programming. You have unallocated and uninitialized pointer and you are trying to push data to that.
You have two options:
Either you define your structure as:
const int str_size = 200;
struct word
{
char word_name[str_size]; // fixed sized char array
char url[str_size]; // fixed sized char array
int counter;
};
Or,
const int str_size = 200;
struct word
{
char *word_name; /
char *url;
int counter;
Word() {
word_name = new char[str_size];
url = new char[str_size];
}
~Word() {
delete [] word_name;
delete [] url;
}
};
The idea is that you need to have allocated memory for these variables
Also, while receiving, you have used:
MPI::COMM_WORLD.Recv(&word_col, size, mpi_word_type, MPI::ANY_TAG, 1, status);
Shouldn't it be like below?
MPI::COMM_WORLD.Recv(&word_col, sizeof(word_col), mpi_word_type, MPI::ANY_TAG, 1, status);

How do you use the void pointer in C?

Here are a couple of function declarations that I'm having trouble understanding how to complete. I've scanned the web to see what a void pointer is, and I understand that it must be cast to something to be useful (because it just points to some memory block), but I don't see how that helps in completing these declarations.
/* type of comparison function that specifies a unique order.
Returns 1 if pointer1 should come before,
0 if equal to, or -1 if after pointer2. */
typedef int (*compare_function) (const void* pointer1, const void* pointer2);
/* get the data object */
void* get_obj(const void* item_pointer);
There are more functions like this, but I think if I understand how to do these two I should be in good shape. For example, for the second function, how do we cast the item_pointer to anything appropriate that should be returned?
void * usually means that you are only interested in the address of the data regardless of its type, some of the reasons:
the internal representation of the data this void * pointing to is hidden, you are not supposed to access the data directly, information hiding, your function 2 is properly an example of this case.
the type is known by some function in the call chain, like with qsort and most functions that pass arguments to other functions.
the type is not required because the data the pointer is pointing to will be handled as different type, like with memcpy which may handle the data as bytes, unsigned char *.
Sorting in C with quicksort uses void pointers so that we can sort any data in arrays. The sort function must return -1, +1, or 0 if the parameter b is before, after or the same as parameter a
#include <stdio.h>
#include <stdlib.h>
int sort_order( const void *, const void *);
int main(void)
{
int i;
char alfa[6] = { ’C’, ’E’, ’A’, ’D’, ’F’, ’B’ };
qsort( (char*)alfa, 6, sizeof(char), sort_order);
for (i=0 ; i<5 ; i++) // now in order?
printf("\nchar %d = %c",i, alfa[i]);
printf("\n");
system("PAUSE");
return 0;
}
int sort_order( const void* a, const void* b)
{
if ( *((char*)a) < *((char*)b) ) return -1 ;
else if ( *((char*)a) > *((char*)b) ) return 1 ;
else return 0 ;
}
Then you can sort your own datatypes:
typedef struct { float left; float right;} ears;
typedef struct{ char name[13]; int weight; ears eararea;} monkey;
monkey* Index[4];
for(i=0;i<4;i++)
Index[i]= (monkey* )malloc(sizeof(monkey));
qsort((void* ) Index, 4, sizeof(monkey* ), sort_order);
// Sorted by weight
int sort_order( const void* a, const void* b) {
if((**((monkey** )a)).weight < (**((monkey** )b)).weight) return -1 ;
else if ((**((monkey** )a)).weight > (**((monkey** )b)).weight ) return 1 ;
else return 0 ;
}
Complete program
#include <stdio.h>
#include <stdlib.h>
typedef struct {
float left;
float right;
} ears;
typedef struct {
char name[13];
int weight;
ears eararea;
} monkey;
int sort_monkeys( const void *, const void *);
int main(void)
{ monkey* monkeys[4];
int i;
for(i=0; i<4; i++) {
monkeys[i]= (monkey* )malloc(sizeof(monkey));
monkeys[i]->weight=i*10;
if (i==2)
monkeys[i]->weight=1;
}
for (i=0 ; i<4; i++)
printf("\nchar %d = %i",i, monkeys[i]->weight);
qsort((void* ) monkeys, 4, sizeof(monkey* ), sort_monkeys);
for (i=0 ; i<4; i++) // now in order?
printf("\nmonkey %d = %i",i, monkeys[i]->weight);
return 0;
}
// Sorted by weight
int sort_monkeys( const void* a, const void* b) {
if((**((monkey** )a)).weight < (**((monkey** )b)).weight) return -1 ;
else if ((**((monkey** )a)).weight > (**((monkey** )b)).weight ) return 1 ;
else return 0 ;
}
Any pointer type may be assigned to a void*, this is useful in cases where a function does not need to know the type, or the type information is conveyed by other means. This allows you to write just one function to deal with any pointer type rather than a separate function for each data type.
While you cannot dereference a void* you can cast it to any type and dereference it - the semantics of that - i.e. whether it is meaningful, depends on the code and is not enforced byte compiler.
Frequently a generic function is not interested in the content of some block of data, just its address and often its size.
As a simple example:
void memcopy( void* to, void* from, int length )
{
char* source = (char*)from ;
char* dest = (char*)to ;
int i ;
for( i = 0; i < lengt; i++ )
{
dest[i] = source[i] ;
}
}
int main()
{
typedef struct
{
int x ;
int y ;
} tItem
tItem AllItems[256] = {0} ;
tItem AllItemsCopy[256] ;
memcopy( AllItemsCopy, AllItems, sizeof(AllItems) ) ;
}
See that memcopy() does not need to know what a tItem is in order to copy an array of them, it only needs to know the addresses and the size on the array in bytes. It casts the void* pointer arguments to reinterpret the data as a char array to perform a byte-by-byte copy. To do that it does not need to know the internal semantics of tItem or any other data object passed to it.

How to initialize pointer to pointer with premade data?

I have a pointer to a pointer, since I can't pass dynamic arrays to functions. However, if I want to initialize that pointer-to-pointer with premade data, how can I set it since {a,b,c} notation for arrays won't work for pointers?
You can do this:
static int row1[] = {1, 2, 3};
static int row2[] = {4, 5, 6, 7};
static int row3[] = {8, 9, 10, 11, 12, 13};
static int *pptr[] = {row1, row2, row3};
At this point, pptr can be assigned to an int**:
int **p = pptr;
[This answer is only relevant if you need a double*. Your question was edited to say pointer to pointer - if that's what you need, this answer is not relevant.]
You can do this instead:
double fValues[3] = { 1, 2, 3 };
The variable fValues is already a pointer - array variables without the [] are pointers to the first element of the array. This is not a dynamic array, so you don't need to allocate/free its memory.
Assuming your function that takes a double pointer looks something like this:
void Func(double* pDbl) {...}
you'd call it like this:
Func(fValues);
You can create small dynamic arrays recursively something like this:
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct
{
int* pValues;
size_t Count;
} List;
const List ListEnd = { NULL, 0 };
List NewList(int Value, List SubList)
{
List l;
l.Count = SubList.Count + 1;
if (SubList.Count == 0)
{
l.pValues = malloc(sizeof(int));
}
else
{
l.pValues = realloc(SubList.pValues, l.Count * sizeof(int));
}
if (l.pValues == NULL)
{
// do proper error handling here
abort();
}
// moving data isn't necessary if the list elements are
// in the reverse order
memmove(&l.pValues[1], &l.pValues[0], SubList.Count * sizeof(int));
l.pValues[0] = Value;
return l;
}
void PrintDynArr(int* pValues, size_t Count)
{
while (Count--)
{
printf("%d\n", *pValues++);
}
}
int main(void)
{
int* p;
PrintDynArr(p = NewList(1,
NewList(2,
NewList(3,
NewList(4, ListEnd)))).pValues,
4);
free(p);
return 0;
}
Output:
1
2
3
4

How to cast from char pointer to custom object pointer

I'm using leveldb to store key-value pairs of integer and MyClass objects. Actually, a key can contain more then one of theses objects.
The problem I have appears when retrieving the data from the database. It compiles, however the values of the MyClass members are not the one I put into the database.
std::string value;
leveldb::Slice keySlice = ANYKEY;
levelDBObj->Get(leveldb::ReadOptions(), keySlice, &value);
The std::string value1 can now contain only one MyClass object or more. So how do I get them?
I already tried the following which didn't work;
1.) directly typecasting and memcpy
std::vector<MyClass> vObjects;
MyClass* obj = (MyClass*)malloc( value.size());
memcpy((void*)obj, (void*) (value.c_str()), value.size());
MyClass dummyObj;
int numValues = value.size()/sizeof(MyClass);
for( int i=0; i<numValues; ++i) {
dummyObj = *(obj+i);
vObjects.push_back(dummyObj);
}
2.) reinterpret_cast to void pointer
MyClass* obj = (MyClass*)malloc( value.size());
const void* vobj = reinterpret_cast<const void*>( value.c_str() );
int numValues = value.size()/sizeof(MyClass);
for( int i=0; i<numValues; ++i) {
const MyClass dummyObj = *(reinterpret_cast<const MyClass*>(vobj)+i);
vObjects.push_back(dummyObj);
}
MyClass is a collection of several public members, e.g. unsigned int and unsigned char and it has a stable size.
I know that there are similar problems with only one object. But in my case the vector can contain more then one and it comes from the leveldb database.
EDIT: SOLUTION
I wrote (de)serialization method for MyClass which then made it working. Thanks for the hint!
void MyClass::serialize( char* outBuff ) {
memcpy(outBuff, (const void*) &aVar, sizeof(aVar));
unsigned int c = sizeof(aVar);
memcpy(outBuff+c, (const void*) &bVar, sizeof(bVar));
c += sizeof(bVAr);
/* and so on */
}
void MyClass::deserialize( const char* inBuff ) {
memcpy((void*) &aVar, inBuff, sizeof(aVar));
unsigned int c = sizeof(aVar);
memcpy((void*) &aVar, inBuff+c, sizeof(aVar));
c += sizeof(aVar);
/* and so on */
}
The get method is as follows (put analogously):
int getValues(leveldb::Slice keySlice, std::vector<MyObj>& values) const {
std::string value;
leveldb::Status status = levelDBObj->Get(leveldb::ReadOptions(), keySlice, &value);
if (!status.ok()) {
values.clear();
return -1;
}
int nValues = value1.size()/sizeof(CHit);
MyObj dummyObj;
for( int i=0; i<nValues; ++i) {
dummyObj.deserialize(value.c_str()+i*sizeof(MyObj));
values.push_back(dummyObj);
}
return 0;
}
You have to serialize your class... otherwise, you're just taking some memory and writing it in leveldb. Whatever you get back is not only going to be different, but it will probably be completely useless too. Check out this question for more info on serialization: How do you serialize an object in C++?
LevelDB does support multiple objects under one key, however, try to avoid doing that unless you have a really good reason. I would recommend that you hash each object with a unique hash (see Google's CityHash if you want a hashing function) and store the serialized objects with their corresponding hash. If your objects is a collection in itself, then you have to serialize all of your objects to an array of bytes and have some method that allows you to determine where each object begins/ends.
Update
A serializable class would look something like this:
class MyClass
{
private:
int _numeric;
string _text;
public:
// constructors
// mutators
void SetNumeric(int num);
void SetText(string text);
static unsigned int SerializableSize()
{
// returns the serializable size of the class with the schema:
// 4 bytes for the numeric (integer)
// 4 bytes for the unsigned int (the size of the text)
// n bytes for the text (it has a variable size)
return sizeof(int) + sizeof(unsigned int) + _text.size();
}
// serialization
int Serialize(const char* buffer, const unsigned int bufferLen, const unsigned int position)
{
// check if the object can be serialized in the available buffer space
if(position+SerializableSize()>bufferLen)
{
// don't write anything and return -1 signaling that there was an error
return -1;
}
unsigned int finalPosition = position;
// write the numeric value
*(int*)(buffer + finalPosition) = _numeric;
// move the final position past the numeric value
finalPosition += sizeof(int);
// write the size of the text
*(unsigned int*)(buffer + finalPosition) = (unsigned int)_text.size();
// move the final position past the size of the string
finalPosition += sizeof(unsigned int);
// write the string
memcpy((void*)(buffer+finalPosition), _text.c_str(), (unsigned int)_text.size());
// move the final position past the end of the string
finalPosition += (unsigned int)_text.size();
// return the number of bytes written to the buffer
return finalPosition-position;
}
// deserialization
static int Deserialize(MyClass& myObject,
const char* buffer,
const unsigned int buffSize,
const unsigned int position)
{
insigned int currPosition = position;
// copy the numeric value
int numeric = *(int*)(buffer + currentPosition);
// increment the current position past the numeric value
currentPosition += sizeof(int);
// copy the size of the text
unsigned int textSize = *(unsigned int*)(buffer + currentPosition);
// increment the current position past the size of the text
currentPosition += sizeof(unsigned int);
// copy the text
string text((buffer+currentPosition), textSize);
if(currentPosition > buffSize)
{
// you decide what to do here
}
// Set your object's values
myObject.SetNumeric(numeric);
myObject.SetText(text);
// return the number of bytes deserialized
return currentPosition - position;
}
};