我有一个C++程序,通过读取网格人口数据并将其存储在一个大的8640x3432元素的双精度向量中,计算给定半径内的人口数量。将ASCII数据读入向量需要约30秒(循环遍历每列和每行),而程序的其余部分仅需几秒钟。要求我通过将人口数据写入二进制文件来加快此过程,这样读取速度会更快。
ASCII数据文件有一些标题行,给出了一些数据规范,如列数和行数,然后是每个网格单元的人口数据,格式为8640个数字的3432行,由空格分隔。人口数据数字是混合格式,可以是0、小数值(0.000685648)或科学计数法表示的值(2.687768e-05)。
我找到了一些读写包含向量的结构体的示例,并尝试实现类似的东西,但遇到了问题。当我在同一程序中同时将向量写入和读取二进制文件时,它似乎可以工作并给我所有正确的值,但最后要么以“segment fault: 11”的形式结束,要么是一个内存分配错误,“未分配指针”被释放。如果我仅从先前写入的二进制文件中读取数据(而不在同一程序运行中重新编写它),则可以正常读取标题变量,但在给出向量数据之前会出现段错误。
非常感谢您提供有关我可能犯的错误或更好的方法的任何建议!我正在Mac上编译和运行,目前没有Boost或其他非标准库。(注意:我非常新于编码,并且需要通过跳入深水区来学习,所以我可能会忽略许多基本概念和术语 - 抱歉!)
这是我想到的代码:
感谢您提前的任何帮助!
ASCII数据文件有一些标题行,给出了一些数据规范,如列数和行数,然后是每个网格单元的人口数据,格式为8640个数字的3432行,由空格分隔。人口数据数字是混合格式,可以是0、小数值(0.000685648)或科学计数法表示的值(2.687768e-05)。
我找到了一些读写包含向量的结构体的示例,并尝试实现类似的东西,但遇到了问题。当我在同一程序中同时将向量写入和读取二进制文件时,它似乎可以工作并给我所有正确的值,但最后要么以“segment fault: 11”的形式结束,要么是一个内存分配错误,“未分配指针”被释放。如果我仅从先前写入的二进制文件中读取数据(而不在同一程序运行中重新编写它),则可以正常读取标题变量,但在给出向量数据之前会出现段错误。
非常感谢您提供有关我可能犯的错误或更好的方法的任何建议!我正在Mac上编译和运行,目前没有Boost或其他非标准库。(注意:我非常新于编码,并且需要通过跳入深水区来学习,所以我可能会忽略许多基本概念和术语 - 抱歉!)
这是我想到的代码:
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <fstream>
# include <iostream>
# include <vector>
# include <string.h>
using namespace std;
//Define struct for population file data and initialize one struct variable for reading in ascii (A) and one for reading in binary (B)
struct popFileData
{
int nRows, nCol;
vector< vector<double> > popCount; //this will end up having 3432x8640 elements
} popDataA, popDataB;
int main() {
string gridFname = "sample";
double dum;
vector<double> tempVector;
//open ascii population grid file to stream
ifstream gridFile;
gridFile.open(gridFname + ".asc");
int i = 0, j = 0;
if (gridFile.is_open())
{
//read in header data from file
string fileLine;
gridFile >> fileLine >> popDataA.nCol;
gridFile >> fileLine >> popDataA.nRows;
popDataA.popCount.clear();
//read in vector data, point-by-point
for (i = 0; i < popDataA.nRows; i++)
{
tempVector.clear();
for (j = 0; j<popDataA.nCol; j++)
{
gridFile >> dum;
tempVector.push_back(dum);
}
popDataA.popCount.push_back(tempVector);
}
//close ascii grid file
gridFile.close();
}
else
{
cout << "Population file read failed!" << endl;
}
//create/open binary file
ofstream ofs(gridFname + ".bin", ios::trunc | ios::binary);
if (ofs.is_open())
{
//write struct to binary file then close binary file
ofs.write((char *)&popDataA, sizeof(popDataA));
ofs.close();
}
else cout << "error writing to binary file" << endl;
//read data from binary file into popDataB struct
ifstream ifs(gridFname + ".bin", ios::binary);
if (ifs.is_open())
{
ifs.read((char *)&popDataB, sizeof(popDataB));
ifs.close();
}
else cout << "error reading from binary file" << endl;
//compare results of reading in from the ascii file and reading in from the binary file
cout << "File Header Values:\n";
cout << "Columns (ascii vs binary): " << popDataA.nCol << " vs. " << popDataB.nCol << endl;
cout << "Rows (ascii vs binary):" << popDataA.nRows << " vs." << popDataB.nRows << endl;
cout << "Spot Check Vector Values: " << endl;
cout << "Index 0,0: " << popDataA.popCount[0][0] << " vs. " << popDataB.popCount[0][0] << endl;
cout << "Index 3431,8639: " << popDataA.popCount[3431][8639] << " vs. " << popDataB.popCount[3431][8639] << endl;
cout << "Index 1600,4320: " << popDataA.popCount[1600][4320] << " vs. " << popDataB.popCount[1600][4320] << endl;
return 0;
}
当我在同一次运行中同时写入和读取二进制文件时,以下是输出结果:
File Header Values:
Columns (ascii vs binary): 8640 vs. 8640
Rows (ascii vs binary):3432 vs.3432
Spot Check Vector Values:
Index 0,0: 0 vs. 0
Index 3431,8639: 0 vs. 0
Index 1600,4320: 25.2184 vs. 25.2184
a.out(11402,0x7fff77c25310) malloc: *** error for object 0x7fde9821c000: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
如果我尝试从预先存在的二进制文件中读取,我得到的输出如下:
File Header Values:
Columns (binary): 8640
Rows (binary):3432
Spot Check Vector Values:
Segmentation fault: 11
感谢您提前的任何帮助!
sizeof
计算向量的总大小,因为这只会给出底层结构的大小,而不是任何分配的数据。 - Jonathan Potter