2017-10-09 125 views
-5

我有一个动态的二维数组,大小是高度*宽度。更改二维动态数组(c中的realloc)

我想通过使用realloc更改数组大小。

这是我的代码,但它不工作。

我该怎么办?帮我!!

int main(){ 
     char **img; 
     img = (char**)malloc(sizeof(char*)*height); 

     for(i=0;i<height;i++){ 
     img[i] = (char*) malloc(sizeof(char)*width); 
     } 

     resize(height*2, width*2, img); 
} 

void resize(int height, int width, char **img){ 
     int i; 
     img = (char**)realloc(img, sizeof(char)*height); 
     for(i=0;i<h;i++){ 
     img[i] = (char*)realloc(img[i], width); 
     } 

} 
+0

首先,我建议你做的一些研究*由C基准模拟通*。要继续,重新分配后'img'的* new *元素会是什么?提示:它们*未初始化*,不能按原样传递给'realloc'。最后,在'realloc'失败的情况下,您不应该回传给您传递给'realloc'的指针。 –

+0

这是**不是** 2d数组。逻辑是有缺陷的,首先是free()独立数组,不再需要(如果有的话),然后调整指针数组的大小,然后分配新需要的单个数组并调整之前的大小。当然,检查每个**'malloc()'/'realloc()'调用的错误。最后,修改局部变量会修改**副本**,您必须完成后返回'img'。 –

+3

一般而言,“*但它不工作。*”是**不是**适合的问题描述。 –

回答

0

除此之外,您还

  • 不与二维阵列和
  • 和代码泄漏内存处理,如果新的高度较小,则旧的高度和
  • 你不需要在C中铸造void -pointers和
  • 全部int s应该是size_t s

主要有两个错误在这里,因为代码

  • 传递错误的大小重新分配外阵列。它将height乘以sizeof (char)而不是sizeof (char*)
  • 错过了在通过内部调整大小循环将它们传递到realloc()之前,初始化附加指针reallocNULL编辑到“外部”数组。

所以假设新的高度最低限度的调整是大于或等于旧的高度可能看起来像

void resize(size_t height, size_t height_current, size_t width, char **img){ 
    int i; 
    img = (char**)realloc(img, sizeof(char*)*height); 
    for(i=height_current;i<height;i++){ 
    img[i] = NULL; 
    } 
    for(i=0;i<width;i++){ // correct copypasta mistake here 
    img[i] = (char*)realloc(img[i], width); 
    } 
} 

一个更好的版本可能看起来像这样

void resize(size_t height, size_t height_current, size_t width, size_t char **img) 
{ 
    if (height != height_current) 
    { 
    if (height < height_current) 
    { 
     for (size_t i = height; i < height_current; ++i) 
     { 
     free(img[i]); 
     } 
    } 

    img = realloc(img, height * sizeof *img); 

    if (height > height_current) 
    { 
     for (size_t i = height_current; i < height; ++i) 
     { 
     img[i] = NULL; 
     } 
    } 
    } 

    for (size_t i = 0; i < width; ++i) 
    { 
    img[i] = realloc(img[i], width * sizeof *img[i]); 
    } 
} 

这样称呼它:

resize(height*2, height, width*2, img); 

还你真的想要添加错误检查到malloc()realloc()的所有调用,因为它们可能会失败!

+0

“最小调整”不能解决改变'img'指针的问题;并在第二个版本中混合宽度和高度。 –

+0

@StephanLechner:通过添加注释和代码来修复。 Sry基因。 – alk

+0

'for(i = width_current; i

0

有两个主要问题。首先,realloc可能会移动内存块到一个新的位置。因此,如果不需要移动,realloc的返回值将指向“旧”内存块,如果需要移动,则返回新块;如果发生错误,则返回NULL。然而,你忽略resize这个事实,因为它不能改变调用者传入的指针对象。我建议适应原型,使resize返回一个(可能是新的)指针,就像realloc一样。

其次,在重新分配每行时,数组中可能存在未初始化的值,可能指向“某处”。重新分配这样一个未初始化的值是未定义的行为。我建议将“新”行设置为NULL,这样realloc可以在事后正确行事。因此,有必要知道“旧”高度,因为否则无法区分经常初始化的指针和“垃圾”指针。

查看改编的代码。希望能帮助到你。

char** resize(int oldHeight, int oldWidth, int height, int width, char **img){ 
    int i; 
    img = realloc(img, sizeof(char)*height); 
    for (int i=oldHeight; i<height; i++) 
     img[i] = NULL; 

    for(i=0;i<height;i++){ 
     img[i] = realloc(img[i], width); 
     for (int col=oldWidth; col < width; col++) { 
      img[i][col] = 0; 
     } 
    } 

    return img; 
} 

int main(){ 
    int height = 10; 
    int width = 20; 

    char **img; 
    img = malloc(sizeof(char*)*height); 

    for(int i=0;i<height;i++){ 
     img[i] = malloc(sizeof(char)*width); 
    } 

    img = resize(height, width, height*2, width*2, img); 
} 
0

为了正确地做到这一点,你必须知道至少调整前的行数。一种可能性是定义一个struct包含附加信息(种类OOP方法的,具有所有相关数据一起),如下面的例子(也存储列的数目,只是为了完整性,这里未测试代码):

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

typedef struct Lookup Lookup; 

struct Lookup 
{ 
    size_t rows; 
    size_t cols; 
    char **data; 
}; 

static void Lookup_destroy(Lookup *self) 
{ 
    if (!self) return; 
    for (size_t r = 0; r < self->rows; ++r) 
    { 
     free(self->data[r]); 
    } 
    free(self->data); 
    free(self); 
} 

static Lookup *Lookup_create(size_t rows, size_t cols) 
{ 
    Lookup *self = malloc(sizeof *self); 
    if (!self) return 0; 

    self->rows = rows; 
    self->cols = cols; 
    self->data = malloc(rows * sizeof *(self->data)); 
    if (!self->data) 
    { 
     free(self); 
     return 0; 
    } 
    memset(self->data, 0, rows * sizeof *(self->data)); 
    for (size_t r = 0; r < rows; ++r) 
    { 
     self->data[r] = malloc(cols * sizeof *(self->data[r])); 
     if (!self->data[r]) 
     { 
      Lookup_destroy(self); 
      return 0; 
     } 
    } 

    return self; 
} 

static Lookup *Lookup_resize(Lookup *self, size_t rows, size_t cols) 
{ 
    if (!self) return Lookup_create(rows, cols); 

    // free rows that are no longer needed, if any: 
    for (size_t r = rows; r < self->rows; ++r) 
    { 
     free(self->data[r]); 
     self->data[r] = 0; 
    } 

    // reallocate array of rows: 
    char **newdata = realloc(self->data, rows * sizeof *newdata); 
    if (!newdata) 
    { 
     Lookup_destroy(self); 
     return 0; 
    } 

    // update row array and row count: 
    self->data = newdata; 
    size_t oldrows = self->rows; 
    self->rows = rows; 

    // initialize new rows to NULL, if any: 
    if (rows > oldrows) 
    { 
     memset(self->data + oldrows, 0, 
       (rows - oldrows) * sizeof *(self->data)); 
    } 

    // reallocate individual rows: 
    for (size_t r = 0; r < rows; ++r) 
    { 
     char *newrow = realloc(self->data[r], cols * sizeof *newrow); 
     if (!newrow) 
     { 
      Lookup_destroy(self); 
      return 0; 
     } 
     self->data[r] = newrow; 
    } 

    // update col count: 
    self->cols = cols; 

    return self; 
} 

请注意realloc()的结果如何是总是先存储到一个临时变量,这是正确处理错误所需要的。如果出现任何错误,此代码只会丢弃整个对象 - 您可以使用更多的代码做不同的事情。

你可以用它在你的代码是这样的:

int main(){ 
     Lookup img; 
     img = Lookup_create(height, width); 
     // check for NULL here 

     img = Lookup_resize(img, height*2, width*2); 
     // and check for NULL here 
}