2017-10-09 99 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 
}