我已经查看了其他问题,他们似乎无法回答这个问题。
我有一个例程,我想处理一个可能是一维或二维的整数数组
这样:
int myarray[10];
或
int myarray[10][10];
void myroutine(int *input_array, int num_dimens)
{
int digits;
int limbs;
int i, j;
digits = get_num_digits();
if (num_dimens == 1)
{
for(i=0; i< digits; i++)
myprocess(*(input_array+i));
} else { /* 2 dimensions */
limbs = get_num_limbs();
for(j=0;j<limbs;j++)
for(i=0; i< digits; i++)
myprocess(*(input_array+j*digits+i));
}
}
如何调用 myroutine ?
myroutine(myarray, 1);
myroutine(myarray2, 2);
这似乎不起作用。 新编辑:试图进一步充实这个例子。
答案 0 :(得分:2)
假设你真的想要编写一个伪多态函数来处理不同的数组类型(意思是,不同数量的维度和长度),你需要将一个显式指针传递给第一个要素:
myroutine( &myarray[0], 1 );
myroutine( &myarray2[0][0], 2 );
这样你的第一个输入始终是int *
。
在您的例程中,您将input_array
对象视为一维数组:
// input_array is a 1D array
input_array[i] = something;
// input_array is a 2D array
input_array[ i * d0 + j ] = something;
// input_array is a 3D array
input_array[i * d0 * d1 + j * d1 + k ] = something;
您需要将维度长度作为附加参数传递,例如:
myroutine( &myarray[0], 1, 10 );
myroutine( &myarray2[0][0], 2, 10, 10 );
myroutine( &myarray3[0][0][0], 3, 10, 10, 10 );
你要按如下方式处理:
#include <stdarg.h>
...
void myroutine( int *input_array, int num_dimens, ... ) // ... for additional arguments specifying dimension lengths
{
va_alist ap;
size_t *dims = malloc( num_dimens * sizeof *dims );
va_start( ap, num_dimens );
for ( int i = 0; i < num_dimens; i++ )
{
dims[i] = va_arg( ap, int );
}
va_end( ap );
...
然后,根据维度的数量,您可以以不同方式处理input_array:
switch( num_dimens )
{
case 1:
input_array[i] = value;
break;
case 2:
input_array[i * dims[0] + j] = value;
break;
case 3:
input_array[i * dims[0] * dims[1] * j * dims[1] * k ] = value;
break;
...
}
...
free( dims );
}
当然,你必须弄清楚你是如何循环一维阵列而不是二维阵列与三维阵列等。正如其他人建议的那样,你最好不要创建单独的函数对于每个维度。您可以使用伪多态函数作为它们的包装器,但是您将失去类型安全的好处。
修改强>
指向第一个元素的指针以及数组本身:
int *ptr;
#if 1D
int myarray[10];
ptr = &myarray[0];
#else
int myarray[10][10];
ptr = &myarray[0][0];
#endif
然后打电话给
myroutine( ptr, 1, 10 );
或
myroutine( ptr, 2, 10, 10 );
答案 1 :(得分:1)
写两个单独的函数,每个函数处理一个案例。您希望保持编译器类型检查对您有利。无论如何,案件确实不同。要索引1D数组,需要一个int,对于2D数组,您需要两个整数和有关表宽度的信息。
您还可以将两种方法的重复逻辑提取到一个单独的函数中,但在一切正常工作后执行此操作。
答案 2 :(得分:1)
我强烈建议制作2个函数,这些函数可能会调用普通的worker函数。正确的程序设计总是比使用/滥用或多或少模糊的语言机制更好。
话虽如此,代码将无法编译,因为在2D数组的情况下,您将数组指针传递给期望指向int的指针的函数。如果您坚持这样做,请转换为void*
或使该函数采用void*
参数。
答案 3 :(得分:1)
您的方法不起作用,因为 myarray 会衰减到int[10]
,但 myarray2 会衰变为int(*)[10]
。如果您确实想使用一个函数,则应使用void
指针禁用类型检查:
void myroutine(void *input_array, int num_dimens)
/* ^^^^ */
{
/* stuff here */
}
或者,您可以“作弊”并保留您的签名,但不应拨打myroutine(myarray2, 2)
,而应使用:
myroutine(myarray2[0], 2)
答案 4 :(得分:1)
这是一种处理未知维度的2D数组的方法。它使用可变长度数组(VLA) 1 语法来正确声明指向数组的指针。
void foo( int rows, int cols, int (*array2d)[cols] )
{
int value = 1;
for ( int i = 0; i < rows; i++ )
for ( int j = 0; j < cols; j++ )
array2d[i][j] = value++;
}
int main( void )
{
// declare an array
int myarray[5][10];
// initialize the array
foo( 5, 10, myarray );
// show the array
for ( int row = 0; row < 5; row++ )
{
for ( int col = 0; col < 10; col++ )
printf( "%2d ", myarray[row][col] );
printf( "\n" );
}
}
1 在C99中引入了VLA,但从C11开始,编译器对VLA的支持是可选的。
答案 5 :(得分:1)
[为了便于阅读,我将10改为4并使2D阵列不对称]
int a[4];
是
的元素int b[3][4];
因此,让你的函数知道2D数组,并将指针传递给它的元素以及元素的数量。
void f(int (*)[4], size_t);
并像这样称呼它
f(&a, 1);
或
f(b, 3);
在函数内部访问像这样的元素:
void f(int (*c)[4], size_t s)
{
for (size_t i = 0; i < s; ++i)
{
for (size_t j = 0; j < 4; ++j)
{
printf ("c[%zu][%zu] = %d\n", i, j, c[i][j]);
}
}
}
并称之为:
#include <stdio.h>
void f(int (*)[4], size_t);
int main (void)
{
int a[4] = { 1, 2, 3, 4 };
int b[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
printf("a:\n");
f(&a, 1);
printf("b:\n");
f(b, 3); /* b decays to a pointer to its 1st element. */
}
答案 6 :(得分:0)
制作类似
的结构struct Array1or2 {
int *data;
unsigned DimCount;
// If not always width 10, add unsigned Width;
};
创建
等功能void Array1or2_Create(struct Array1or2 *A, unsigned Dims);
void Array1or2_Destroy(struct Array1or2 *A);
// Get value with only X
int Array1or2_X(const struct Array1or2 *A, unsigned x);
// Get value with X & Y
int Array1or2_XY(const struct Array1or2 *A, unsigned x, unsigned x);
示例实现
void Array1or2_Create(struct Array1or2 *A, unsigned Dims) {
assert(Dims >= 1 && Dims <= 2);
A->DimCount = Dims;
size_t size = sizeof *(A->data);
while (Dims > 0) size *= 10;
A->data = malloc(size);
assert(A->data);
}
int Array1or2_X(const struct Array1or2 *A, unsigned x) {
assert(x < 10);
return A->data[x];
}
int Array1or2_XY(const struct Array1or2 *A, unsigned x, unsigned y) {
assert(x < 10 && y < 10);
if (A->DimCount < 2) return 0;
return A->data[x + 10*y];
}