动态分配一个字符串数组

Dynamically allocate an array of strings

如何修复这段代码,使其打印数组中的单词?此外,这是为 n 个最大大小为 40 的单词动态分配内存的正确方法吗?

int main() {

    int n;
    char *arr;
    int i;

    printf("Give me a number:");
    scanf("%d", &n);

    arr = malloc(n * 40);

    for (i = 0; i < n; i++)
    {
        printf("Give me a word: ");
        scanf("%s", &arr[i]);
    }

    for (i = 0; i < n; i++)
    {
        printf("%s", arr[i]); //< --problem here
    }

    return 0;
}

这个:

for(i=0;i<n;i++){
    printf("Give me a word: ");
    scanf("%s",&arr[i]);
}

可能不是你想要的。
你可能想要这个:

for(i=0; i<n; i++){
    printf("Give me a word: ");
    scanf("%s", arr + i*40);
}

然后稍后:

for(i=0; i<n; i++){
    printf("%s", arr + i*40);
}

请记住,C 中的字符串只是一个字符数组。 因此,在定义 char *arr 时,您正在创建一个 单个字符串 。如果您完成了 char **arr,它将是一个 字符串数组 ,这就是您想要的。
但是,我发现allocating/freeing arrays of arrays of arrays on the heap 相当不方便,并且更喜欢'flattening' 将它们合并为一个数组。
这正是您对 arr = malloc(n*40) 所做的,但是后来当您将这个 字符 数组视为 字符串 数组时这样做了:

for(i=0; i<n; i++){
    printf("Give me a word: ");
    scanf("%s", &arr[i]);
}

请注意,这实际上是完全合法的(scanf 想要一个 char* 而你给了它一个),但这是一个逻辑错误,因为你给了它第 ncharacter 当你想给它第 n-th array.

哦,是的,别忘了稍后free(arr)

您的分配不是最好的,并且 printf 参数 arr[i] 需要一个 char* 但您传递给它一个 int (一个 char 如果你喜欢)。

这是你应该如何做的,附有评论:

Live demo

#include <stdio.h>
#include <stdlib.h> //for malloc

int main(){
    int n;
    int i;
    
    printf("Give me a number:");
    scanf("%d", &n);

    //declare a variable of pointer to pointer to char
    //allocate memory for the array of pointers to char, 
    //each one capable of pointing to a char array
    char **arr = malloc(n * sizeof *arr);

    if(arr == NULL){ //check for allocation errors
        perror("malloc");
        return EXIT_FAILURE;
    }

    //allocate memory for each individual char array
    for(i = 0; i < n; i++){
        arr[i] = malloc(40); //char size is always 1 byte

        if(arr == NULL){ //check for allocation errors
            perror("malloc");
            return EXIT_FAILURE;
        }
    }

    for (i = 0; i < n; i++){
        printf("Give me a word: ");
        //limit the size of read input to 39 charaters to avoid overflow, 
        //a nul character will be added by scanf
        scanf("%39s", arr[i]);
    }

    for (i = 0; i < n; i++){
        printf("%s\n", arr[i]);
       
    }
     
    for(int i = 0; i < n; i++){ //free the memory for each char array
        free(arr[i]);
    }
    free(arr); //free array of pointers

    return 0;
}

您也可以使用指向 40 个字符的数组的指针以更少的代码完成此操作,这将简化内存分配和释放:

带有注释的示例:

Live demo

#include <stdio.h>
#include <stdlib.h> //for malloc

int main(){
    int n;    
    int i;

    printf("Give me a number:");
    scanf("%d", &n);

    //declare a pointer to array of chars and
    //allocate memory for all the char arrays
    char (*arr)[40] = malloc(n * sizeof *arr);

    if(arr == NULL){ //check for allocation errors
        perror("malloc");
        return EXIT_FAILURE;
    }

    for (i = 0; i < n; i++){
        printf("Give me a word: ");
        scanf("%39s", arr[i]);
    }

    for (i = 0; i < n; i++){
        printf("%s\n", arr[i]);
    }

    free(arr); //free allocated memory

    return 0;
}