I want to write a generic function to parse CSV files. My code acts very strange as it never stops and repeats the first line forever. What am I doing wrong here?
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
std::vector<std::vector<std::string>> parseCsvFile(std::string_view source,
char valueSeparator) {
auto reult = std::vector<std::vector<std::string>>();
for(std::string line;
std::getline(std::istringstream(source.data()), line);
/* emoty cond */) {
std::istringstream stream(line);
std::string token;
while(std::getline(stream, token, valueSeparator)) { // never ends
// debug
std::cout << token << "\n" << std::endl;
// push to vector
}
}
return reult;
}
void test() {
auto testData = std::string("a,b,c,d\r\ne,f,g,h\r\n");
const auto data = parseCsvFile(testData, ','); // Never ends
}
The problem is with the for
loop:
for(std::string line;
std::getline(std::istringstream(source.data()), line);
/* emoty cond */)
The expression std::istringstream(source.data())
creates a brand new istringstream
object from scratch each iteration of the loop. You never get beyond the first line in the input string source
.
You need to create the string stream before the loop, and then use it in the loop:
std::istringstream source_stream(source.data());
for(std::string line;
std::getline(source_stream, line);
/* emoty cond */)
On a different note: The term "cond" means a "condition". And the condition isn't empty, it's the third "expression" clause that's empty. The condition is the std::getline
call.