How do I create a Dynamic Array in C?

Asked

Viewed 72 times

0

I’m starting programming in C, after learning the basics in Python.

At first I’m trying to write a simple program, which reads input arguments and prints them in reverse, for example, "hello world" would output "odnum álo"

In Python I would write something like:

A = []
for line in sys.stdin:
  A.append(line)
for i in reversed(array):
  print(i)

But in C I don’t know how to create a list without specifying a fixed dimension. To write the above program in C, passing the stdin arguments to an array and then printing it starting at the end, I have something like this in mind:

int c;
int i = 0;
int array;

while ((c = getchar()) != EOF) 
{
  array[i] = c;
  i++;
}

for (int j = array.size; j > 0; j--) 
{
   printf("%s", array[j]);
}

How to create a list that can receive elements up to the EOF, to use in the example code above?

  • Declare array as a pointer to int and make a dynamic allocation like malloc/calloc/realoc of <stdlib. h>.

  • Search for dynamic memory allocation. For implementation, search for functions malloc, free and realloc.

  • I read about these functions, but in the documentation it says that malloc aloca o número especificado de bytes, That doesn’t mean she still keeps a pre-defined limit?

  • You can, for example, allocate an element with malloc and to each new element you want to add make a realloc. Or use a chained list.

1 answer

1


But in C I don’t know how to create a list without specifying a fixed dimension.

Lists like Python do not exist in the C language. There are only simpler data structures.

You need to create your own data structure if you want a dynamic list that holds any number of elements. The programmers who wrote Cpython did the same thing.

How to create a list that can receive elements up to the EOF, to use in the example code above?

You need to allocate the right amount of memory to store all the elements. The quantity of items shall only be revealed during the implementation of the programme when getchar() returns EOF.

To solve this, it is necessary to create a data structure that is able to dynamically expand its capacity during the execution of the algorithm:

struct lista {
    size_t quantidade;
    size_t capacidade;
    char *elementos;
} lista;

Using the function malloc, we can ask the operating system to allocate an initial amount of memory to our list:

#define CAPACIDADE_INICIAL 8

lista.quantidade = 0;
lista.capacidade = CAPACIDADE_INICIAL;
lista.elementos = malloc(CAPACIDADE_INICIAL);

We can then read the elements one by one until we receive EOF:

int retorno;

while (EOF != (retorno = getchar())) {
    lista.elementos[lista.quantidade++] = retorno;
}

The list initially has 0 elements and capacity for 8 elements. You can use the element counter as the list index, incrementing it every time an element is added.

What happens when the amount equals the capacity? It means that we have reached the limits of the current list and we will need to expand the memory it behaves before adding new elements.

It is possible to do this with the function realloc:

if (lista.quantidade >= lista.capacidade) {
    lista.capacidade += CAPACIDADE_INICIAL;
    lista.elementos = realloc(lista.elementos, lista.capacidade);
}

Every time the list gets full up to its maximum capacity, the system expands that maximum capacity and allocates more memory so the list can hold that new maximum capacity.

When you receive EOF, the list shall be filled in with all read elements and the code may continue writing the entries in reverse order.

  • I’m managing to make it work, thanks for the detailed explanation. I just don’t understand why the initial capability is equal to 8 at the beginning

  • 1

    @Pirategull, it’s just an arbitrary value. It could be 0, 1, 10, 100, 1000... The lower the initial capacity, the greater the amount of memory relocations, costly operations and that are within a loop. The higher the initial capacity, the greater the initial memory expenditure. The ideal is to guess a number close to the amount of elements in practice and allocate capacity as close as possible to that number. There are more efficient ways to implement this capacity expansion, but they are less didactic.

  • comprendi, I did not know about #define. your answer has helped me tremendously, I am studying everything little by little. If it’s not too much to ask, you could write printf() syntax to print list elements when it comes to pointers?

  • 1

    @Pirategull, as we have a list of chars, the format is the same as the char common: printf("%c", lista.elementos[i]);. Read the documentation for more options.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.