检查动态分配的二维数组中的相邻单元格

时间:2021-02-07 22:41:32

标签: c allocation

我正在处理一个项目,在该项目中我需要检查动态分配的 2D char 数组中特定单元格的相邻单元格。基本上,例如,如果某些相邻单元格是 'X',则您所在的当前单元格变为 '-'。为了分配二维数组,我使用了一个 malloc 调用:

char *array = (char *)malloc(numRows * numCols * sizeof(char));

要在使用 double for 循环时访问元素,我使用:

for (int i = 0; i <= getNumRows(); i++)
{
    for (int j = 0; j < getNumCols(); j++)
    {
        printf("%c ", **(array + i * getNumCols() + j));
    }
    printf("\n");
}

如何访问和查看当前元素的相邻单元格?

2 个答案:

答案 0 :(得分:2)

贴出显示矩阵的代码有问题:

  • 外循环应该在 i == getNumRows()
  • printf 参数应使用单个 * 解引用运算符

这是修改后的版本:

for (int i = 0; i < getNumRows(); i++) {
    for (int j = 0; j < getNumCols(); j++) {
        printf("%c ", *(array + i * getNumCols() + j));
    }
    printf("\n");
}

也可以重写以避免重复重新计算矩阵大小:

for (int i = 0, row = getNumRows(), cols = getNumCols(); i < rows; i++) {
    for (int j = 0; j < cols; j++) {
        printf("%c ", array[i * cols + j]);
    }
    printf("\n");
}

访问单元格 r,c 的相邻单元格取决于您如何处理边界:

  • 如果不应跨越边界,则必须测试 r 和/或 c 是否在边界上以产生 3 到 8 个邻居。
  • 如果边界包裹为圆环,您只需计算 r+/-1 % rowsc+/-1 % cols 以始终生成 8 个邻居。

为了简化第一种情况,您可以使用 char *array = malloc(sizeof(char) * (numRows + 1) * (numCols + 2)); 分配具有 2 个额外列和行的矩阵,并以这种方式使用内部空间(活动区域):

for (int i = 1; i <= getNumRows(); i++) {
    for (int j = 1; j <= getNumCols(); j++) {
        printf("%c ", *(array + i * getNumCols() + j));
    }
    printf("\n");
}

如果将矩阵中的边界行和列初始化为 ' ',则始终可以访问 r+/-1, c+/-1 处的 8 个单元格并检查 'X',而无需对边界行进行特殊大小写活动部分。

可以根据实现选择来访问这些相邻小区:

 int rows = getNumRows(), cols = getNumCols();
 char *cellp = array + r * cols + c;

 // using extra rows and columns
 char top_1 = cellp[-cols - 1];
 char top_2 = cellp[-cols];
 char top_3 = cellp[-cols + 1];
 char mid_1 = cellp[-1];
 char mid_2 = cellp[+1];
 char bot_1 = cellp[+cols - 1];
 char bot_2 = cellp[+cols];
 char bot_3 = cellp[+cols + 1];

 // using torus-like wrapping
 char top_1 = array[(r + rows - 1) % rows * cols + (c + cols - 1) % cols];
 char top_2 = array[(r + rows - 1) % rows * cols + c];
 char top_3 = array[(r + rows - 1) % rows * cols + (c + 1) % cols];
 char mid_1 = array[r * cols + (c + cols - 1) % cols];
 char mid_2 = array[r * cols + (c + 1)];
 char bot_1 = array[(r + 1) % rows * cols + (c + cols - 1) % cols];
 char bot_2 = array[(r + 1) % rows * cols + c];
 char bot_3 = array[(r + 1) % rows * cols + (c + 1) % cols];

 // using tests
 char top_1 = (r == 0        || c == 0       ) ? 0 : cellp[-cols - 1];
 char top_2 = (r == 0                        ) ? 0 : cellp[-cols];
 char top_3 = (r == 0        || c == cols - 1) ? 0 : cellp[-cols + 1];
 char mid_1 = (                 c == 0       ) ? 0 : cellp[-1];
 char mid_2 = (                 c == cols - 1) ? 0 : cellp[+1];
 char bot_1 = (r == rows - 1 || c == 0       ) ? 0 : cellp[+cols - 1];
 char bot_2 = (r == rows - 1                 ) ? 0 : cellp[+cols];
 char bot_3 = (r == rows - 1 || c == cols - 1) ? 0 : cellp[+cols + 1];

答案 1 :(得分:1)

我会使用指向数组的指针。它使数组索引更容易。示例打印相邻单元格。

void print_n(void *arr, size_t nrows, size_t ncols, size_t col, size_t row)
{
    int (*array)[nrows][ncols] = arr;

    if(col) printf("Left: %d\n", (*array)[row][col - 1]);
    if(col < ncols - 1) printf("Right: %d\n", (*array)[row][col + 1]);
    if(row) printf("Top: %d\n", (*array)[row - 1][col]);
    if(row < nrows - 1) printf("Right: %d\n", (*array)[row + 1][col]);
}

int main(void)
{
    size_t ncols = 10, nrows = 20;
    int (*array)[nrows][ncols] = malloc(sizeof(*array));

    for(size_t row = 0; row < nrows; row++)
        for(size_t col = 0; col < ncols; col++)
            (*array)[row][col] = row * 100 + col;
    print_n(array, nrows, ncols, 6, 7);
    free(array);
}

https://godbolt.org/z/7Yoff5