我的老师给了我一个问题来解决: -
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
,您无法再次取消引用。
相反,您希望使用i
和j
来获取正确的索引。您想要的索引是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
的数组int
3 的int *
类型的左值。
*(array + i) + j
是一个指向三角形i
边j
的int *
,所以*(*(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' );
}
否则,您必须将一维指针数组分配给一维整数数组。