指向带有函数的二维数组的指针

3

我对指针如何与二维数组配合工作感到有些困惑。即使错误消息也没有帮助我。我有一个需要指针来操作的2D数组,以便我可以在函数内部进行操作(我认为这是您应该这样做的方式)。请问有人可以指出我的错误并将我引导到正确的方向吗?

以下是我的代码:

#include <stdio.h>
#include <time.h>

void init(char *array);

int main(int argc, char *argv[]) {
  char grid[21][80];
  char (*grid_ptr)[80];
  grid_ptr = grid;
  int i, j;
  init(*grid_ptr);

  for (i=0; i<21; i++) {
    for (j=0; j<80; j++) {
      printf("%c", grid_ptr[i][j]);
    }
    printf("\n");
  }

  return 0;
}

void init(char *array) {
  int i,j;
  for (i=0; i<21; i++) {
    for (j=0; j<80; j++) {
      *array[i][j] = ' ';
    }
  }
  for (i=0; i<21; i++) {
    *array[i][0] = '|';
    *array[i][79] = '|';
  }
  for (i=0; i<80; i++) {
    *array[0][i] = '-';
    *array[20][i] = '-';
  }
}

错误的类型如下所示:
main.c:27:16: error: subscripted value is not an array, pointer, or vector
      *array[i][j] = ' ';

2
即使错误信息也没有帮助我,但它们可能会帮助我们。你遇到了什么错误? - Tim Biegeleisen
2个回答

4

让我说一下,您正在无端地让生活变得艰难! :) 当一个人想要操纵一个二维数组时,他可以直接对数组进行操作,通过将数组本身传递给函数,就像这样:

#include <stdio.h>
#include <time.h>

void init(int n, int m, char array[n][m]);

int main(int argc, char *argv[]) {
  const int n = 21, m = 80;
  char grid[n][m];
  int i, j;
  init(n, m, grid);

  for (i = 0; i < n; i++) {
    for (j = 0; j < m; j++) {
      printf("%c", grid[i][j]);
    }
    printf("\n");
  }

  return 0;
}

void init(int n, int m, char array[n][m]) {
  int i,j;
  for (i = 0; i < n; i++) {
    for (j = 0; j < m; j++) {
      array[i][j] = ' ';
    }
  }
  for (i = 0; i < n; i++) {
    array[i][0] = '|';
    array[i][m - 1] = '|';
  }
  for (i = 0; i < m; i++) {
    array[0][i] = '-';
    array[n - 1][i] = '-';
  }
}

它会生成这个漂亮的矩形:

C02QT2UBFVH6-lm:~ gsamaras$ gcc -Wall main.c
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out 
--------------------------------------------------------------------------------
|                                                                              |
|                                                                              |
|                                                                              |
|                                                                              |
|                                                                              |
|                                                                              |
|                                                                              |
|                                                                              |
|                                                                              |
|                                                                              |
|                                                                              |
|                                                                              |
|                                                                              |
|                                                                              |
|                                                                              |
|                                                                              |
|                                                                              |
|                                                                              |
|                                                                              |
--------------------------------------------------------------------------------

现在请注意我对你的代码所做的更改:
  1. 我删除了指向数组的指针,因为它是多余的。
  2. 我按照这里所述,将数组本身作为参数传递给函数。
  3. 我声明了两个新的常量变量nm,它们是你的二维数组的维度,n行xm列,而不是到处使用魔术数字(21和80)。*
  4. 我使用这些维度来实现你已经实现的相同逻辑。请注意,我也必须将它们作为函数参数传递。

至于错误,它意味着你没有访问你认为你正在访问的内容!但是让我不在这里扩展此问题,保持简洁 :)


*现在,如果你想改变你的二维数组的维度,你只需要一次性更改n和/或m,而不是到处修改你的代码(这样容易出错)。


1
谢谢!正是我想要的! - Tyler McAnally
干得好,也许值得向 OP 介绍一下语法,允许您将参数 char array[n][m] 指定为 char (*array)[m],这反映了当数组作为参数传递时,第一级间接性转换为指针。(并且还清楚地说明了在函数内部使用 sizeof 的任何尝试都将失败的原因) - David C. Rankin
虽然我同意@DavidC.Rankin,M.M的答案似乎已经涉及到了,而我的回答已经很长了.. :) 谢谢! - gsamaras
@DavidC.Rankin 这种语言有意允许您以这种方式传递数组,以便我们不必担心诸如数组衰减、数组指针和按引用传递等问题。引入一个数组指针只会使代码变得丑陋。 - Lundin

0

如果有人正在使用不支持可选的“变长数组”功能(例如Microsoft编译器)的C编译器,这里有另一种方法:

void init( int rows, char (*array)[80] );

    // ... in main ...
    char grid[21][80];
    init(grid);          // use of grid_ptr is not required
    // ...

void init(int rows, char (*array)[80])
{
    int i,j;
    for (i = 0; i < rows; i++) {
      for (j = 0; j < 80; j++) {
        array[i][j] = ' ';

j 循环中,您可以将 80 替换为 sizeof *array。或者您可以用一个对 memset 的调用来替换整个 j 循环(实际上是两个循环)。

在没有标准编译器的情况下,我认为应该使用带有可变维度的“混淆”二维数组init(int rows, int cols, char* array)或硬编码的“魔数”数组:init(char [21][80])。这似乎是这两种方法的混合体。 - Lundin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接