通过指针打印二维数组



我的老师给了我一个问题来解决: -

1)用户将输入"n"个三角形。

2)输入"n"后,用户将输入三角形的边。

3)我们基本上必须打印这些面(基本上是2-D的问题) 数组)。

这是我对问题的实现:-

# include <stdio.h>
# include <stdlib.h>
# include <stdbool.h>
int main(void)
{
int number_of_triangles; // Takes the value of number of triangles the user will input.
scanf("%d", &number_of_triangles);
int *array;
array = malloc(number_of_triangles * 3 * sizeof(int)); 
//trying to create a 2D array whose column size is fixed i.e. 3.

int i,j; // Counter variables.
for(i = 0; i < number_of_triangles; i++)
{
for(j = 0; j < 3; j++)
{
scanf("%d", ((array + i) + j)); // Scanning value of sides of triangle.
}
}
for(i = 0; i < number_of_triangles; i++)
{
for(j = 0; j < 3; j++)
{
printf("%d ", (*(array + i) + j));//printing those sides. <-This is the problem statement.
}
printf("n");
}
return 0;
}

代码工作正常,但我对下面给出的这一行有疑问:-

for(i = 0; i < number_of_triangles; i++)
{
for(j = 0; j < 3; j++)
{
printf("%d ", (*(array + i) + j));
//printing those sides. <-This is the problem statement.
}
printf("n");
}

难道不应该printf("%d ", *(*(array + i) + j))而不是printf("%d ", (*(array + i) + j))来获取三角形边的值吗?

如果我放printf("%d ", *(*(array + i) + j)),那么我得到错误:-

间接寻址需要指针操作数("int"无效)。

我在 C 语言中学到的是,为了取消引用二维数组指针,我们必须使用前一种方法,而不是我在代码中使用的后一种方法。我哪里出错了?

不能取消引用两次。您正在处理一个 1D 数组,您将其用作 2D 数组。

array + i具有类型int *,因此*(array + i)具有类型int,您无法再次取消引用。

相反,您希望使用ij来获取正确的索引。您想要的索引是i * 3 + j

*(array + i * 3 + j)

然而,使用[]表示法要漂亮得多,这是等效的:

array[i * 3 + j]

当您具有通过指向数组的指针数组构造的 2D 数组时,或者当使用的类型是多维数组时,可以使用*(*(array + i) + j))

例如:

int **array;
array = malloc(number_of_triangles * sizeof(int *)); 
for (int i = 0; i < number_of_triangles; ++i)
array[i] = malloc(3 * sizeof(int));
for (int i = 0; i < number_of_triangles; ++i)
for (int j = 0; j < 3; ++j)
printf("array[%d][%d]: %dn", i, j, *(*(array + i) + j)));

(我省略了分配成功的所有检查。如果使用此代码,则必须包含这些代码。

请注意,示例的最后一行非常丑陋。*(*(array + i) + j))相当于array[i][j]。因此可以重写:

printf("array[%d][%d]: %dn", i, j, array[i][j]);

双重取消引用的另一个用途是多维数组类型。

例如,如果您提前知道三角形的数量:

int array[5][3];
for (int i = 0; i < 5; ++i)
for (int j = 0; j < 3; ++j)
printf("array[%d][%d]: %dn", i, j, *(*(array + i) + j)));

在这种情况下,我们利用了数组标识符衰减到指向其第一个元素的指针这一事实。array + i是指向第i个三角形的指针,因此*(array + i)是指向三角形i的数组int3 的int *类型的左值。

*(array + i) + j是一个指向三角形ijint *,所以*(*(array + i) + j))是该元素的int类型的左值。

同样,使用数组表示法更漂亮,用array[i][j]替换*(*(array + i) + j))

对于初学者,您没有分配二维数组。您分配了一个包含3 * number_of_triangles个元素的一维数组。

程序无效,因为在此循环中

for(i = 0; i < number_of_triangles; i++)
{
for(j = 0; j < 3; j++)
{
scanf("%d", ((array + i) + j)); // Scanning value of sides of triangle.
}
}

您正在覆盖已输入的值。

此表达式

((array + i) + j)

等效于表达式

array + ( i + j)

所以array + ( 0 + 1 )等于array + ( 1 + 0 )也就是说,如果使用索引,那么这两个表达式都等效于&array[1]

如果您的编译器支持可变长度数组,则程序可能如下所示

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int number_of_triangles; // Takes the value of number of triangles the user will input.
scanf("%d", &number_of_triangles);
int ( *array )[3] = malloc( sizeof( int[number_of_triangles][3] ) );
for ( int ( *p )[3] = array; p != array + number_of_triangles; ++p )
{
for( int *q = *p; q != *p + 3; ++q )
{
scanf( "%d",  q ); // Scanning value of sides of triangle.
}
}

for ( int ( *p )[3] = array; p != array + number_of_triangles; ++p )
{
for( int *q = *p; q != *p + 3; ++q )
{
printf( "%d ", *q );
}
putchar( 'n' );
}
free( array );
return 0;
}

你可以循环也可以像

for ( int i = 0; i < number_of_triangles; i++ )
{
for( int j = 0; j < 3; j++ )
{
scanf( "%d",  *( array + i ) + j ); // Scanning value of sides of triangle.
}
}

for ( int i = 0; i < number_of_triangles; i++ )
{
for( int j = 0; j < 3; j++ )
{
printf( "%d ", *( *( array + i ) + j ) );
}
putchar( 'n' );
}

否则,您必须将一维指针数组分配给一维整数数组。

最新更新