【问题标题】:How to create a dynamic array that holds static arrays in C?如何在 C 中创建一个包含静态数组的动态数组?
【发布时间】:2018-02-26 16:45:37
【问题描述】:

我的程序解析代码,并且在解析代码时,我需要根据我计划稍后创建的这些信息,跟踪每 x 行(可能每 10 行左右)它通过的每个关键字的实例数带有 gnuplot 的直方图,但这并不重要。

所以有 13 个关键字,我可以很容易地用一个 0 的数组来计算它们,其中每个索引代表一个关键字,每当我找到一个关键字时,我将它的索引增加 1。好吧,很简单

int keywordcount[13]={0};

问题是我需要每 10 行创建一个新的keywordcount,而且我不知道该文件有多少代码行。所以这告诉我应该有一个keywordcount 数组的动态数组。

如何在 C 中声明这个动态数组数组以及如何添加keywordcount 数组?我仍然对 C 中的多维数组感到困惑。我不知道是否应该将其声明为指针数组或什么,我不知道如何为它分配一个新的 keywordcount 数组当创建keywordcount 的函数返回时不会消失。如果有不清楚的地方请告诉我。

【问题讨论】:

  • 使用 typedef 声明一个 13 字节的数组类型,然后对该类型的数组使用 realloc。

标签: c arrays pointers memory-management keyword


【解决方案1】:

您可以使用malloc()calloc() 创建静态数组的动态数组。例如,这将keywordcount_arr 定义为指向13 个ints 数组的指针(这里为max_lines 这样的数组分配了足够的内存):

size_t max_lines = 10;
int (*keywordcount_arr)[13] = calloc(max_lines, sizeof *keywordcount_arr);

如果在此处使用typedef,可能会使代码更易于阅读和编写:

typedef int KW_Count[13];

/* ... */

KW_Count *keywordcount_arr = calloc(max_lines, sizeof *keywordcount_arr);

您可以使用二维数组索引来索引分配的内存:

for (size_t i = 0; i < 13; i++) {
    keywordcount_arr[0][i] = i;
}

或者,如果必须将现有数组存储在动态数组中,则可以使用memcpy()。如果动态数组需要增长,可以使用realloc()。并且realloc() 可以再次用于将动态分配修剪为最终大小:

max_lines *= 2;
KW_Count *temp = realloc(keywordcount_arr,
                         sizeof *keywordcount_arr * max_lines);

这是一个示例程序:

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

#define NUM_KEYWORDS  13

typedef int KW_Count[NUM_KEYWORDS];

int main(void)
{
    size_t max_lines = 10;
    size_t num_lines = 0;
    KW_Count *keywordcount_arr = calloc(max_lines, sizeof *keywordcount_arr);
    if (keywordcount_arr == NULL) {
        perror("Allocation failure");
        /* Handle error... perhaps: */
        exit(EXIT_FAILURE);
    }

    /* Store keyword counts directly in keywordcount_arr[] */
    ++num_lines;
    for (size_t i = 0; i < NUM_KEYWORDS; i++) {
        keywordcount_arr[0][i] = i;
    }

    /* Or use memcpy() if an existing array must be stored */
    ++num_lines;
    KW_Count keywordcount = { 0, 2, 0, 0, 3, 1, 0, 0, 0, 1, 2, 0, 1 };
    memcpy(keywordcount_arr[1],
           keywordcount,
           sizeof *keywordcount * NUM_KEYWORDS);

    /* Use realloc() to grow the dynamic array as needed */
    max_lines *= 2;
    KW_Count *temp = realloc(keywordcount_arr,
                             sizeof *keywordcount_arr * max_lines);
    if (temp == NULL) {
        perror("Unable to reallocate");
        /* Handle error */
    } else {
        keywordcount_arr = temp;
    }

    /* Use realloc() to trim the dynamic array to final size */
    temp = realloc(keywordcount_arr, sizeof *keywordcount_arr * num_lines);
    if (temp == NULL) {
        perror("Unable to reallocate");
        /* Handle error */
    } else {
        keywordcount_arr = temp;
    }

    /* Display array contents */
    for (size_t i = 0; i < num_lines; i++) {
        for (size_t j = 0; j < NUM_KEYWORDS; j++) {
            printf("%5d", keywordcount_arr[i][j]);
        }
        putchar('\n');
    }

    /* Cleanup */
    free(keywordcount_arr);

    return 0;
}

程序输出:

    0    1    2    3    4    5    6    7    8    9   10   11   12
    0    2    0    0    3    1    0    0    0    1    2    0    1

【讨论】:

    【解决方案2】:

    假设将创建多少个keywordcounts。假设您几乎可以肯定会创建其中的 10 个。

    您可以动态地声明一个 10 行 13 列的二维数组。

    现在keywordcount[0] 将成为第一个keywordcount 数组(大小为13)的索引,以此类推。

    现在,如果在实际操作中您发现需要超过 10 个关键字计数数组,您可以使用 realloc() 动态增加二维数组的大小。


    PS:一个好的提示是每次需要增加二维数组的大小时将其大小增加一倍(而不是每次增加一行,这样可以避免重定位,这可能会损害性能)在某些情况下)。

    【讨论】:

    • 不,您不能在声明为 int keywordcount[10][13]; 的数组上使用 realloc()。为了使用这种方法,您必须从一开始就动态分配它。
    【解决方案3】:

    不要接触二维数组、数组数组、指针数组、指向数组的指针或任何此类废话。

    将静态大小的数组包装在 struct 中。

    typedef struct
    {
      int keyword_count[13];
    } fragment_info;
    

    拥有一个fragment_info 的动态数组,就像创建任何其他动态数组一样:

    fragment_info* infos = malloc(initial_capacity * sizeof(*infos));
    ....
    fragment_info* new_infos = realloc(infos, new_capacity * sizeof(*new_infos));
    

    现在,如果您想存储有关 10 行片段的其他信息,您可以自然地保存它。只需向struct 添加更多字段。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-07
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多