bsearch() with dynamic array

S

Steph

Hello,

I have filled a dynamic array of strings (realloc() + malloc())

char **sMyArray;

At the end, I get correctly sMyArray[0] = "STRING_0", sMyArray[1] =
"STRING_1", etc...

But I'm unable to use bsearch(). It doens't find any string.

(and nSize = sizeof(sMyArray[0]) = 4, which is not what I would want (8))

Is it possible ?

Thanks in advance.
 
R

Richard Heathfield

Steph said:
Hello,

I have filled a dynamic array of strings (realloc() + malloc())

char **sMyArray;

At the end, I get correctly sMyArray[0] = "STRING_0", sMyArray[1] =
"STRING_1", etc...

But I'm unable to use bsearch(). It doens't find any string.

(and nSize = sizeof(sMyArray[0]) = 4, which is not what I would want
(8))

It might not be what you want, but it's what you get when you use sizeof
to calculate the number of bytes occupied by a pointer (on your
platform, at least - the number may vary on other platforms).
Is it possible ?

It is certainly possible to use bsearch to find a string within a sorted
array of strings, yes. I conclude that there is a bug in your program.
Solution: find and fix the bug.
 
E

Eric Sosman

Steph said:
Hello,

I have filled a dynamic array of strings (realloc() + malloc())

char **sMyArray;

At the end, I get correctly sMyArray[0] = "STRING_0", sMyArray[1] =
"STRING_1", etc...

But I'm unable to use bsearch(). It doens't find any string.

(and nSize = sizeof(sMyArray[0]) = 4, which is not what I would want (8))

Is it possible ?

My guess is that you are confused about the nature
of your dynamic array. You have not created an array
of four eight-char strings, but an array of four char*
pointers that in turn point to the beginnings of the
strings. The comparison function therefore receives
two void* pointers that point to two char* pointers
that point to the characters, and you must handle this
arrangement correctly in your comparison function.

By the way, "STRING_0" is eight characters long but
requires *nine* characters of storage. If you're trying
to cram these nine-character objects into eight-character
slots, that's yet another source of trouble.
 
P

pete

Steph said:
Hello,

I have filled a dynamic array of strings (realloc() + malloc())

char **sMyArray;

At the end, I get correctly sMyArray[0] = "STRING_0", sMyArray[1] =
"STRING_1", etc...

But I'm unable to use bsearch(). It doens't find any string.

(and nSize = sizeof(sMyArray[0]) = 4,
which is not what I would want (8))

Is it possible ?

/* BEGIN new.c */

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

#define KEY "STRING_8"
#define TEN {"STRING_0","STRING_1", \
"STRING_2","STRING_3","STRING_4","STRING_5", \
"STRING_6","STRING_7","STRING_8","STRING_9"}

#define NMEMB(A) (sizeof (A) / sizeof (*A))

int comparison(const void *, const void *);
void free_sMyArray(char **sMyArray, size_t nmemb);

int main(void)
{
char *ten[] = TEN;
char *key = KEY;
char **sMyArray;
char **found;
size_t index;

sMyArray = malloc(NMEMB(ten) * sizeof *sMyArray);
for (index = 0; index != NMEMB(ten); ++index) {
sMyArray[index] = malloc(sizeof "STRING_8");
if (sMyArray[index] == NULL) {
free_sMyArray(sMyArray, index);
puts("sMyArray[index] == NULL");
exit(EXIT_FAILURE);
}
}
qsort(ten, NMEMB(ten), sizeof *ten, comparison);
for (index = 0; index != NMEMB(ten); ++index) {
strcpy(sMyArray[index], ten[index]);
puts(sMyArray[index]);
}
putchar('\n');
printf("searching for %s\n", key);
found = bsearch
(&key, sMyArray, NMEMB(ten), sizeof *ten, comparison);
if (found == NULL) {
puts("found == NULL");
} else {
printf("found %s\n", *found);
}
free_sMyArray(sMyArray, NMEMB(ten));
return 0;
}

int comparison(const void *a, const void *b)
{
return strcmp(*(const char **)a, *(const char **)b);
}

void free_sMyArray(char **sMyArray, size_t nmemb)
{
while (nmemb-- != 0) {
free(sMyArray[nmemb]);
}
free(sMyArray);
}

/* END new.c */
 
B

Barry Schwarz

Steph said:
Hello,

I have filled a dynamic array of strings (realloc() + malloc())

char **sMyArray;

At the end, I get correctly sMyArray[0] = "STRING_0", sMyArray[1] =
"STRING_1", etc...

But I'm unable to use bsearch(). It doens't find any string.

(and nSize = sizeof(sMyArray[0]) = 4,
which is not what I would want (8))

You may think you want 8 but your code (calls to malloc) asks for 9
which is the correct value. Remember, each of your strings has a
terminating '\0'.

However, you are not sorting the strings. You are sorting the
pointers to string (technically char*). Each of the pointers is four
bytes (on your system) regardless of how long the string it points to
is.

Your code worked fine when I compiled and executed it.

I also
reordered TEN so that qsort will not find everything already
sorted.
changed KEY to specify other strings, both present and not
present.

The code still worked fine.

You probably need to post a portion of the real code that is
exhibiting the problem. But based on you comment about nSize above,
you might first want to make sure you are not overrunning any
allocated memory. If you are, it would lead to undefined behavior
which could manifest itself as you describe.
/* BEGIN new.c */

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

#define KEY "STRING_8"
#define TEN {"STRING_0","STRING_1", \
"STRING_2","STRING_3","STRING_4","STRING_5", \
"STRING_6","STRING_7","STRING_8","STRING_9"}

#define NMEMB(A) (sizeof (A) / sizeof (*A))

int comparison(const void *, const void *);
void free_sMyArray(char **sMyArray, size_t nmemb);

int main(void)
{
char *ten[] = TEN;
char *key = KEY;
char **sMyArray;
char **found;
size_t index;

sMyArray = malloc(NMEMB(ten) * sizeof *sMyArray);

You check the other calls to malloc; you should check this one also.
for (index = 0; index != NMEMB(ten); ++index) {

The usual idiom for this kind of for loop uses < instead of !=.
sMyArray[index] = malloc(sizeof "STRING_8");
if (sMyArray[index] == NULL) {
free_sMyArray(sMyArray, index);
puts("sMyArray[index] == NULL");
exit(EXIT_FAILURE);
}
}
qsort(ten, NMEMB(ten), sizeof *ten, comparison);
for (index = 0; index != NMEMB(ten); ++index) {
strcpy(sMyArray[index], ten[index]);
puts(sMyArray[index]);
}
putchar('\n');
printf("searching for %s\n", key);
found = bsearch
(&key, sMyArray, NMEMB(ten), sizeof *ten, comparison);
if (found == NULL) {
puts("found == NULL");
} else {
printf("found %s\n", *found);
}
free_sMyArray(sMyArray, NMEMB(ten));
return 0;
}

int comparison(const void *a, const void *b)
{
return strcmp(*(const char **)a, *(const char **)b);
}

void free_sMyArray(char **sMyArray, size_t nmemb)
{
while (nmemb-- != 0) {

The usual idiom in this case is
for (i = 0; i < nmemb; i++)
free(sMyArray[nmemb]);
}
free(sMyArray);
}

/* END new.c */


Remove del for email
 

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,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top