C - 动态调整二维字符数组的大小

C - dynamically resizing a 2 dimensional char array

大家好,我需要你们的专业知识!

如标题所示,我想调整 2 dim 的大小。 C 中的 char array。我已经知道如何使用更简单的数据结构来实现它:

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

int main( void ){
    int *store;
    int capacity = 3;
    store = malloc(capacity * sizeof(int));
    store[0] = 0;
    store[1] = 1;
    store[2] = 2;

    /* need more storage */

    int new_capacity = 5;
    int *more_storage = realloc(store, new_capacity);
    more_storage = store;

    more_storage[3] = 3;
    more_storage[4] = 4;
    // Is this free() command dangerous? 
    free(store);
    /* this for loop gives me the correct integers, so i can proof that more_storage indeed contains all the
    values, that have been stored in store*/
    for (int i = 0; i < new_capacity; i++){
        printf("%d\n", more_storage[i]);
    }

    /* I have succesfully created a new array, that contains all the old integers plus 
    the new ones */ 

    return 0;
}

现在让我们进入热门话题: 再次做同样的事情,只使用 char-array,它存储未知数量的字符串,最大长度为 100(或其他):

char [???][100];

尽管你们中的一些人可能会摇头,但我 post 我的 下面的方法:(请客气,我是 c-beginner :P )

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

int main( void ){
    //this means to be the 2 - dim array. not sure, if i'm wrong yet.
    char *store[100];
    int capacity = 3;
    store[100] = malloc(capacity * 100 * sizeof(char));
    // This (below) already causes a segmentation fault... :/ 
    strcpy(store[0], "Hi");

    /*Okai, im done yet.. */ 



}

这里还有一种方法,可能对您的娱乐有用:

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

int main( void ){
    char **store;
    int capacity_words = 3;
    int capacity_letters = 100;
    /* Means: char store[3][100]*/

    store = malloc(capacity_words * capacity_letters *sizeof(char));
    strcpy(store[0], "Hi");
    //Segmentation fault again..
    // Damn..! Programming is hard..:D 

}

好的,这就是我的知识底线,有人可以与我分享他或她的答案吗? :)

(我使他的内容更加详细和通用,因为我希望这也可以作为任何其他艺术学者的答案。)

可以将一维数组用作二维数组,但对于像字符串这样的可变长度数据,它的工作量超过了它的价值。如果你这样做,那么你需要一个指针,而不是指向指针的指针。

对于字符串,您需要分配一个指针数组,例如

char **store = malloc(initial_size * sizeof(*store));

for (size_t i = 0; i < initial_size; ++i)
    store[i] = some_string;  // alternatively strdup(some_string) or similar

然后当你需要重新分配这个数组时,你可以像对一维数组那样做:

char **new_store = realloc(store, new_size * sizeof(*new_store));
if (new_store == NULL)
{
    fprintf(stderr, "Error reallocating memory\n");
    exit(EXIT_FAILURE);
}
store = new_store;

for (size_t i = initial_size; i < new_size; ++i)
    store[i] = ...; // Initialize new memory

代码 1) 你不应该 free(store) - 它要么已经被之前的 realloc 释放了,要么等于 new_storage(如果 realloc 决定旧块适合新大小)。

代码 2) 数组被放入堆栈中,并且在不破坏堆栈的情况下无法选择增长。

代码 3) 这很合理,但请注意,您不仅应该分配数组本身(外部维度),还应该分配每个内部维度(capacity_word 乘以字符串)。 strncpy 在这里不可用,因为 store[0] 尚未初始化;相反,试试

store[0] = strdup("Hi");
store[1] = strdup("There");
store[2] = strdup("!");

定义

char *store[100];

创建一个包含 100 个字符指针的数组。您可以将现有字符串分配给这些指针,也许是您通过 strdup 获得的字符串,但您不能将它们 strcpy 分配给它们,因为它们未初始化并且没有指向任何合理的地方。

您可以创建一个指向 100 个字符数组的指针:

char (*store)[100];

现在您可以为该指针分配内存并使用它:

int capacity = 3;

store = malloc(capacity * sizeof(*store));
strcpy(store[0], "orange");
strcpy(store[1], "green");
strcpy(store[2], "mauve");

重新分配同样有效:

capacity = 5;
store = realloc(store, capacity * sizeof(*store));

store[3] = 3;
store[4] = 4;

(我已将新内存分配给相同的 space,这通常是您想要的。但是,如果重新分配失败,这将丢失原始数据。请参阅 Joachim 的示例以了解如何处理该问题例。)

当然你应该在使用后释放分配的内存:

for (int i = 0; i < capacity; i++) puts(store[i]);

free(store);

这种方法可能既浪费又限制,因为你浪费了很多space用于短字符串并且仍然被限制在99个字符以内。根据需要多少分配内存可能会更好。 (但至少此方法立即为每个字符串提供 100 个字符。唯一涉及的分配和释放是 store 本身。)