我有一個動態分配的 3D 陣列,它被實作為指向陣列指標陣列的指標(至少這是我對我正在做的事情的解釋),并希望將該資料存盤在 hdf5 檔案中。雖然檔案中存盤了一些內容,但它不是原始資料。
這是我的代碼(此處省略了錯誤檢查的內容):
#include <stdlib.h>
#include <stdio.h>
#include <hdf5.h>
double ***arr3D_d( size_t dim1, size_t dim2, size_t dim3 ) {
size_t ii, jj;
double ***arr;
arr = calloc( (size_t)dim1, sizeof(double**) );
for ( ii=0 ; ii<dim1 ; ii ) {
arr[ii] = calloc( (size_t)(dim2*dim3), sizeof(double*) );
for ( jj=0 ; jj<dim2 ; jj ) {
arr[ii][jj] = calloc( (size_t)(dim3), sizeof(double) );
}
}
return arr;
}
int main( int argc, char *argv[] ) {
size_t ii, jj, kk,
dim1, dim2, dim3;
double ***arr3D;
// hdf5 related variables
hid_t file_id, dataset_id, dataspace_id;
hsize_t dims[3];
herr_t status;
dim1 = 2;
dim2 = 3;
dim3 = 4;
arr3D = arr3D_d( dim1, dim2, dim3 );
for (ii=0 ; ii<dim1 ; ii)
for (jj=0 ; jj<dim2 ; jj)
for (kk=0 ; kk<dim3 ; kk)
arr3D[ii][jj][kk] = ii jj kk;
for (ii=0 ; ii<dim1 ; ii)
for (jj=0 ; jj<dim2 ; jj)
for (kk=0 ; kk<dim3 ; kk)
printf( "arr3D[%ld][%ld][%ld] = %f\n",
ii, jj, kk, arr3D[ii][jj][kk] );
// create new file for hdf5 data to be written into
file_id = H5Fcreate( "data.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT );
// create simple dataspace for the dataset
dims[0] = dim1;
dims[1] = dim2;
dims[2] = dim3;
dataspace_id = H5Screate_simple( 3, dims, NULL );
// create dataset
dataset_id = H5Dcreate( file_id, "dataset", H5T_NATIVE_DOUBLE, dataspace_id,
H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
// write the dataset
status = H5Dwrite( dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL,
H5P_DEFAULT, arr3D[0][0] );
// terminate access and free identifiers
status = H5Dclose(dataset_id);
status = H5Sclose(dataspace_id);
status = H5Fclose(file_id);
return 0;
}
當我現在用 輸出資料時h5dump,它的內容如下:
HDF5 "data.h5" {
GROUP "/" {
DATASET "dataset" {
DATATYPE H5T_IEEE_F64LE
DATASPACE SIMPLE { ( 2, 3, 4 ) / ( 2, 3, 4 ) }
DATA {
(0,0,0): 0, 1, 2, 3,
(0,1,0): 0, 2.42092e-322, 1, 2,
(0,2,0): 3, 4, 0, 2.42092e-322,
(1,0,0): 2, 3, 4, 5,
(1,1,0): 0, 5.58294e-322, 4.64561e-310, 4.64561e-310,
(1,2,0): 4.64561e-310, 0, 0, 0
}
}
}
}
這arr3D與代碼中的不對應,代碼在運行時列印到控制臺 - 輸出如下:
arr3D[0][0][0] = 0.000000
arr3D[0][0][1] = 1.000000
arr3D[0][0][2] = 2.000000
arr3D[0][0][3] = 3.000000
arr3D[0][1][0] = 1.000000
arr3D[0][1][1] = 2.000000
arr3D[0][1][2] = 3.000000
arr3D[0][1][3] = 4.000000
arr3D[0][2][0] = 2.000000
arr3D[0][2][1] = 3.000000
arr3D[0][2][2] = 4.000000
arr3D[0][2][3] = 5.000000
arr3D[1][0][0] = 1.000000
arr3D[1][0][1] = 2.000000
arr3D[1][0][2] = 3.000000
arr3D[1][0][3] = 4.000000
arr3D[1][1][0] = 2.000000
arr3D[1][1][1] = 3.000000
arr3D[1][1][2] = 4.000000
arr3D[1][1][3] = 5.000000
arr3D[1][2][0] = 3.000000
arr3D[1][2][1] = 4.000000
arr3D[1][2][2] = 5.000000
arr3D[1][2][3] = 6.000000
如上所述,這不是寫入 hdf5 檔案的內容。我究竟做錯了什么?
uj5u.com熱心網友回復:
垃圾值的原因是在 HDF5 檔案中存盤指標而不是實際的雙精度值。為了很好地存盤連續分配的陣列,最簡單的方法是使用指向可變長度陣列 (VLA) 的指標分配 3d 陣列。只需用以下行替換所有分配代碼:
double (*arr3D)[dim2][dim3] = calloc(dim1, sizeof *arr3D);
就這樣。
記得打電話free(arr3D)釋放它。
與流行的看法相反,將 VLA 添加到 C 的主要原因是為了簡化處理多維陣列,而不是用于運行時定義大小的物件的堆疊分配。
使用H5Dwrite()passarr3D作為最后一個引數存盤陣列時。
更改后的hdf5檔案內容為:
HDF5 "data.h5" {
GROUP "/" {
DATASET "dataset" {
DATATYPE H5T_IEEE_F64LE
DATASPACE SIMPLE { ( 2, 3, 4 ) / ( 2, 3, 4 ) }
DATA {
(0,0,0): 0, 1, 2, 3,
(0,1,0): 1, 2, 3, 4,
(0,2,0): 2, 3, 4, 5,
(1,0,0): 1, 2, 3, 4,
(1,1,0): 2, 3, 4, 5,
(1,2,0): 3, 4, 5, 6
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/378636.html
上一篇:為什么我們用絕對值來求余弦級數?
