The way you reallocate the array is fine, albeit inefficient. The reason you do not get the expected output is you output the first element 3 times.
It is recommended to allocate arrays in a single shot if you know the final length in advance, in other cases, where large arrays need to be reallocated on the fly, it is recommended to reallocate using increasing sizes following a geometric progression:
Here is an example using the golden ratio:
#include <stdlib.h>
#include <stdio.h>
int main() {
char *arr = NULL;
size_t size = 0;
size_t pos = 0;
int c;
while ((c = getchar()) != EOF) {
if (pos + 1 > size) {
// increase size by a ratio of 1.625
// with an offset to handle the initial case without a test
size_t new_size = size + (size >> 1) + (size >> 3) + 32;
char *new_arr = realloc(arr, sizeof(*arr) * new_size);
if (new_arr == NULL) {
fprintf(stderr, "cannot reallocate array for %zu bytes\n", new_size);
free(arr);
return 1;
}
arr = new_arr;
size = new_size;
}
arr[pos++] = c;
}
if (arr == NULL) {
fprintf(stderr, "empty file\n");
return 1;
}
arr[pos] = '\0';
char *new_arr = realloc(arr, sizeof(*arr) * (pos + 1));
if (new_arr != NULL) {
arr = new_arr;
size = pos + 1;
}
/* more code to handle full buffer */
free(arr);
return 0;
}