简体   繁体   English

在C中保存多维数组

[英]Saving multidimensional arrays in C

I have saved multidimensional arrays in Matlab before (eg an array A that has size 100x100x100) using a .mat file and that worked out very nicely. 我之前使用.mat文件在Matlab中保存了多维数组(例如,大小为100x100x100的数组A )并且效果非常好。

What is the best way to save such multidimensional arrays in C? 在C中保存这样的多维数组的最佳方法是什么? The only way I can think of is to store it as a 2D array (eg convert a KxNxM array to a KNxM array) and be careful in remembering how it was saved. 我能想到的唯一方法是将其存储为2D数组(例如,将KxNxM数组转换为KNxM数组),并记住它是如何保存的。

What is also desired is to save it in a way that can be opened later in Matlab for post-processing/plotting. 还希望以稍后可以在Matlab中打开的方式保存它以进行后处理/绘图。

C does 3D arrays just fine: C做3D阵列就好了:

double data[D0][D1][D2];
...
data[i][j][k] = ...;

although for very large arrays such as in your example, you would want to allocate the arrays dynamically instead of declaring them as auto variables such as above, since the space for auto variables ( usually the stack, but not always) may be very limited. 虽然对于非常大的数组(例如在您的示例中),您可能希望动态分配数组,而不是将它们声明为auto变量(如上所述),因为auto变量的空间( 通常是堆栈,但并非总是如此)可能非常有限。

Assuming all your dimensions are known at compile time, you could do something like: 假设在编译时已知所有维度,您可以执行以下操作:

#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);
}

This will allocate a D0xD1xD2 array from the heap, and you can access it like any regular 3D array. 这将从堆中分配D0xD1xD2数组,您可以像任何常规3D数组一样访问它。

If your dimensions are not known until run time, but you're working with a C99 compiler or a C2011 compiler that supports variable-length arrays, you can do something like this: 如果直到运行时才知道维度,但是您使用的是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
}

If your dimensions are not known until runtime and you're working with a compiler that does not support variable-length arrays (C89 or earlier, or a C2011 compiler without VLA support), you'll need to take a different approach. 如果您的尺寸是不知道,直到运行时和你同支持变长数组编译器(C89或更早的版本,或者没有VLA支持C2011编译器)的工作,你需要采取不同的方法。

If the memory needs to be allocated contiguously, then you'll need to do something like the following: 如果需要连续分配内存,那么您需要执行以下操作:

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);
}

Note that you have to map your i , j , and k indices to a single index value. 请注意,您必须将ijk索引映射到单个索引值。

If the memory doesn't need to be contiguous, you can do a piecemeal allocation like so: 如果内存不需要连续,你可以这样做一个零碎的分配:

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();
          }
        }
      }
    }
  }
}

and deallocate it as 并将其解除分配

for (i = 0; i < d0; i++)
{
  for (j = 0; j < d1; j++)
  {
    free(data[i][j]);
  }
  free(data[i]);
}
free(data);

This is not recommended practice, btw; 这不是推荐的做法,顺便说一下; even though it allows you to index data as though it were a 3D array, the tradeoff is more complicated code, especially if malloc fails midway through the allocation loop (then you have to back out all the allocations you've made so far). 尽管它允许您将data入索引,就像它是一个3D数组一样,但是权衡更复杂的代码, 特别是如果malloc在分配循环的中途失败(那么你必须退出到目前为止所做的所有分配)。 It may also incur a performance penalty since the memory isn't guaranteed to be well-localized. 它可能还会导致性能下降,因为内存不能保证良好本地化。

EDIT 编辑

As for saving this data in a file, it kind of depends on what you need to do. 至于将这些数据保存在文件中,它取决于您需要做什么。

The most portable is to save the data as formatted text, such as: 最便携的是将数据保存为格式化文本,例如:

#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");
  }
}

This writes the data out as a sequence of floating-point numbers, with a newline at the end of each row, and two newlines at the end of each "page". 这将数据写为一系列浮点数,每行末尾有换行符,每个“页”末尾有两个换行符。 Reading the data back in is essentially the reverse: 重新读取数据基本上是相反的:

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]);
}

Note that both of these snippets assume that the array has a known, fixed size that does not change from run to run. 请注意,这两个片段都假定该数组具有已知的固定大小,该大小在运行期间不会更改。 If that is not the case, you will obviously have to store additional data in the file to determine how big the array needs to be. 如果不是这种情况,您显然必须在文件中存储其他数据以确定数组需要多大的数据。 There's also nothing resembling error handling. 也没有类似错误处理的东西。

I'm leaving a lot of stuff out, since I'm not sure what your goal is. 我要留下很多东西,因为我不确定你的目标是什么。

Well, you can of course store it as a 3D array in C, too. 那么,您当然可以将其存储为C中的3D数组。 Not sure why you feel you must convert to 2D: 不确定为什么你觉得必须转换为2D:

double data[100][100][100];

This will of course require quite a bit of memory (around 7.6 MB assuming a 64-bit double ), but that should be fine on a PC, for instance. 这当然需要相当多的内存(假设64位double大约需要7.6 MB),但这应该可以在PC上使用,例如。

You might want to avoid putting such a variable on the stack, though. 但是,您可能希望避免将这样的变量放在堆栈上。

C handles multidimensional arrays ( double array[K][M][N]; ) just fine, and they are stored contiguously in memory the same as a 1-D array. C处理多维数组( double array[K][M][N]; )就好了,它们连续存储在内存中,与1-D数组相同。 In fact, it's legal to write double* onedim = &array[0][0][0]; 实际上,编写double* onedim = &array[0][0][0];是合法的double* onedim = &array[0][0][0]; and then use the same exact memory area as both a 3-D and 1-D array. 然后使用与3-D和1-D阵列相同的精确存储区域。

To get it from C into matlab, you can just use fwrite(array, sizeof array[0][0][0], K*M*N*, fptr) in C and array = fread(fileID, inf, 'real*8') in MatLab. 要从C到matlab,你可以在C中使用fwrite(array, sizeof array[0][0][0], K*M*N*, fptr)array = fread(fileID, inf, 'real*8')在MatLab中。 You may find that the reshape function is helpful. 您可能会发现reshape功能很有用。

c can handle 3-dimensional arrays, so why don't use that? c可以处理三维数组,为什么不使用它?

Writing it on a .mat file is a little bit of work, but it doesn't seem too difficult. 将它写在.mat文件上有点工作,但看起来并不太难。

The .mat format is described here . 这里描述 .mat格式。

Triple pointer: 三指针:

double*** X;
X= (double***)malloc(k*sizeof(double**));
for(int i=0; i<k;i++)
{
   X[i]=(double**)malloc(n*sizeof(double*));
   for(int j=0; j<n;j++)
   {
       X[i][j]=(double*)malloc(m*sizeof(double));
   }
}

This way the method to access at each value if quite intuitive: X[i][j][k]. 这种方式可以非常直观地访问每个值:X [i] [j] [k]。
If instead you want, you can use an unique array: 如果你想要,你可以使用一个独特的数组:

double* X;
X=(double*)malloc(n*m*k*sizeof(double));

And you access to each element this way: 您可以通过这种方式访问​​每个元素:

X[i*n*m+j*n+k]=0.0;

If you use a triple pointer, don't forget to free the memory. 如果使用三重指针,请不要忘记释放内存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM