请,我是C编程的新手,请帮助我。以下代码中有一些错误? 基本上,我们如何处理指向二维数组的指针......
#include<stdio.h>
#include<stdlib.h>
int* max5(int** p,int r,int c)
{
/* have to design a function which takes as argument pointer to a 2-D array and returns a pointer to an array which contains the 5 highest entries*/
}
int main()
{
int rows,coloumns;
printf("Enter the number of rows and coloumns separated by a space\n");
scanf("%d %d",&rows,&coloumns);
int **ptr;
ptr=(int**)malloc(sizeof(int*)*rows);
int i,j;
for(i=0;i<rows;i++)
{
for(j=0;j<coloumns;j++)
{
scanf("%d",*(ptr+i)+j);
printf("%d\n",*(*(ptr+i)+j));
}
}
free(ptr);
return 0;
}
答案 0 :(得分:1)
在C中,2D数组只是具有不同索引的常规数组。所以,你有两个选择:
array[I*n+j]
您可以按相关帖子中显示的方式实现第二个:allocate matrix in C。
答案 1 :(得分:1)
动态分配2D阵列可以通过多种方式完成。
假设你有一个支持可变长度数组的C99编译器或C2011编译器,这很容易:
int rows, columns;
...
scanf("%d %d",&rows,&columns);
int array[rows][columns];
array
是一个可变长度数组(VLA),意味着它的维度是在运行时建立的。要将其传递给另一个函数,原型就是
int *max5( int rows, int columns, int arr[rows][columns] ) { ... }
也可以写成
int *max5( int rows, int columns, int (*arr)[columns] ) { ... }
我将进入下面的第二个表格。请注意,在VLA声明中使用它们之前,必须声明rows
和columns
。
您可以将其称为
int *maxarr = max5( rows, columns, array );
这种方法的优点是:a)它很容易,并且b)array
的内存被连续分配(即,作为单个连续的内存块),并在您退出它的封闭后立即释放范围;没有必要手动free
它。这种方法的缺点是rows
和columns
不能任意大,你不能使用常规初始化语法初始化数组(即你不能写int array[rows][columns] = { ... };
),你不能在文件范围定义VLA(即作为全局变量)。还有一个问题是VLA支持总是有点不稳定,2011标准现在使它们成为可选项,所以不能保证它们在任何地方都会得到支持。
如果rows
或columns
非常大,或者由于某些其他原因你想从堆中分配这个内存,那只会稍微复杂一些:
int rows, columns;
...
scanf("%d %d", rows, columns);
int (*array)[columns] = malloc( sizeof *array * rows );
在此版本中,array
是一个指针,指向int
的N元素数组(其中N == columns
),我们{{ 1}}空间来容纳M个这样的数组(其中M == malloc
)。同样,这利用了VLA语法,但是我们不是从堆栈帧分配内存,而是从堆中分配它。与第一种方法一样,内存是连续分配的。你可以像任何其他数组一样索引它:
rows
完成数组后,您可以将其释放为
array[i][j] = x;
free( array );
的原型将是
max5
看起来很熟悉?这是我们之前通过2D VLA时使用的第二个版本。
除非它是int *max5( int rows, int columns, int (*arr)[columns] ) { ... }
或一元sizeof
运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,否则表达式为“N-element array of &
“将转换为”指向T
的指针“的表达式,表达式的值将是数组中第一个元素的地址。
在我们将T
声明为2D VLA的第一种情况下,当您致电
array
表达式int *maxarr = max5( rows, columns, array );
从类型“array
- rows
的元素数组 - columns
的元素数组”转换为“指向int
的指针 - 元素数组columns
“,所以int
接收的是指针值,而不是数组。恰好在函数参数声明的上下文中,max5
和T a[N]
都被解释为T a[]
; IOW,这三个都声明T *a
作为指向a
的指针。
因此,两者
T
和
int *max5( int rows, int columns, int arr[rows][columns] ) { ... }
将int *max5( int rows, int columns, int (*arr)[columns] ) { ... }
声明为指向数组的指针,而不是2D数组。同样,两者都返回一个简单的arr
,而不是int *
的数组。这样做的原因是简单的;如果你使用
int
表达式return arr[i];
的类型为“arr[i]
- 元素数组columns
”;根据上述规则,该表达式将转换为int
类型。 C不允许您将数组对象作为数组返回,数组表达式也不能作为赋值的目标。
现在,如果您使用的是C89编译器或不支持VLA的C2011编译器,该怎么办?在这种情况下,您需要以零散的方式分配内存,如下所示:
int *
您的int rows, columns;
int **array;
...
scanf("%d %d", rows, columns);
array = malloc( sizeof *array * rows );
if ( array )
{
int i;
for ( i = 0; i < rows; i++ )
{
array[i] = malloc( sizeof *array[i] * columns );
}
}
原型现在
max5
你不再处理数组或指向数组的指针了;你正在处理一个双指针,这与指向二维数组的指针不同。您仍然可以将其下标,就好像它是一个2D数组
int *max5( int rows, int columns, int **arr );
但不是一个数组对象本身。
最重要的是要确保内存不是连续的;行可能在内存中不相邻,因此不想要尝试使用指针向下走行,如下所示:
arr[i][j] = x;
对于分段分配的数组,这种算法不起作用。
此外,由于内存是零散分配的,因此需要逐个释放:
int (*p)[columns] = arr;
while ( some_condition )
p++; // sets p to point to the next row
希望有所帮助。
答案 2 :(得分:0)
此代码可以解决您的问题:
#include<stdio.h>
#include<stdlib.h>
int* max5(int** p,int r,int c)
{
/* have to design a function which takes as argument pointer to a 2-D array and returns a pointer to an array which contains the 5 highest entries*/
}
int main()
{
int rows,coloumns;
printf("Enter the number of rows and coloumns separated by a space\n");
scanf("%d %d",&rows,&coloumns);
int **ptr;
int i,j;
ptr=(int**)malloc(sizeof(int*)*rows);
for(j=0;j<coloumns;j++)
{
*(ptr+j) = (int *)malloc(sizeof(int)*coloumns);
}
for(i=0;i<rows;i++)
{
for(j=0;j<coloumns;j++)
{
scanf("%d",*(ptr+i)+j);
//*(*(ptr+j)+i) = i+j;
printf("%d\n",*(*(ptr+i)+j));
}
}
free(ptr);
return 0;
}
实际上你忘记为列分配内存了!
答案 3 :(得分:-1)
您可以通过正确定义类型在C中分配2D数组:
int (*ptr)[coloumns] = calloc(sizeof(int) , rows * coloumns);
然后您可以通过ptr[i][j]
解决此问题。如果你的数组确实需要超出分配它的范围并且相当小,那么你也可以在堆栈上分配它
int ptr[rows][coloumns];
memset(ptr, 0, sizeof(ptr));
您尝试分配的是指针数组int (*)[coloumns]
与int **
的类型不同,尽管它们都可以通过使用索引运算符[i][j]
来解决。后者是一个复杂得多的数据结构,容易出现更多错误。除非你需要可变的行大小,否则我会反对它。