Reputation: 2486
I need to fill an c array with a number of objects which I don't know before the process of filling is completed.
It's an array of strings. Another addition: I'm dividing a string into it's words so I know the size of the string. Cloud this be helpful to guess the right size?
I need to have something like an mutable array.
How can I achieve this?
Upvotes: 2
Views: 738
Reputation: 76413
Update
Given that you're chunking the string (dividing it into words), you could count the number of spaces, giving you an idea of how big an array you'll need:
char givenString[] = "The quick brown fox jumps over the lazy dog";
int i;
for (i=0;givenString[i];givenString[i] == ' ' ? ++i : givenString++);
++i;// + 1 for the last word
Now i
will tell you how many words there are in the given string. Then you can simply do:
char **words = malloc(i*sizeof(char *));
And set about your business. Of course, you'll still have to allocate each word pointer, and free it. Perhaps this is a decent use-case for strtok
, BTW:
//assuming i still holds the word-count
words[0] = strtok(givenString, " ");//
for (int j=1;j<i;++j)
{
words[j] = strtok(NULL, " ");
}
You might want to look into strtok_r
if you're going to be doing a lot of this string-splitting business, though.
You could use realloc
for that. realloc
changes the size of the block of memory that a given pointer points to. If the pointer points to NULL
, realloc
behaves like malloc
char **ptr_array = NULL;
for (int i=1;i<argc;++i)
{
ptr_array = realloc(ptr_array, i*sizeof(char *));
ptr_array[i-1] = calloc(strlen(argv[i]) + 1, sizeof(char));
strncpy(ptr_array[i-1], argv[i], strlen(argv[i]));
}
This code will copy all arguments to heap memory, one by one allocating memory for the memory required. Don't forget the free
calls, mind you!
Here's an example in full (including free
-calls)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char **ptr_array = NULL;//pointer to pointers
int i, argc = 5;//fake argc, argv
char *argv[5] = {"me","foo","bar","zar", "car"};//dummy strings
for (i=1;i<argc;++i)
{
ptr_array = realloc(ptr_array, i*sizeof(char *));//(re-)allocate mem
ptr_array[i-1] = calloc(strlen(argv[i]) + 1, sizeof(char));//alloc str
strncpy(ptr_array[i-1], argv[i], strlen(argv[i]));//copy
}
--argc;
for(i=0;i<argc;++i)
{
printf("At index %d: %s\n", i, ptr_array[i]);//print
free(ptr_array[i]);//free string mem
}
free(ptr_array);//free pointer block
return 0;
}
I've tested this code, and the output was, as you'd expect:
At index 0: foo
At index 1: bar
At index 2: zar
At index 3: car
Upvotes: 1
Reputation: 15055
You could use realloc
to declare your array and change its size when needed.
myStrArray = realloc(myStrArray, MaxArray * sizeof(char*));
Realloc will return the same block of memory in most cases until it's "full" and then it will move the memory and contents to somewhere else.
Please note this is an array of pointers and so the strings themselves will need to be allocated or assigned to it. To allocate a 100 char string to the first element, for example:
myStrArray[0] = calloc(100, sizeof(char));
And always free your allocated memory with free
(realloc, calloc, malloc).
Upvotes: 1
Reputation: 42984
Since you don't know a priori the size of the array, you must use malloc()
to dynamically allocate the memory for the array and for the strings contained in it.
You then must use free()
to release this memory when it is no longer needed.
To have good locality, you may want to allocate a single chunk of memory for the strings in the array, considering a data structure like double-NUL terminated strings.
Upvotes: 0