我需要一些帮助 - 下一段代码将一个长双动态数组写入文件
int nx = 10, ny = 10;
long double **data = new long double *[nx];
long double **data_read = new long double *[nx];
for (int i = 0; i < nx; i++) {
data[i] = new long double [ny];
data_read[i] = new long double [ny];
}
data[4][4] = 10.0;
printf("%LF\n", data[4][4]);
FILE *file = fopen("data", "wb");
fwrite(data, nx * ny * sizeof(data), 1, file);
fclose(file);
file = fopen("data", "rb");
fread(data, nx * ny * sizeof(data_read), 1, file );
fclose(file);
printf("%LF\n", data_read[4][4]);
但是data[4][4] != data_read[4][4]
,因为在阅读了文件data_read[4][4]=0.0
之后。
有人知道我做错了什么吗?
答案 0 :(得分:7)
您需要单独编写指针数组中的每一行。批量写入不适用于假二维数组(或nD)的指针到指针实现。
写作:
for (int i=0; i<nx; ++i)
fwrite(data[i], sizeof(data[i][0]), ny, file);
阅读:
for (int i=0; i<nx; ++i)
fread(data[i], sizeof(data[i][0]), ny, file);
坦率地说,你是(非)幸运的,这个过程并没有彻底崩溃,因为你正在为你的磁盘文件写一堆内存地址(十六进制转储会向你显示),并且可能已经离开了两个操作期间指针数组分配的结束。
那就是说,我开始学习标准的C ++ IO库,而不是在C ++世界中使用C代码(或者在这个问题上修复标签)。
单一块写入/读取
您询问是否可以将此作为单个块读/写来执行。答案是肯定的,但您必须连续分配内存。如果你仍然想要一个指向指针的数组,你当然可以使用一个。虽然我建议使用std::vector<long double>
作为数据缓冲区,但以下内容将演示我所指的内容:
int main()
{
int nx = 10, ny = 10;
long double *buff1 = new long double[nx * ny];
long double *buff2 = new long double[nx * ny];
long double **data = new long double *[nx];
long double **data_read = new long double *[nx];
for (int i = 0; i < nx; i++)
{
data[i] = buff1 + (i*ny);
data_read[i] = buff2 + (i*ny);
}
data[4][4] = 10.0;
printf("%LF\n", data[4][4]);
FILE *file = fopen("data.bin", "wb");
fwrite(buff1, sizeof(*buff1), nx * ny, file);
fclose(file);
file = fopen("data.bin", "rb");
fread(buff2, sizeof(*buff2), nx * ny, file );
fclose(file);
printf("%LF\n", data_read[4][4]);
// delete pointer arrays
delete [] data;
delete [] data_read;
// delete buffers
delete [] buff1;
delete [] buff2;
}
<强>输出强>
10.000000
10.000000
std::vector<>
使用RAII解决方案
所有这些分配都会变得混乱,坦率地说容易出问题。考虑一下这是如何不同的:
#include <iostream>
#include <fstream>
#include <vector>
int main()
{
int nx = 10, ny = 10;
// buffers for allocation
std::vector<long double> buff1(nx*ny);
std::vector<long double> buff2(nx*ny);
// holds pointers into original
std::vector<long double*> data(nx);
std::vector<long double*> data_read(nx);
for (int i = 0; i < nx; i++)
{
data[i] = buff1.data() + (i*ny);
data_read[i] = buff2.data() + (i*ny);
}
data[4][4] = 10.0;
std::cout << data[4][4] << std::endl;
std::ofstream ofp("data.bin", std::ios::out | std::ios::binary);
ofp.write(reinterpret_cast<const char*>(buff1.data()), buff1.size() * sizeof(buff1[0]));
ofp.close();
std::ifstream ifp("data.bin", std::ios::in | std::ios::binary);
ifp.read(reinterpret_cast<char*>(buff2.data()), buff2.size() * sizeof(buff2[0]));
ifp.close();
std::cout << data_read[4][4] << std::endl;
return 0;
}
答案 1 :(得分:2)
将您的代码更改为(请参阅注释以获取详细信息):
...
data[4][4] = 10.0;
printf("%Lf\n", data[4][4]); // use %Lf to print long double, not %LF
FILE *file = fopen("data", "wb");
for (int i=0; i<nx; ++i) // must write row-by-row as data are not continuous
fwrite(data[i], sizeof(long double), ny, file);
// cannot use sizeof(data) here as data is a pointer here, will always return 4
fclose(file);
file = fopen("data", "rb");
for (int i=0; i<nx; ++i) // read row-by-row
fread(data_read[i], sizeof(long double), ny, file);
// 1. read to data_read, not data
// 2. cannot use sizeof(data) here as data is a pointer here, will always return 4
fclose(file);
printf("%Lf\n", data_read[4][4]); // use %Lf to print long double, not %LF
...
修改强>
如果要在连续内存中格式化数据,请改用vector<long double>
或long double data[nx*ny]
。然后你可以通过以下方式轻松地书写或阅读:
fwrite(data, nx * ny * sizeof(long double), 1, file);
...
fread(data_read, nx * ny * sizeof(long double), 1, file );