2

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?

5
  • Use C++ and std::vector. Commented Nov 19, 2013 at 12:25
  • 3
    I can't use C++ - C is a requirement! Commented Nov 19, 2013 at 12:26
  • @Claudio: No C++ tag, no C++ constructions please... Commented Nov 19, 2013 at 12:38
  • Do you know the length of the input string? Commented Nov 19, 2013 at 12:38
  • Not the exact length. But I assume I can get it with sizeof Commented Nov 19, 2013 at 12:40

3 Answers 3

1

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

Sign up to request clarification or add additional context in comments.

Comments

1

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).

5 Comments

That would cause a realloc for every element... Wouldn't it? Except I'm guessing a size which could be too big in some cases
Only when needed - see updated answer. If you want to get clever then you could allocate it in blocks of 1024 or something.
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?
Sure! I'm not 100% sure what you mean (size of what?), but if you know the size of either the string or array your creating then allocate that number. Remember a string will need an extra char for the null terminator.
@AzzUrr1: Since you're dividing a string into words, I've updated my answer, to offer you an easy (as in 2 lines) way to determine how many pointers you'll need to allocate, so you won't need realloc anymore
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.