I am reading a CSV file and storing it in vector vector string. I want to print the data and for that I am using two for loops one iterating over vector of vector and other iterating over the vector string.
a1,b1,c1,d1
a1,b1,c4,d3
a1,b2,c2,d2
a2,b3,c3,d4
a2,b4,c3,d4
this is the CSV data I am reading. Below code I am using to print it to screen
void ReadCSV::printdata(vector<vector<string>> ipd){
for(auto it1 = ipd.begin();it1 != ipd.end();++it1){
vector<string> test = *it1;
for(auto it2 = test.begin();it2 != test.end();++it2){
string r = "";
r= *it2;
cout<<r<<" ";
}
cout<<endl;
}
}
But the output I am getting seems is not iterating properly:
a1 b1 c1 d1
a1 b1 c1 d1 a1 b1 c4 d3
a1 b1 c1 d1 a1 b1 c4 d3 a1 b2 c2 d2
a1 b1 c1 d1 a1 b1 c4 d3 a1 b2 c2 d2 a2 b3 c3 d4
a1 b1 c1 d1 a1 b1 c4 d3 a1 b2 c2 d2 a2 b3 c3 d4 a2 b4 c3 d4
I used below code to read data:
vector<vector<string>> ReadCSV:: ReadData(){
fstream fin(filename);
vector<string> temp;
string val1, val2, val3 ,val4;
if(!fin.is_open()){
cout<<"ERROR: file open";
}
cout<<"FIRST OUTPUT: "<<endl;
while(fin.good()){
getline(fin, val1,',');
//store
temp.push_back(val1);
cout<<val1<<" ";
getline(fin, val2,',');
temp.push_back(val2);
cout<<val2<<" ";
getline(fin, val3,',');
temp.push_back(val3);
cout<<val3<<" ";
getline(fin, val4,'\n');
temp.push_back(val4);
cout<<val4<<" ";
csvdata.push_back(temp);
}
cout<<endl;
return csvdata;
}
Can anyone tell where I am going wrong, other issue I face is when I run debugger (ECLIPSE IDE) and hover over a variable it opens up some popup but doesn't displays the value of the variable, such as "string r" in this case. thanks
Your CSV reader besides having some minor issues is hard-coded to read exactly 4 comma separated values. Here is a more general code which can read as many lines and with each line having variable number of comma separated values.
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
#include <algorithm>
template<typename In, typename Out>
void csv2vec(In first, In last, Out& result) {
std::string temp;
unsigned i{0};
while(1) {
do{
if(*first == '\n') break;
temp.push_back(*first);
++first;
}while(*first != ',' && first != last);
result[i].push_back(temp);
if(*first == '\n') {
++i;
result.resize(i+1);
}
temp.clear();
if(first == last) break;
++first;
}
}
int main(void) {
std::vector<std::vector<std::string>> vec(1);
std::ifstream in("data.txt");
std::istreambuf_iterator<char> begin(in);
std::istreambuf_iterator<char> end;
csv2vec(begin,end,vec);
for(const auto& vecouter : vec) {
for(const auto& elem : vecouter){
std::cout<<elem<<" ";
}
std::cout<<"\n";
}
return 0;
}
Note: I have used istreambuf_iterator which never skips any characters (including whitespaces such as '\n'). It grabs whatever's next in the stream buffer unlike istream_iterator which skips whitespaces. Also istream_iterator is useful when performing formatted input and is slower than the istreambuf_iterator. Reference: Item 29, Effective STL, Scott Meyers.