-2
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void) {
    char *names = NULL;
    int capacity = 0;
    int size = 0;

    printf("Type 'end' if you want to stop inputting names\n");
    while (1) {
        char name[100];
        printf("Input:\n");
        fgets(name, sizeof(name), stdin);

        if (strncmp(name, "end", 3) == 0) {
            break;
        }

        if (size == capacity) {
            char *temp = realloc(names, sizeof(char) * (size + 1));

            if (!temp) {
                if (names) {
                    return 1;
                }
            }
            names = temp;
            capacity++;
        }

        names[size] = name;
        size++;
    }

    for (int i = 0; i < size; i++) {
        printf("OUTPUT :%c\n", names[i]);
    }

    if (names) {
        free(names);
    }
}

I am trying to create an array of dynamic length in C but I don't know what is wrong with my code? I think it is cause of how I take the user input and the problem occurs when the code names[size] = name is executed.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
drazer
  • 19
  • 1

2 Answers2

2

You need to declare an array of pointers to strings (char**), not a pointer to a single character string (char*).

This means that when you want to add a new entry, not only do you need to make space for the new pointer in your array (type is char* not char) but you also have to separately allocate storage for the string itself and then set the pointer you just made space for to that allocated string.

Gem Taylor
  • 5,381
  • 1
  • 9
  • 27
0

There are multiple problems in the code:

  • names should be defined as a pointer to an array of char *: char **names = NULL;
  • you must make copies of the strings read with fgets(), otherwise all entries in names will point to the same array name.
  • you actually do not need to distinguish capacity and size if you reallocate one extra slot at a time.
  • the format "OUTPUT :%c\n" is incorrect for a string.

Here is a corrected version:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void) {
    char **names = NULL;
    int capacity = 0;
    int size = 0;

    printf("Type 'end' if you want to stop inputting names\n");
    for (;;) {
        char name[100];
        printf("Input:\n");
        if (!fgets(name, sizeof(name), stdin)) {
            break;
        }
        if (strncmp(name, "end", 3) == 0) {
            break;
        }
        if (size == capacity) {
            // reallocate array with geometric growth
            int new_capacity = capacity + (capacity / 2) + 4;
            char *temp = realloc(names, sizeof(*names) * new_capacity);
            if (!temp) {
                free(names);
                printf("out of memory\n");
                return 1;
            }
            names = temp;
            capacity = new_capacity;
        }
        name[strcspn(name, "\n")] = '\0';  // strip the trailing newline if any
        names[size++] = strdup(name);      // allocate a copy of the string
    }
    for (int i = 0; i < size; i++) {
        printf("OUTPUT: %s\n", names[i]);
    }
    free(names);
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • I tried to compile it but there is 1 error ":25:19: error: cannot initialize a variable of type 'char *' with an rvalue of type 'void *' char *temp = realloc(names, sizeof(*names) * new_capacity);" How do I solve it? – drazer Aug 18 '19 at 14:26
  • @drazer: you should compile the code as **c**, not **c++**. the gcc option is `-x c`. Yo compile as c++, you need a cast: `char *temp = (char *)realloc(names, sizeof(*names) * new_capacity);` – chqrlie Aug 18 '19 at 22:26