【问题标题】:Checking neighboring cells in a dynamically allocated 2D array检查动态分配的二维数组中的相邻单元格
【发布时间】:2021-05-11 14:26:41
【问题描述】:

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

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

要在使用双 for 循环时访问元素,我使用这个:

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

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

【问题讨论】:

  • 您的程序可能无法编译,+ j* 语法无效。此外,您正在分配一个 char * 并取消引用它两次 (**):这是错误的,您只能取消引用一次。
  • 可能第一个for循环中的条件应该是i &lt; getNumRows()
  • 我试过那个 zois,但它不会打印出数组的最后一行。
  • 旁注: 不要将malloc 的返回值转换成返回值。而且,sizeof(char) 根据定义总是 1,所以使用它是多余的。
  • 您对**(array + i*getNumCols() + j) 的使用不正确(并被编译器标记)。单个* 可能会起作用。但是,更好的解决方法是:array[i * numCols + j]

标签: c allocation


【解决方案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

【讨论】:

  • 如果您要使用 VLA,为什么首先要使用 void * 指针?您可以到处使用 VLA:void print_n( size_t nrows, size_t ncols, int array[nrows][ncols], ...)
【解决方案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];

【讨论】:

  • 只是想为什么不使用指向数组的指针并且没有所有这些算术问题。 (顺便说一句,这不是我的 DV。有趣的是为什么你的答案是 DV)
  • @0___________:我最初的回答没有解决 OP 的问题:如何访问相邻单元格,它只是指出了发布代码中的一些问题。
  • 投反对票是因为原始答案没有回答有关访问相邻单元格的问题。该问题已得到修复,因此反对票已转为赞成票。
猜你喜欢
  • 1970-01-01
  • 2021-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-04
  • 1970-01-01
  • 2014-07-27
  • 2017-07-20
相关资源
最近更新 更多