我有一个CSV文件,我希望将其中的值存储到C++中的三维数组Cl[x][y][z]
中。
当前文件遵循二维阵列的格式。
29 26 20 18
29 25 23 21
31 28 25 23
33 30 28 25
这个2D阵列必须在第三维度中重复多次才能产生3D阵列,我将在代码中进一步使用它。
目前,我在读取csv文件中的值并将其转换为C++中的3D数组时遇到了问题。
这是我目前拥有的代码:
unsigned short int widthX = wX;
unsigned short int widthY = wY;
unsigned short int widthZ = wZ;
unsigned short int x, y, z;
float clvDefault = 0.0;
float *** Cl = new float**[widthZ];
for (i=0; i<widthZ; i++)
{
Cl[i] = new float*[widthY];
for (j=0; j<widthY; j++)
{
Cl[i][j] = new float[widthX];
}
}
std::ifstream clvIn;
std::string clvFileName = "File_read.csv";
clvIn.open(clvFileName.c_str());
if(clvIn.fail())
{
// something bad happened when opening the file
}
std::string filejunk;
char delim;
std::getline(clvIn, filejunk);
int clvX, clvY, clvZ;
float clvValue;
for (z = 0; z < widthZ; z++)
{
for (y = 0; y < widthY; y++)
{
for (x = 0; x < widthX; x++)
{
Cl[z][y][x] = clvDefault;
}
}
}
while(clvIn >> clvY >> delim >> clvX >> delim >> clvValue)
{
Cl[0][clvY][clvX] = clvValue;
}
for(y = 0; y < widthY; y++)
{
for(x = 0; x < widthX; x++)
{
clvIn >> Cl[0][y][x] >> delim;
}
for (z = 1; z < widthZ; z++)
{
for (y = 0; y < widthY; y++)
{
for (x = 0; x < widthX; x++)
{
Cl[z][y][x] = Cl[0][y][x];
}
}
}
当我运行代码时,数组的每个元素都有我分配的clvDefault
值,并且不会读取csv文件中的值。
看起来while循环在运行过程中被跳过了。欢迎就如何解决此问题提出任何建议。
程序中有很多错误。让我列出最重要的:
- 拥有内存的原始指针的使用。永远不要在C++中执行此操作(如果有的话,请改用
std::unique_ptr
( - 不要在C++中使用
new
来分配内存(使用std::make_unique
( - 如果使用
new
分配内存,则必须稍后使用delete
- 最佳:请使用标准库中的容器,在本例中为
std::vector
- 始终初始化所有变量
- 始终检查打开或>>等文件操作的结果
- 处理错误
- 使用
++v
而不是v++
- 在需要时定义变量。保持它们的作用域。防止命名空间污染
- 如果你想写C++代码,那么就使用C++语言元素,而不是C
- 尝试使用现代C++语言元素设计代码
所以。我修复了您的代码,使其运行、读取示例文件并显示结果。我去掉了主要的bug。请参阅:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
float*** get3dArry(unsigned short widthX, unsigned short widthY, unsigned short widthZ) {
unsigned short int i, j, x, y, z;
float clvDefault = 0.0;
float*** Cl = new float** [widthZ];
for (i = 0; i < widthZ; i++)
{
Cl[i] = new float* [widthY];
for (j = 0; j < widthY; j++)
{
Cl[i][j] = new float[widthX];
}
}
std::ifstream clvIn;
std::string clvFileName = "r:\File_read.csv";
clvIn.open(clvFileName.c_str());
if (clvIn.fail())
{
std::cerr << "n*** Error: Could not open input filen";
}
else {
std::string filejunk, line;
char delim;
//std::getline(clvIn, filejunk);
int clvX, clvY, clvZ;
float clvValue;
for (z = 0; z < widthZ; z++)
{
for (y = 0; y < widthY; y++)
{
for (x = 0; x < widthX; x++)
{
Cl[z][y][x] = clvDefault;
}
}
}
for (y = 0; (y < widthY) && std::getline(clvIn, line); ++y) {
std::istringstream iss{ line };
for (x = 0; (x < widthY) && (iss >> Cl[0][y][x]); ++x)
;
}
for (z = 0; z < widthZ; z++)
{
for (y = 0; y < widthY; y++)
{
for (x = 0; x < widthX; x++)
{
Cl[z][y][x] = Cl[0][y][x];
}
}
}
}
return Cl;
}
int main() {
float*** a3d = get3dArry(4, 4, 3);
for (int z = 0; z < 3; ++z) {
std::cout << "n";
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
std::cout << a3d[z][y][x] << "t";
}
std::cout << "n";
delete[] a3d[z][y];
}
delete[] a3d[z];
}
delete[] a3d;
return 0;
}
然而。我不建议使用它。质量太差了。它很容易出错,而且在某种程度上仍然可以完成C程序。
请参阅我阅读CSV文件的部分。当然,这里不需要外部图书馆。我经常听到这种对超简单CSV文件的无意义的建议。所以,没有图书馆。以上代码示例:
for (y = 0; (y < widthY) && std::getline(clvIn, line); ++y) {
std::istringstream iss{ line };
for (x = 0; (x < widthY) && (iss >> Cl[0][y][x]); ++x)
;
}
没有人能说服我,我需要一个库,因为我可以用3行简单的代码做什么。
如果你有兴趣学习,那么我还会向你展示一个"更现代"的C++解决方案:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include <iterator>
// Make reading datatypes easier
using DataType = float;
using Matrix1dX = std::vector<DataType>;
using Matrix2dYX = std::vector<Matrix1dX>;
using Matrix3dZYX = std::vector<Matrix2dYX>;
// This is the number of z values for the 3rd dimension. Whatever you want
constexpr size_t NumberOfDimensionZ = 3U;
int main() {
// Open input csv file, and check, if open operation worked
if (std::ifstream clvIn("r:\File_read.csv"); clvIn) {
// Define 2d array and initialize all values with 0.0;
Matrix2dYX myx{};
// Read all lines of the file and split values
for (std::string line{}; std::getline(clvIn, line); ) {
// Convert just read string to a std::istringstream
std::istringstream iss{ line };
// Add the new values to the 2d array. Iterate over all values in one line
// then create a 1d vector inplace and add this line values to our 2d matrix
myx.emplace_back(Matrix1dX(std::istream_iterator<DataType>(iss), {}));
}
// Define a 3d matrix, with a given size and having each z-value be the data from the csv file
Matrix3dZYX mzyx(NumberOfDimensionZ, myx);
// Some debug output
// Show result to user
for (const Matrix2dYX& m2 : mzyx) {
std::cout << "n";
for (const Matrix1dX& m1 : m2) {
for (const DataType& d : m1) std::cout << d << "t";
std::cout << "n";
}
}
}
else {
std::cerr << "n*** Error: Could not open input filen";
}
return 0;
}
请注意,您可以用C++编写优雅、非常优雅和紧凑的代码。
对于读取文件和创建三维矢量,我不需要任何循环。
请阅读并试着理解。请用谷歌搜索unknwon语言结构。如果你不明白,那就去问。