简体   繁体   English

使用realloc调整C中2D数组的大小

[英]Using realloc to resize a 2D array in C

Assignment: we have a canvas which the user can "paint" on - they can draw lines, add or delete rows/columns, etc. One of the commands we have to implement is resizing the canvas. 分配:我们有一个画布,用户可以在其上“绘画”-他们可以画线,添加或删除行/列等。我们要实现的命令之一是调整画布的大小。 Per the assignment specs, new rows are added to the top of the canvas, and new columns on the right. 根据分配规范,新行将添加到画布的顶部,新列将添加到右侧。 These new rows/columns are filled with blank spaces, which are denoted by '*'. 这些新的行/列填充有空白,用'*'表示。 The user inputs r numRows numCols . 用户输入r numRows numCols

The part where I'm struggling is using realloc. 我苦苦挣扎的部分是使用realloc。 If I have a 5x5 canvas to start with, and the user decides to resize to be 7x5, how would I do that? 如果我有一个5x5的画布开始,并且用户决定将尺寸调整为7x5,我该怎么做? Where does realloc put the new rows/columns, and does it automatically shift the existing rows downwards? 重新分配将新行/列放在何处,并且是否自动将现有行向下移动? I have a function implementResize that is called when the user inputs ar: 我有一个函数ImplementResize,当用户输入ar时会调用该函数:

void implementResize(BoardState* boardState, int newRows, int newCols) {
  if (newRows > boardState->board.numRows) {
    printf("add rows\n");
    addRow(boardState, newRows);
  }
  else if (newCols < boardState->board.numRows) {
    printf("delete rows\n");
    //deleteRow();
  }
  else {
    printf("same\n");
    boardState->board.numRows = newRows;
  }
  if (newCols > boardState->board.numCols) {
    printf("add columns\n");
    //addCol();
  }
  else if (newCols < boardState->board.numCols) {
    printf("delete columns\n");
    //deleteCol();
  }
  else {
    printf("same\n");
    boardState->board.numCols = newCols;
  }
}

Right now I'm focusing on how to add rows to the top of the canvas. 现在,我专注于如何在画布顶部添加行。 My code for the function addRow right now is: 我现在的功能addRow的代码是:

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

I'm trying to figure out how to realloc space for the rows. 我试图弄清楚如何为行重新分配空间。 I know I need to use a nested for loop based on the number of newRows and the number of columns, but I'm not sure where these new rows go. 我知道我需要根据newRows的数量和列的数量使用嵌套的for循环,但是我不确定这些新行的位置。 If anyone could clear my confusion up I would appreciate it. 如果有人能消除我的困惑,我将不胜感激。

This code cannot be directly put into your program because it does not use addColumn or addRow . 此代码不能直接放入您的程序,因为它不使用addColumnaddRow This instead gives you an idea how you could approach the problem. 相反,这使您有了一个解决问题的思路。

Comments have been added at lines where there is a catch. 在有问题的地方添加了注释。 There are also some suggestions. 也有一些建议。

    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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM