Динамический 2 массив в C - PullRequest
0 голосов
/ 19 мая 2018

Я изучаю C и пытаюсь использовать виртуальную сетку, в которой пользователь может помещать новые элементы сетки для «активации» в консоль.Так, например, если я начинаю с нуля, а пользователь добавляет (40,50), то размер составляет не менее 40x50 с инициализированным элементом (40,50).Если следует (20,30), он просто активирует элемент на 20,30.Но если пользователь затем введет (500 300), он выделит еще немного памяти и увеличит размер массива.Я хотел бы получить к ним доступ легко.Я хотел бы работать (я мог бы в любом случае), потому что они являются новыми для меня.Мой код (на данный момент) следующий:

int width = 4, height = 5;
bool **arr = (bool **) malloc(height * sizeof(bool *));
for (int x = 0; x < height; x++) {
    arr[x] = (bool *) malloc(width * sizeof(bool));
}

for (int x = 0; x < height; x++) {
    for (int y = 0; y < width; y++) {
        *(*(arr + x) + y) = false;
    }
}

*(*(arr + 3) + 2) = true;

// user puts a value bigger than (4,5) inside
int newX=10, newY = 10;

//allocate more memory

Так что я использую 2D-указатель с логическими значениями, и я сначала делаю "malloc" высоту, а затем создаю их массив для ширины.

В последней строке приведен пример ввода первого элемента в (2,3).Метод сканирования для пользователя здесь не имеет значения.

Так есть ли способ увеличить размер моего массива впоследствии или мне нужна совершенно другая концепция для него?

===== Текущий код:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

int main() {
    int width = 4, height = 5;
    bool **arr = (bool **) malloc(height * sizeof(bool *));

    for (int x = 0; x < height; x++) {
        arr[x] = (bool *) malloc(width * sizeof(bool));
    }

    for (int x = 0; x < height; x++) {
        for (int y = 0; y < width; y++) {
            *(*(arr + x) + y) = false;
        }
    }

    *(*(arr + 3) + 2) = true;

    int newWidth = 10, newHeight = 10;
    bool **narr = realloc(arr, newHeight * sizeof(bool*));
    if(narr) {
        arr = narr;
        for(size_t i = 0; i < newHeight; i++){
            bool* p = realloc(arr[i] , newWidth * sizeof(bool));
            if( !p ){
                perror("realloc");
            }
            arr[i] = p;
        }
        // here resize the number of elements if needed
    }
    else {
        perror("realloc failed");
        exit(EXIT_FAILURE);
    }

    return 0;
}

Ответы [ 2 ]

0 голосов
/ 19 мая 2018

Вы можете использовать realloc , чтобы увеличить размер массива

, в вашей ситуации вы бы сделали

arr = (bool **)realloc(arr, sizeof(bool*) * new_height)
for(int i = 0; i < new_height; i++){
    arr[i] = (bool *)realloc(arr, sizeof(bool) * new_width);
}

Обратите внимание, что вы должны проверить,массив должен стать еще больше, realloc также может «сжать» ваш массив, поэтому действуйте осторожно.

Инициализация вновь созданной памяти в false:

for(int i = old_height; i < new_height; i++){
    for(int j = old_width; j < new_width; j++){
        arr[i][j] = false;
    }
}
arr[new_height - 1][new_width - 1] = true;
0 голосов
/ 19 мая 2018

Да, есть метод, называемый realloc.И вы можете использовать это.Вы можете полностью изменить размер зубчатого массива.

bool **narr = realloc(arr , newsize * sizeof(bool*));
if( narr ) {
  arr = narr;
  for(size_t i = 0; i < newsize; i++){
     bool* p = realloc(arr[i] , newsize1 * sizeof(bool));
     if( !p ){
        perror("realloc");
     }
     arr[i] = p;
  }
  // here resize the number of elements if needed
}
else {
    perror("realloc failed");
    exit(EXIT_FAILURE);
}

Также упростите запись a[1][2] вместо *(*(a+1)+2).Проверка необходима, так как realloc может завершиться неудачей - в этом случае вместо того, чтобы ваш код работал неправильно, при необходимости выполните соответствующий шаг.

Также обратите внимание, что вам нужно установить для всех вновь выделенных bool* значение NULL.Так что сделайте это: -

    for(size_t i = 0; i < newHeight; i++){
        if( i >= height)
           arr[i] = NULL;
        bool* p = realloc(arr[i] , newWidth * sizeof(bool));
        if( !p ){
            perror("realloc");
        }
        arr[i] = p;
    }

Это необходимо, потому что realloc ожидает адрес памяти, ранее выделенный с помощью *alloc функций или NULL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...