C中二维数组的“方向”

时间:2009-05-01 19:45:40

标签: c arrays

作为C新手,我对二维数组感到有点困惑。

如果我想表示一个包含3行和5列的矩阵,我想正确的声明是:

char a[3][5];

那么,这是一个由3个字符串组成的3个指针数组还是什么?

为什么每当我尝试循环通过它时,它似乎会读取错误的结果?

int x, y;
for( x=0; x<3; x++ ){
    for( y=0; y<3; y++ ){
        printf( "%c", a[x][y] );
    }
}

是否有以下等效和正确的方法来初始化它?

char a[3][5] = {
               {1,0,0,0,1},
               {1,0,0,0,1},
               {1,0,0,0,1},
               };

char a[3][5] = {1,0,0,0,1,
                1,0,0,0,1,
                1,0,0,0,1};

感谢您最近的解释。


修改

抱歉打字错误,代码未复制。顺便说一句,我继续让他们读起来就像他们以垂直方式阅读,而不是水平阅读。

同样在本教程http://www.cplusplus.com/doc/tutorial/arrays/的示例中,它以一种不向我前进的方式读取数组,因为它似乎适用于5x3,高度宽度,y x,cols 行结构而不是3x5,宽度高度,x y。行 cols one:

#define WIDTH 5
#define HEIGHT 3

int jimmy [HEIGHT][WIDTH];
int n,m;

int main ()
{
  for (n=0;n<HEIGHT;n++)
    for (m=0;m<WIDTH;m++)
    {
      jimmy[n][m]=(n+1)*(m+1);
    }
  return 0;
}

8 个答案:

答案 0 :(得分:4)

只是因为它是什么,不是什么。

char a[3][5];

没有涉及指针。像这样的多维数组是......的数组数组,依此类推。在您的情况下,您有一个包含5个字符的3个数组的数组。使用typedef执行此操作时会更清楚。

typedef char T[5];
T a[3];

无论如何都不涉及任何指针。如果要访问这3个数组的第一个数组,可以这样做:

a[0]; 

它会返回一个char[5]类型的对象。通常,您没有注意到这一点,因为通常您会索引所有维度。因此a[0]返回的数组是下一个索引的下标,例如a[0][1][1]将应用于a[0]返回的数组,正如我们之前发现的那样,类型为char[5]

  

那么,这是一个由3个字符串组成的3个指针数组还是什么?

让我们创建该类型,看看它与上面的不同之处。一旦获得基本声明符,创建它很简单:

  • 创建指针:*D
  • 创建数组:D[N]

D只是一个现有的另一个声明者。现在让我们继续吧。首先你说array of 3 pointers to 5 arrays of chars...。我想你的意思是array of 3 pointers to arrays of 5 chars。首先,创建array of 5,如

D1[5]

现在,让我们用pointer to声明符替换D1:

(*D2)[5]

我们必须插入括号,因为下标运算符[N]比解除引用运算符*绑定得更好,否则它将被读作*(D2[5]),这不是我们想要的。现在我们有pointer to array of 5

现在让我们做array of 3。将D2替换为D3[3]会产生以下结果:

(*D3[3])[5]

太好了,现在我们得到了array of 3 pointer to array of 5。只需将该声明符所附的基类型生成完整的声明:

char (*D3[3])[5];

这当然是一个完全不同的东西:)你可以用它来存储指向你的另一个类型为array of 3 arrays of 5 char的数组的指针。让我们将指向a的第一个子数组的指针存储到D3[0]中。我们之前发现a[0]的类型为char[5]。我们可以将指向该数组的指针存储到D3[0],因为D3是一个指向char[5]的指针数组,真是巧合!

D3[0] = &a[0]; // works!

我希望这个小练习向你展示了指针和数组之间的一些关系。干杯!

答案 1 :(得分:2)

您的结果错误,因为您使用x两次(看起来像复制/粘贴错误)。尝试

int x, y;
for (x = 0; x < 3; x++) {
    for (y = 0; y < 5; y++) {
        printf("%c", a[x][y]); // Emil H says "%d" might be more useful
    }
}

编辑:我不确定该教程有什么令人困惑的。它完全等同于你的代码,除了不打印数组,它将每个元素设置为(row * column)(行和列都是一个,因此是+ 1)。

答案 2 :(得分:2)

我发现您的代码存在一些问题。首先(从上面复制):

int x, y;
for( x=0; x<3; x++ ){
    for( x=0; x<3; x++ ){
        printf( a[x][y] );
    }
}

在您的内部循环中,您似乎想要使用y而不是x,并且您希望y从0..5开始。目前,您正在重复变量x。此外,您的printf()语句有问题。这是一些更正的代码:

int x, y;
for( x=0; x<3; x++ ){
    for( y=0; y<5; y++ ){
        printf("%d\n", a[x][y] );
    }
}

其次,初始化阵列时,您的代码几乎正确。这是更正后的版本:

char a[3][5] = {
               {1,0,0,0,1},
               {1,0,0,0,1},
               {1,0,0,0,1}
               };

(我在最后一行数据后删除了, - 这是语法错误。)

您发布的第二种语法不正确(没有花括号的语法)。

答案 3 :(得分:1)

int x, y;
for( x=0; x<3; x++ ){
    for( x=0; x<3; x++ ){
        printf( a[x][y] );
    }
}

您需要更改第二个for循环以引用“y”而不是“x”。

希望有所帮助。

答案 4 :(得分:1)

教程中的图像是数据的绝佳表示: alt text http://www.cplusplus.com/doc/tutorial/arrays/bidimensional_arrays3.gif

从示例中,嵌套的for循环逐行遍历(左 - >右)数组,并为每列填充一个值。

答案 5 :(得分:1)

当您可能想要“%d”时使用“%c”这样的小错误,这些并不是您真正想要得到的答案我谦虚地想。你说你对数组有点困惑,并且还提到你希望看到指针作为包含数组的数组的数组元素。你

数组数组定义中的最后一个逗号不是语法错误。允许从C99开始。

真正清除事物的是知道数组不是指针。确实,数组名称可以用作常量指针(对第一个元素),并且指针可以像数组一样被索引。但是,这并不意味着数组和指针是相同的。他们不是。

您询问程序中的符号“a”实际上是什么。它是一个数组数组。存储器布局可以像三线部分的长线切割一样可视化,但仍然是连续线。然后以相同的方式将这些中的每一个切成五个部分。寻址一个元素时,必须使用两个索引;首先是你想要的五元素数组,然后是你想要的第五个元素。

内存布局不像行和列网格。内存由一个标量处理,因此它是线性的。指针运算可能是您可以研究的下一步,并查看指针的增量如何工作。

答案 6 :(得分:0)

你以错误的方式使用printf。尝试:

printf("%d", a[x][y]);

我不确定您是否要使用%c或%d。如果要打印该号码,请使用%d。如果要打印实际字符,请使用%c。

答案 7 :(得分:0)

  

char a [3] [5];

     

那么,这是一个由3个指针组成的数组   5个字符阵列还是什么?

是的,就是这样。虽然你也可以把它作为连续的15个字符来操作。

按照惯例,大多数人会认为它代表一个有3行5列的矩阵(我认为),但是数据结构本身并不需要它。您可以轻松地使用它来表示5行和3列。或者3组,每组包含5个元素,但彼此之间没有任何有意义的关系。

用于执行矩阵操作的特定库将具有此约定。