使用Realloc在C中调整了2D数组的大小



分配:我们有一个用户可以在上面"油漆"的画布 - 他们可以绘制行,添加或删除行/列等。我们必须实现的命令之一是调整大小画布。根据分配规格,将新行添加到画布的顶部,并在右侧添加新列。这些新的行/列充满了空白,这些空间用"*"表示。用户输入r numRows numCols

我挣扎的部分是使用Realloc。如果我有一个5x5帆布,并且用户决定调整大小为7x5,我该怎么办?Realloc将新的行/列放在哪里,并且它会自动向下移动现有行?当用户输入a r:

时,我有一个函数实现的措施。
void implementResize(BoardState* boardState, int newRows, int newCols) {
  if (newRows > boardState->board.numRows) {
    printf("add rowsn");
    addRow(boardState, newRows);
  }
  else if (newCols < boardState->board.numRows) {
    printf("delete rowsn");
    //deleteRow();
  }
  else {
    printf("samen");
    boardState->board.numRows = newRows;
  }
  if (newCols > boardState->board.numCols) {
    printf("add columnsn");
    //addCol();
  }
  else if (newCols < boardState->board.numCols) {
    printf("delete columnsn");
    //deleteCol();
  }
  else {
    printf("samen");
    boardState->board.numCols = newCols;
  }
}

现在,我专注于如何将行添加到画布顶部。我的函数代码现在是:

void addRow(BoardState *boardState, int newRows) {
  boardState->board.numRows = newRows;
  boardState->board.theBoard = (char**) realloc(boardState->board.theBoard, boardState->board.numRows * sizeof(char*));
}

我试图弄清楚如何为行进行真正的空间。我知道我需要根据newRow的数量和列数使用嵌套循环进行循环,但我不确定这些新行的去向。如果有人能清除我的困惑,我会很感激。

无法将此代码直接放入您的程序中,因为它不使用addColumnaddRow。相反,这使您知道如何解决问题。

在有收获的线路上添加了评论。也有一些建议。

    int  resizeBoard(BoardState *boardState, size_t newRows, size_t newCols) {
    //verify before you dereference
    if(boardState == NULL)
        return 0;
    if(boardState->board.theBoard == NULL)
        return 0;
    const size_t oldRows = boardState->board.numRows; //more readbale
    /*
    ** if the number of rows decreased, free the excess
    ** we have to do it now because it becomes inaccessible after realloc of boardState.board.theBoard
    */
    for(int i = newRows; i < oldRows; i++)
        free(boardState->board.theBoard[i]);
    /* set these to the new values so that freeBoard gets the correct data in case of failure */
    boardState->board.numRows = newRows;
    boardState->board.numCols = newCols;
    //it is important to use a different pointer to store the value returned by realloc because if the reallocation fails, realloc will return NULL and we will lose access to the original board
    void *ptr = realloc(boardState->board.theBoard, izeof(char*)*newRows);
    if(ptr == NULL) { 
        //realloc failed
        freeBoard(boardState);
        return 0;
    }
    boardState->board.theBoard = ptr;
    //As realloc copies the previous data to the new memory location, theBoard is still pointing to the old rows (from row 0 to row [newRows - 1])
    for(int i = 0; i < min(newRows, oldRows); i++) {
        void *ptr = realloc(boardState->board.theBoard[i], sizeof(char)*newCols);
        if(ptr == NULL) {
            //realloc failed
            freeBoard(boardState);
            return 0;
        }
        boardState->board.theBoard[i] = ptr;
    }
    
    //we cannot use realloc for first time memory allocation; doing so causes undefined behaviour
    //we must separately allocate memory for the new rows
    for(int i = oldRows; i < newRows; i++)
    {
        boardState->board.theBoard[i] = malloc(sizeof(char)*newCols);
        if(boardState->board.theBoard[i] == NULL) {
            //perform cleanup
            return 0;
        }
    }
    return 1;
}

最新更新