C做3D数组就好了:
double data[D0][D1][D2];
...
data[i][j][k] = ...;
Run Code Online (Sandbox Code Playgroud)
尽管对于例如您的示例中的非常大的数组,您可能希望动态分配数组,而不是auto像上面那样将它们声明为变量,因为auto变量的空间(通常是堆栈,但并非总是如此)可能非常有限。
假设所有尺寸在编译时都是已知的,则可以执行以下操作:
#include <stdlib.h>
...
#define DO 100
#define D1 100
#define D2 100
...
double (*data)[D1][D2] = malloc(sizeof *data * D0);
if (data)
{
...
data[i][j][k] = ...;
...
free(data);
}
Run Code Online (Sandbox Code Playgroud)
这将从堆中分配一个D0xD1xD2数组,您可以像访问任何常规3D数组一样访问它。
如果您的尺寸直到运行时才知道,但是您正在使用支持可变长度数组的C99编译器或C2011编译器,则可以执行以下操作:
#include <stdlib.h>
...
size_t d0, d1, d2;
d0 = ...;
d1 = ...;
d2 = ...;
...
double (*data)[d1][d2] = malloc(sizeof *data * d0);
if (data)
{
// same as above
}
Run Code Online (Sandbox Code Playgroud)
如果直到运行时才知道尺寸,并且您正在使用不支持可变长度数组的编译器(C89或更早版本,或者不支持VLA的C2011编译器),则需要采用其他方法。
如果需要连续分配内存,则需要执行以下操作:
size_t d0, d1, d2;
d0 = ...;
d1 = ...;
d2 = ...;
...
double *data = malloc(sizeof *data * d0 * d1 * d2);
if (data)
{
...
data[i * d0 * d1 + j * d1 + k] = ...;
...
free(data);
}
Run Code Online (Sandbox Code Playgroud)
请注意,你有你的地图i,j和k索引到一个单一的指标值。
如果内存不需要是连续的,则可以像这样进行零碎分配:
double ***data;
...
data = malloc(d0 * sizeof *data);
if (data)
{
size_t i;
for (i = 0; i < d0; i++)
{
data[i] = malloc(d1 * sizeof *data[i]);
if (data[i])
{
size_t j;
for (j = 0; j < d1; j++)
{
data[i][j] = malloc(d2 * sizeof *data[i][j]);
if (data[i][j])
{
size_t k;
for (k = 0; k < d2; k++)
{
data[i][j][k] = initial_value();
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
并重新分配为
for (i = 0; i < d0; i++)
{
for (j = 0; j < d1; j++)
{
free(data[i][j]);
}
free(data[i]);
}
free(data);
Run Code Online (Sandbox Code Playgroud)
不建议这样做,顺便说一句;即使它可以让你的索引data,就好像是一个三维阵列,代价是更复杂的代码,特别是如果malloc通过分配回路中途失败(那么你必须背出所有到目前为止您所做的分配)。由于不能保证内存的位置很好,这也可能会导致性能下降。
编辑
至于将这些数据保存在文件中,这取决于您需要执行的操作。
最可移植的是将数据另存为格式化的文本,例如:
#include <stdio.h>
FILE *dat = fopen("myfile.dat", "w"); // opens new file for writing
if (dat)
{
for (i = 0; i < D0; i++)
{
for (j = 0; j < D1; j++)
{
for (k = 0; k < D2; k++)
{
fprintf(dat, "%f ", data[i][j][k]);
}
fprintf(dat, "\n");
}
fprintf(dat, "\n");
}
}
Run Code Online (Sandbox Code Playgroud)
这将数据以浮点数序列的形式写出,每行的末尾都有一个换行符,每个“页面”的末尾有两个换行符。读回数据本质上是相反的:
FILE *dat = fopen("myfile.dat", "r"); // opens file for reading
if (dat)
{
for (i = 0; i < D0; i++)
for (j = 0; j < D1; j++)
for (k = 0; k < D2; k++)
fscanf(dat, "%f", &data[i][j][k]);
}
Run Code Online (Sandbox Code Playgroud)
请注意,这两个片段均假定阵列具有已知的固定大小,并且每次运行之间都不会改变。如果不是这种情况,显然您将不得不在文件中存储其他数据,以确定阵列需要多大。也没有类似错误处理的内容。
我不确定很多东西,因为我不确定您的目标是什么。