0

I have a CSV file from which I want the values to be stored into a three dimensional array Cl[x][y][z] in C++.

The current file following format of a 2D array.

29  26  20  18  
29  25  23  21  
31  28  25  23
33  30  28  25  

This 2D array has to be duplicated multiple times in the third dimension to yield a 3D array which I will be using further along in the code.

Currently I have trouble reading the values from the csv file and converting them to 3D array in C++.

This is the current code that I have:

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

When I run the code, each element of array has the clvDefault value which I assigned and the values from the csv file are not read.

It looks like while loop is skipped during the run. Any suggestions on how to fix this issue is appreciated.

6
  • can you give us a snippet of the csv file Commented Mar 13, 2020 at 3:09
  • There already is a plethora of questions and examples about read CSV files. Search the internet for "C++ read csv file array". Commented Mar 13, 2020 at 3:48
  • You need to add a return or similar in your file error handling code, otherwise the code keeps executing as if the file open was successful. Commented Mar 13, 2020 at 3:50
  • If your values are tab or whitespace separated, don't read in a delimiter. Reading in and integer skips whitespace (by default). Commented Mar 13, 2020 at 3:53
  • You allocate for widthZ pointers to widthY pointers to widthX float. Is that what you intend? Your code is set up that way and it doesn't matter what letters you use, but that is a bit in reverse of what you normally see. Commented Mar 13, 2020 at 4:56

1 Answer 1

1

There are many, many errors in your program. Let me list up the most important:

  • Usage of raw pointers for owned memory. Never do this in C++ (if at all, use std::unique_ptr instead)
  • Do not use new in C++ to allocate memory (use std::make_unique)
  • If you allocate memory with new, then you must delete it afterwards
  • Best: Do use container from the standard library, in this case std::vector
  • Always initialize all variables
  • Always check the result of file operations like open or >>
  • Handle errors
  • Use ++v instead of v++
  • Define variables, when you need them. Keep them scoped. Prevent Namespace pollution
  • If you want to write C++ code, then use C++ language elements and not C
  • Try to design your code with modern C++ language elements

So. I fixed your code, so that it runs, reads your example file and displays the result. I removed the major bugs. Please see:

#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 file\n";
    }
    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;
}

However. I would not recommend to use that. The quality is too bad. It is error prone and somehow still complete a C-Program.

Please see the part, where I read the CSV file. Of course, there is no external library necessary. I hear often such nonesense recomendations for ultra simple CSV files. So, no library. Example from above code:

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

Nobody can persuade me, that I need a library, for what I can do with 3 simple lines of code.

If you are interested to learn, then I show you also a "more-modern" C++ solution:

#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 file\n";
    }
    return 0;
}

Please note that you can write elegant very elegant and compact code in C++.

For reading the file and creating the 3d vector, I do not need any loop.

Please read and try to understand. Please google unknwon language constructs. If you do not understand, then ask.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.