I haved to realise dynamic array in c. Here is the struct of it:
typedef void (*PrintArrayElement)(const void* element);
typedef struct {
size_t size;
size_t capacity;
void** array;
PrintArrayElement printElement; // Callback
} dynamic_array;
I have realised function to add element to array:
void arrayAddItem(dynamic_array* container, void* item)
{
if (container->size == container->capacity)
{
void** temp = container->array;
container->capacity <<= 1;
container->array = (void **)realloc(container->array, container->capacity * sizeof(void*));
if (!container->array)
{
printf("Out of Memory\n");
container->array = temp;
return;
}
}
container->array[container->size] = strdup(item);
container->size++;
}
Also I have function to find word indexes in string:
dynamic_array* findWord(char str[], char keyword[])
{
dynamic_array* indexes;
arrayInit(&indexes, 16, printInt);
int i = 0;
int start = 0;
int end = 0;
size_t len = strlen(str);
while (i < len) {
while (i < len && !isalpha(str[i]))
{
i++;
}
if (isalpha(str[i]))
{
start = i;
while (i < len && isalpha(str[i]))
{
i++;
}
end = i;
char* word = (char*)malloc(end - start + 1);
strncpy(word, &str[start], end - start);
word[end - start] = '\0';
if(strcmp(word, keyword) == 0)
{
printf("%d\n", start);
arrayAddItem(indexes, &start);
}
free(word);
}
}
return indexes;
}
So I write dynamic_array* test_find_array1 = findWord("hello, world, hello", "hello"); and waiting for dynamic_array with two elements: 0 and 14, but I have a dynamic_array with pointers. And the main problem is that sometimes I have the correct answer, but I didn't rewrite the code. Why can it happen?
I tried to rewrite findWord function and arrayAddItem but its still going random way. I have nothing ideas whats wrong. Let me know if I should add some code of other functions from project.
You should provide a minimal reproducible example program that demonstrate the issue. From the question headers are missing as are the implementations of
arrayInit(),printInt()andmain(). Presumably aarrayFree()is also missing otherwise your program leaks memory. I added example implementations for you to test your code.printElementis not used so you should eliminate it.arrayAddItem()will fail ifcapacityis initialized to0. You expect memory to be allocated but isn't.malloc(0)is implementation defined and could be NULL which now runs afoul of check ifrealloc()failed. I added a check and default tocapacity = 1if it was0. It's not wrong to use<<1but* 2probably compiles to the same thing and easier to read at lest to me.The factor
2is fine for small values but2^capacitygrows fast. Say, you have2^10elements (i.e. 8 MB to store void pointers) do you want want to allocate another 8 MB when you hit that?Also it's an optimization so you could see (benchmark) what the overhead is for growing 1 element at a time before doing so in batches.
malloc()may have similar optimizations, or others that result in batches being both slower and wasteful of memory.(not fixed)
arayAddItem():capacitycould overflow which result in data loss whenarrayshrinks.arrayAddItem()usesstrdup()to copyitemwhich means it assumes a string. InfindWord()you pass inintso this will most likely segfault. Changing the API to expect caller to provide a copy of the data and caller is also responsible for free'ing said data (for symmetry). Otherwise you need to tellarrayAddItem()how to copy (i.e. size) whateveritempoints to.arrayAddItem()will return an invalidcontainer->capacityifrealloc()fails (new capacity instead of the old capacity). I updated code to use variables and only updatecontainerupon success to illustrate it (they are not actually used as the program will now exit on failure).arrayAddItem()error handling strategy is inconsistent. You ignore the possibility ofstrdup()failing and return corrupt data ifrealloc()fail. You don't check ifarrayInit()fails so I assume you don't return anything. Now codeexit(1)upon failure. API needs to change to survive these errors but if you are out of memory you probably will quit anyways.(not fixed)
findWord()will fail if eitherstrorkeywordis NULL. You could useassert()if it's a error, or you need a check if it's valid run-time condition that you need to handle.findWord(): minimize scope of variables and avoid thestart = 0andend = 0which initial values art not used.findWord():strlen()returns asize_tbut you useintforstart,endandi. Prefer unsigned types.findWord(): It's silly to go through all that effort to copy the string if you only want to record the starting position. The main thing is that you want tomallocspace for the position so you can pass a pointer toarrayAddItem(). (As an exercise try pass&startto see why that won't work).(not fixed)
findWord(): strings contain a terminating\0. It's common idiom for c code to rely on that instead of calculating the length of a string.and example output: