Reputation: 68
There are many options of csv to vector, including read a csv file and and add its all data into vector in c++ however I want to something a bit above or below csv -> vector
. Instead, I have a CURL function that loads csv data into a std::string
in the format of
col1,col2,col3
abc,2,ghi
jkl,2,pqr
which, each row is separated by \n
. How can I parse data in this given structure into a std::vector<data>
Where data would look something like
struct data
{
std::string col1, col3;
int col2;
};
Upvotes: 2
Views: 718
Reputation: 2937
If it is only parser you need to crate in your application, you can build some simple streaming recursive parser like this:
#include <cctype>
#include <cstring>
#include <vector>
#include <string>
#include <iostream>
struct data
{
std::string col1;
int col2;
std::string col3;
};
std::ostream& operator<<(std::ostream& to,const data& d)
{
to << d.col1 << ',';
to << d.col2 << ',';
to << d.col3;
return to;
}
static char* skip_spaces(const char* csv)
{
constexpr const char* WHITESPACE = "\t\n\v\f\r ";
return const_cast<char*>( csv + std::strspn(csv,WHITESPACE) );
}
static const char* parse_csv_line(const char* csv, data& to)
{
char* b = skip_spaces(csv);
char* e = std::strchr(b,',');
to.col1 = std::string(b,e);
b = skip_spaces(e+1);
e = std::strchr(b,',');
to.col2 = std::strtol(b,&e,10);
b = skip_spaces(e+1);
e = std::strchr(b,'\n');
if(nullptr == e) {
e = b + std::strlen(b);
}
to.col3 = std::string(b,e);
return ('\0' == *e) ? nullptr : e + 1;
}
std::vector<data> parse_csv(const char* csv)
{
std::vector<data> ret;
// skip header
csv = std::strchr(csv,'\n');
while(nullptr != csv) {
data next;
csv = parse_csv_line(csv, next);
ret.push_back( next );
}
return ret;
}
int main(int argc, const char** argv)
{
const char* CSV = "col1,col2,col3,\r\nabc,2,ghi\r\njkl,2,pqr";
std::vector<data> parsed = parse_csv(CSV);
for(auto d: parsed) {
std::cout << d << std::endl;
}
return 0;
}
If you need something much more complex, i.e. handling errors etc use some CSV parsing library
Upvotes: 4