【问题标题】:Adding a 1-dimensional list to a 2D list将一维列表添加到二维列表
【发布时间】:2021-08-06 06:30:34
【问题描述】:
#include <stdio.h>
#include <stdlib.h>

int make_2d_arr(int x, int y){
     int **last = (int **)malloc(sizeof(int *)*y);
     for (int i=0;i<y;++i){
          last[i] = (int *)malloc(sizeof(int)*x);
     }
     return last;
}

int main(){
     int *example_arr = (int *)malloc(sizeof(int)*3);
     int **last = make_2d_arr(3,4);
     example_arr[0] = 11;
     example_arr[1] = 22;
     example_arr[2] = 33;
     last[1] = example_arr;
     return 0;
}

我的代码和上面一样。正如你可以想象的那样,我遇到了“分段错误”。 我想做的是将一维数组添加到二维数组中。 我怎样才能正确且没有错误地做到这一点? 我应该写一个像下面这样的代码吗?

...

void add_2d_arr_1d(int **two_dimensional_arr, int *one_dimensional, int index_2d, int len_one_dimensional){
     for (int i=0;i<len_one_dimensional;++i){
           two_dimensional[index_2d][i] = one_dimensional[i];
     }
}
...

!!!除了我写的第一个代码之外,还添加了上面的“add_2d_arr_1d”函数。

【问题讨论】:

    标签: c multidimensional-array malloc


    【解决方案1】:

    除了@MarkSouls 回答中解决的函数类型问题,目前还不清楚您为什么使用xy(大概是rowscols)并分配给y 行的@987654327 @科尔斯?它看起来是转置的,但无论它们是否向后,只需重新排列即可纠正行/列问题。

    您需要了解,在分配以模拟 2D 数组(实际上不涉及任何数组)时,您有一个两步过程。您必须首先分配rows 的指针数量并将起始地址分配给last。然后您必须循环 rows 次,为 cols 整数个数分配存储空间,并依次为每个指针分配起始地址。

    您还必须验证通过检查返回以确保分配了存储空间,如果不是malloc()calloc()realloc())将失败时返回NULL。您需要处理该错误。另外,在C语言中,malloc的返回不需要强制转换,没有必要。见:Do I cast the result of malloc?

    在模拟 2D 数组时,如果您没有显式初始化每个值,则应考虑使用 calloc() 分配并将所有字节设置为零,以确保您不会意外从未初始化的内存中读取地址。

    综上所述,您的 make_2d_arr() 函数可以写成:

    int **make_2d_arr (int rows, int cols)
    {
        int **last = malloc (sizeof *last * rows);      /* allocate rows number of pointers */
        
        if (!last) {                                    /* validate EVERY allocation */
            perror ("malloc-last");
            return NULL;
        }
        
        for (int i = 0; i < rows; i++) {                /* loop rows times */
            last[i] = calloc (cols, sizeof *last[i]);   /* allocate/initialize cols int */
            if (!last[i]) {                             /* validate EVERY allocation */
                perror ("calloc-last[i]");
                while (i--)                             /* loop to free prior allocations */
                    free (last[i]);                     /* free each row of int */
                free (last);                            /* free pointers */
                return NULL;
            }
        }
        
        return last;            /* on success return pointer to allocated block of pointers */
    }
    

    (注意:在为每一行分配cols价值int时,如果calloc()失败,则需要free()所有之前分配的行,然后在返回之前释放指针NULL 以避免造成内存泄漏。)

    如果不使用以下内容覆盖原始 last[1] 指针,则无法分配内存块:

    last[1] = example_arr;
    

    发生这种情况时,last[1] 的分配整数的原始地址将被example_array 的地址覆盖。 last[1] 指针丢失,您无法释放分配的内存。相反,您需要将example_arr 的内容复制到模拟二维数组的第二行。只需包含string.h 和:

        /* you cannot overwrite pointers, you must copy (or loop and assign each) */
        memcpy (last[1], example_arr, rows * sizeof *example_arr);
    

    把一个完整的例子放在一起,然后将example_arr 的填充重新排列为一个简单的循环,您将拥有:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int **make_2d_arr (int rows, int cols)
    {
        int **last = malloc (sizeof *last * rows);      /* allocate rows number of pointers */
        
        if (!last) {                                    /* validate EVERY allocation */
            perror ("malloc-last");
            return NULL;
        }
        
        for (int i = 0; i < rows; i++) {                /* loop rows times */
            last[i] = calloc (cols, sizeof *last[i]);   /* allocate/initialize cols int */
            if (!last[i]) {                             /* validate EVERY allocation */
                perror ("calloc-last[i]");
                while (i--)                             /* loop to free prior allocations */
                    free (last[i]);                     /* free each row of int */
                free (last);                            /* free pointers */
                return NULL;
            }
        }
        
        return last;            /* on success return pointer to allocated block of pointers */
    }
    
    int main (void) {
        
        int *example_arr, **last, rows = 3, cols = 4;   /* declarations */
        
        /* allocate / validate for example_arr */
        if (!(example_arr = malloc (sizeof *example_arr * 3)))
            return 1;
        
        /* call make_2d_arr / validate return */
        if (!(last = make_2d_arr (rows, cols)))
            return 1;
        
        for (int i = 0; i < rows; i++)                      /* loop adding your 3 values */
            example_arr[i] = (i + 1) * 11;
        
        /* you cannot overwrite pointers, you must copy (or loop and assign each) */
        memcpy (last[1], example_arr, rows * sizeof *example_arr);
        
        for (int i = 0; i < rows; i++) {                    /* loop rows */
            for (int j = 0; j < cols; j++)                  /* loop cols */
                printf (j ? ", %2d" : "%2d", last[i][j]);   /* output results */
            putchar ('\n');                                 /* separate with newline */
            free (last[i]);                                 /* free ints when done */
        }
        free (last);            /* free pointers at end */
    }
    

    使用/输出示例

    $ ./bin/example_arr_last
     0,  0,  0,  0
    11, 22, 33,  0
     0,  0,  0,  0
    

    内存使用/错误检查

    在您编写的任何动态分配内存的代码中,对于分配的任何内存块,您都有 2 个职责:(1)始终保留指向起始地址的指针内存块,因此,(2) 当不再需要它时可以释放

    您必须使用内存错误检查程序来确保您不会尝试访问内存或写入超出/超出分配块的边界,尝试读取或基于未初始化的值进行条件跳转,最后, 以确认您已释放所有已分配的内存。

    对于 Linux,valgrind 是正常的选择。每个平台都有类似的内存检查器。它们都易于使用,只需通过它运行您的程序即可。

    $ valgrind ./bin/example_arr_last
    ==15454== Memcheck, a memory error detector
    ==15454== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==15454== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
    ==15454== Command: ./bin/example_arr_last
    ==15454==
     0,  0,  0,  0
    11, 22, 33,  0
     0,  0,  0,  0
    ==15454==
    ==15454== HEAP SUMMARY:
    ==15454==     in use at exit: 0 bytes in 0 blocks
    ==15454==   total heap usage: 6 allocs, 6 frees, 1,108 bytes allocated
    ==15454==
    ==15454== All heap blocks were freed -- no leaks are possible
    ==15454==
    ==15454== For counts of detected and suppressed errors, rerun with: -v
    ==15454== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
    

    始终确认您已释放已分配的所有内存并且没有内存错误。

    查看一下,如果您还有其他问题,请告诉我。

    【讨论】:

      【解决方案2】:

      分段错误是由于错误的函数签名。你应该改变

      int make_2d_arr(int x, int y)
      

      int** make_2d_arr(int x, int y)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-18
        • 1970-01-01
        • 2023-02-19
        • 2013-01-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多