Fernando Salviati
Fernando Salviati

Reputation: 43

C++ Information from csv gets unorganised in the array[][]

I am new in C++, actually learning to do the assignments from the Masters I am studying.

Firstly in my code, I need to read each row and column from a csv file and store it in an array[][].

My CSV file is(columns A1, A2, B1, B2):

46842 test
46825 test2

My code atm is:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main(){
    string val;
    string arr[2][2];

    ifstream myFile;
    myFile.open("excel.csv");
    while (myFile.good())
    {    
        for(int row = 0; row <= 1; row++)
        {
            for(int column = 0; column <= 1; column++)
            { 
                getline(myFile, val, ',');
                arr[row][column] = val;
            }
        }         
    }
    cout <<"cell 0.0: " << arr[0][0] << endl;
    cout <<"cell 0.1: " << arr[0][1] << endl;
    cout <<"cell 1.0: " << arr[1][0] << endl;
    cout <<"cell 1.1: " << arr[1][1] << endl;

}

The problem is the outcome:

cell 0.0: 46842
cell 0.1: test
46825
cell 1.0: test2

cell 1.1: test2

It should be:

cell 0.0: 46842
cell 0.1: test
cell 1.0: 46825
cell 1.1: test2

it seems like the problem is when it reaches the last position of the first row. Does anyone know how to fix this? Thanks :)

Upvotes: 0

Views: 70

Answers (2)

A M
A M

Reputation: 15267

You made some mistakes that need to be fixed. You used std::getline to read until the next comma. It will do exactly that, even if a new line starts. So it will continue tor read until it finds the next comma. This will explain the output of

cell 0.1: test
46825

It shows "test", then the new line and then 46825.

So, this will not work. We need to use a line based approach. We will first read a complete line 46842,test and then split it. We will use std::getline to split it. But now, it will work, becuase it will extract data until the next comma or until the end of the line.

You should also never use:

while (myFile.good())

Please see 3 possible solutions:

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>

using namespace std;

int main() {
    string val;
    string arr[2][2];

    ifstream myFile;
    myFile.open("excel.csv");
    int row = 0;
    while (getline(myFile,val))
    {
        std::istringstream iss(val);
        for (int column = 0; column <= 1; column++)
        {
            getline(iss, arr[row][column], ',');
        }
        ++row;
    }
    cout << "cell 0.0: " << arr[0][0] << endl;
    cout << "cell 0.1: " << arr[0][1] << endl;
    cout << "cell 1.0: " << arr[1][0] << endl;
    cout << "cell 1.1: " << arr[1][1] << endl;

}

Next improvement

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>


int main() {

    std::string val;
    std::string arr[2][2];

    std::ifstream myFile;
    myFile.open("excel.csv");

    for (unsigned int row = 0; std::getline(myFile, val); ++row)
    {
        std::istringstream iss(val);
        for (unsigned int column = 0; column <= 1; column++)
        {
            std::getline(iss, arr[row][column], ',');
        }
    }

    std::cout << "cell 0.0: " << arr[0][0] << std::endl;
    std::cout << "cell 0.1: " << arr[0][1] << std::endl;
    std::cout << "cell 1.0: " << arr[1][0] << std::endl;
    std::cout << "cell 1.1: " << arr[1][1] << std::endl;

}

Full C++ solution:

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>

int main() {

    // Here we will store all data from our CSV file
    std::vector<std::vector<std::string>> data{};

    // Open the csv file with the source data
    std::ifstream myFile{ "excel.csv" };

    // Check, if we could open the source file
    if (myFile) {

        // We will read all lines of the source file in a for loop
        for (std::string line{}; std::getline(myFile, line); ) {

            // Stuff the line in an std::istringstream, so that we can extract data of jkust one line
            std::istringstream lineAsStream{ line };

            // The single parts of one line
            std::vector<std::string> parts{};

            for (std::string partData{}; std::getline(lineAsStream, partData, ','); parts.push_back(partData))
                ; // Empty body

            // Store new row data
            data.push_back(parts);
        }
        std::cout << "cell 0.0: " << data[0][0] << std::endl;
        std::cout << "cell 0.1: " << data[0][1] << std::endl;
        std::cout << "cell 1.0: " << data[1][0] << std::endl;
        std::cout << "cell 1.1: " << data[1][1] << std::endl;
    }
    else {
        std::cerr << "\n***Error: COuld not open source file\n";
    }
    return 0;
}

Upvotes: 1

Fernando Salviati
Fernando Salviati

Reputation: 43

This is my code atm. it prints:

    cell 0.0: 46842 
    cell 0.1: test 
    cell 1.0: 46842 
    cell 1.1: test 

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>

using namespace std;

main() {
   string arr[2][2];
   string val;
   string my_str; 
   ifstream myFile;
   myFile.open("excel.csv");   

   for(int row = 0; row <= 1; row++) {
       getline(myFile, val);
       stringstream s_stream(val);
       for(int column = 0; column <= 1; column++) {                            
           string substr;
           getline(s_stream, substr, ',');
           result.push_back(substr);
           arr[row][column] = result.at(column);
       }
   }
   cout <<"cell 0.0: " << arr[0][0] << endl;
   cout <<"cell 0.1: " << arr[0][1] << endl;
   cout <<"cell 1.0: " << arr[1][0] << endl;
   cout <<"cell 1.1: " << arr[1][1] << endl;
}

Upvotes: 0

Related Questions