我的老师给我解决了一个问题,其中:-
1)用户将输入“ n”个三角形。
2)输入“ n”后,用户将输入三角形的边。
3)我们基本上必须打印这些面(基本上是二维问题 数组)。
这是我对问题的实现:-
# 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语言中学到的是,为了取消引用二维数组指针,我们必须使用前一种方法,而不是我在代码中使用的后一种方法。我要去哪里错了?
答案 0 :(得分:1)
您不能两次取消引用。您正在处理一维数组,用作二维数组。
array + i
的类型为int *
,因此*(array + i)
的类型为int
,您不能再次取消引用。
相反,您想使用i
和j
来获取正确的索引。您想要的索引是i * 3 + j
:
*(array + i * 3 + j)
然而,使用[]
表示法相当漂亮:
array[i * 3 + j]
*(*(array + i) + j))
可以用于具有通过指向数组的指针的数组构成的2D数组,或者使用的类型是多维数组时。
例如:
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]: %d\n", i, j, *(*(array + i) + j)));
(我省去了分配成功的所有检查。如果正在使用此代码,则必须包括这些检查。)
请注意,示例的最后一行非常难看。 *(*(array + i) + j))
等同于array[i][j]
。因此可以将其重写:
printf("array[%d][%d]: %d\n", 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]: %d\n", i, j, *(*(array + i) + j)));
在这种情况下,我们利用了数组标识符衰减到指向其第一个元素的指针这一事实。 array + i
是第i
个三角形的指针,因此*(array + i)
是类型int *
的左值,指向三角形{{的int
的数组3 1}}。
i
是指向三角形*(array + i) + j
的边int *
的{{1}},因此j
是i
类型的左值元素。
同样,使用数组表示法更漂亮,将*(*(array + i) + j))
替换为int
。
答案 1 :(得分:0)
对于初学者,您没有分配二维数组。您为一维数组分配了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' );
}
否则,您必须将一维指针数组分配给一维整数数组。