Yaksha
Yaksha

Reputation: 153

C++ Parsing a CSV file into vector of vectors: Loosing string 1st character

I am reading a CSV file into vector of string vectors. I have written code below.

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

using namespace std;

int main()
{
    ifstream mesh;
    mesh.open("mesh_reference.csv");

    vector<vector<string> > point_coordinates;
    string line, word;

    while (getline(mesh,line))
    {
        stringstream ss(line);
        vector<string> row;
        while (getline(ss, word, ','))
        {
            row.push_back(word);
        }
        point_coordinates.push_back(row);
    }

    for(int i=0; i<point_coordinates.size(); i++) 
    {
        for(int j=0; j<3; j++)
            cout<<point_coordinates[i][j]<<" ";
        cout<<endl;
    }
    return 0;
}

When I print out the vector of vectors, I see that I am loosing the first character of Element at 0 position in the vector row. Basically, point_coordinates[0][0] is displaying 0.0001 while the string is supposed to be -0.0001. I am not able to understand the reason for the same. Kindly help.

A typical output line is

 .0131 -0.019430324 0.051801

Whereas the CSV data is

0.0131,-0.019430324,0.051801

SAMPLE CSV DATA FROM FILE

    NODES__X,NODES__Y,NODES__Z
    0.0131,-0.019430324,0.051801
    0.0131,-0.019430324,0.06699588
    0.0131,-0.018630324,0.06699588
    0.0131,-0.018630324,0.051801
    0.0131,-0.017630324,0.050801
    0.0131,-0.017630324,0.050001
    0.0149,-0.017630324,0.050001
    0.0149,-0.019430324,0.051801

Upvotes: 1

Views: 2964

Answers (1)

A M
A M

Reputation: 15265

Although the problem is already solved, I would like to show you a solution using some modern C++ algorithms and eliminating minor issues.

  • Do not use using namespace std;. You should not do this
  • Ne need for a separate file.open. The std::ifstream constructor will open the file for you. And the destructor will close it
  • Check if the file could be opened. The ifstreams ! operator is overloaded. So you can do a boolean check
  • Do not use int in for loops where you compare against .size(). Use ````size_t instead
  • Always initialize all variables, even if there is an assignement in the next line
  • For tokenizing you should use std::sregex_token_iterator. It has exactly been designed for this purpose
  • In modern C++ you are encouraged to use algorithms

Please see an improved version of your code below:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <regex>

const std::regex comma(",");

int main()
{
    // Open source file.
    std::ifstream mesh("r:\\mesh_reference.csv");

    // Here we will store the result
    std::vector<std::vector<std::string>> point_coordinates;

    // We want to read all lines of the file
    std::string line{};
    while (mesh && getline(mesh, line)) {
        // Tokenize the line and store result in vector. Use range constructor of std::vector
        std::vector<std::string> row{ std::sregex_token_iterator(line.begin(),line.end(),comma,-1), std::sregex_token_iterator() };
        point_coordinates.push_back(row);
    }
    // Print result. Go through all lines and then copy line elements to std::cout
    std::for_each(point_coordinates.begin(), point_coordinates.end(), [](std::vector<std::string> & vs) {
        std::copy(vs.begin(), vs.end(), std::ostream_iterator<std::string>(std::cout, " ")); std::cout << "\n"; });

    return 0;
}

Please consider, if you may want to use such an approach in the future

Upvotes: 5

Related Questions