Como criar um array de strings de tamanho desconhecido?
Estou tentando entender como posso criar um programa C que declara uma "matriz de strings" cujo tamanho é desconhecido no momento da declaração. Isso é o que eu tenho até agora:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n, i;
char** words;
printf("How many strings you want to input? \n");
scanf("%d", &n);
words = malloc(sizeof(char*) * n);
for (i = 0; i < n; i++) {
printf("Input your %d string: ", i + 1);
scanf("%s", words[i]);
}
for (i = 0; i < n; i++) {
printf("%s\n", words[i]);
}
return 0;
}
O programa compila, mas recebo um Segmentation faulterro.
Respostas
Você alocou apenas memória para o ponteiro das strings, mas não para as strings em si. A tentativa de armazenar strings na memória não alocada invoca um comportamento indefinido.
O ponteiro é apenas um ponteiro. Você não pode armazenar strings neles. Você precisa reservar memória para onde o ponteiro deve apontar .
#define STR_SIZE 100 // max length of a string (incl. null terminator)
printf("How many strings you want to input? \n");
if (scanf("%d", &n) != 1)
{
fputs("Error at input", stderr);
// further error routine.
}
// allocate memory for the pointer to the strings.
words = malloc(sizeof(*words) * n);
if (!words)
{
// error routine if the memory allocation failed.
perror("malloc");
exit(EXIT_FAILURE);
}
// allocate memory for the strings themselves.
for (int i = 0; i < n; i++)
{
words[i] = malloc(sizeof(**words) * STR_SIZE);
if (!words[i])
{
// error routine if the memory allocation failed.
perror("malloc");
exit(EXIT_FAILURE);
}
}
Notas laterais:
Sempre verifique o retorno das funções de gerenciamento de memória se um erro aconteceu na alocação! O mesmo vale para operações de entrada como
scanf().Observe que usar
sizeof(*words)e emsizeof(**words)vez desizeof(char*)esizeof(char)é mais seguro caso seu código seja alterado.
Você não alocou a memória corretamente para o ponteiro char individual words[i].
Isso foi ok - você alocou memória para o ponteiro para ponteiro para char words:
words = malloc(sizeof(char*) * n);
Mas você ainda não alocou para indicadores individuais disso words. Para fazer isso, você precisa provisionar quanto buffer para uma palavra individual. Por exemplo, se cada palavra tiver 100 caracteres, então:
for (i = 0; i < n; i++)
{
printf("Input your %d string: ", i + 1);
words[i] = malloc(sizeof(char) * 100); //<--
scanf("%s", words[i]);
}
Lembre-se também de liberar o buffer quando terminar.
for (int i=0; i<n; ++i) {
free(words[i]);
}
free(words);
return 0;