您好我正在尝试在C中转换matlab代码。在这样做时,我必须将2d数组重塑为3d数组。我试着编写一个函数,如下所示。我从here获得了帮助。
#include <stdio.h>
#include <stdlib.h>
#define ZALLOC(item, n, type) if ((item = (type *)calloc((n), sizeof(type))) == NULL) \
fatalx("Unable to allocate %d unit(s) for item\n", n)
int i,j,k,x,y;
static void fatalx(const char *str, size_t n)
{
fprintf(stderr, "%s: %zu\n", str, n);
exit(1);
}
static int ***alloc_3d(int ar[][12],int rows, int cols,int levels)
{
int count = 0;
int ***array_3d;
ZALLOC(array_3d, levels, int **);
for (i = 0; i < levels; i++)
{
int **data;
ZALLOC(data, rows, int *);
array_3d[i] = data;
for (j = 0; j < rows; j++)
{
int *entries;
ZALLOC(entries, cols, int);
array_3d[i][j] = entries;
for (k = 0; k < cols; k++)
{
array_3d[i][j][k] = ar[i][j];
}
}
}
return array_3d;
}
static void print_3d(int ***a3d, int rows, int cols,int levels)
{
for (i = 0; i < levels; i++)
{
printf("%d:\n", i);
for (j = 0; j < rows; j++)
{
printf(" %d: ", j);
for (k = 0; k < cols; k++)
printf(" %3d", a3d[i][j][k]);
putchar('\n');
}
}
}
static void free_3d(int ***a3d, int levels, int rows)
{
for (i = 0; i < levels; i++)
{
for (j = 0; j < rows; j++)
free(a3d[i][j]);
free(a3d[i]);
}
free(a3d);
}
int main(void)
{
int ar[2][12]={
{1,2,3,4,5,6,7,8,9,10,11,12},
{13,14,15,16,17,18,19,20,21,22,23,24}
};
int d1 = 2;
int d2 = 3;
int d3 = 4;
int ***a3d = alloc_3d(ar,d1, d2, d3);
print_3d(a3d, d1, d2, d3);
free_3d(a3d, d3, d2);
return(0);
}
这不仅给了我错误的值,还给了垃圾值。第一个切片的matlab输出是:
a3d(:,:,1)=
1 2 3 13 14 15
我的一个与
完全不同0:
0: 1 1 1
1: 2 2 2
1:
0: 13 13 13
1: 14 14 14
2:
0: 1991011277 1991011277 1991011277
1: 4 4 4
3:
0: 1 1 1
1: 6630248 6630248 6630248
正如您所看到的那样,还有垃圾价值。所以我的索引也是错误的。知道如何正确地做到这一点? 提前谢谢。
答案 0 :(得分:1)
事实上,您的示例不会执行重新整形,因为它会创建一个与原始数组完全不同类型的复合对象。
C多维数组是一个数组数组(数组......)。在其他重要特征中,这种阵列的所有元素在存储器中是连续的。你也可以构造一个指针数组,并初始化每个指针以指向它自己的数组等。尽管这些类型的对象在表面上是相似的,你可以以大致相同的方式将索引操作符应用于两者。重要的是要理解:
如果使用标准C多维数组(==数组数组)编写,程序的外观如下:
#include <stdlib.h>
#include <stdio.h>
#define ALLOC(p, n) do { \
if (!((p) = calloc((n), sizeof(*(p))))) { \
fprintf(stderr, "Memory allocation failure\n"); \
exit(1); \
} \
} while (0)
void *reshape_2d_3d(size_t id1, size_t id2, int iar[][id2],
size_t od1, size_t od2, size_t od3) {
// oar is a pointer to a multidimensional array; in this case, it will
// point to the first element of an array of arrays (of arrays).
int (*oar)[od2][od3];
size_t size1 = id1 * id2;
size_t size2 = od1 * od2 * od3;
size_t min_size = (size1 <= size2) ? size1 : size2;
ALLOC(oar, od1);
// A loop nest could be used here, too, but I find this simpler for
// tracking the correspondence of array elements. It also better
// accommodates the case where the reshaped result has different overall
// size from the original.
for (size_t i = 0; i < min_size; i++) {
oar[i / (od2 * od3)][(i / od3) % od2][i % od3] = iar[i / id2][i % id2];
}
return oar;
}
void print_3d(size_t levels, size_t rows, size_t cols, int ar[][rows][cols]) {
for (int i = 0; i < levels; i++) {
printf("%d:\n", i);
for (int j = 0; j < rows; j++) {
printf(" %d: ", j);
for (int k = 0; k < cols; k++) {
printf(" %3d", ar[i][j][k]);
}
putchar('\n');
}
}
}
int main(void) {
int ar[2][12] = {
{1,2,3,4,5,6,7,8,9,10,11,12},
{13,14,15,16,17,18,19,20,21,22,23,24}
};
int d1 = 2, d2 = 3, d3 = 4;
int (*a3d)[d2][d3] = reshape_2d_3d(2, 12, ar, d1, d2, d3);
print_3d(d1, d2, d3, a3d);
// A single, simple free() is all that's needed
free(a3d);
}
输出:
0:
0: 1 2 3 4
1: 5 6 7 8
2: 9 10 11 12
1:
0: 13 14 15 16
1: 17 18 19 20
2: 21 22 23 24
请注意,它使用可变长度数组,但通常不关心堆栈分配。因此,它需要符合C99编译器,或符合C2011编译器,以实现VLA可选(在该版本中)功能。
答案 1 :(得分:0)
将数字分配给新分配的内存的方法是错误的。
static int ***alloc_3d(int ar[][12],int rows, int cols,int levels,int colsize)
{
int count = 0;
int ***array_3d;
ZALLOC(array_3d, levels, int **);
int i1=0,j1=0;
for (i = 0; i < levels; i++)
{ ...
...
for (k = 0; k < cols; k++)
{
array_3d[i][j][k] = ar[i1][j1++];
if( j1 == colsize) i1++,j1=0;
}
}
}
return array_3d;
}
像这样打电话
int colsize = 12;
int ***a3d = alloc_3d(ar,d1, d2, d3,colsize);
打印:
0:
0: 1 2 3
1: 4 5 6
1:
0: 7 8 9
1: 10 11 12
2:
0: 13 14 15
1: 16 17 18
3:
0: 19 20 21
1: 22 23 24
一个小小的注释 - 早些时候你的代码有未定义的行为访问绑定的数组索引。