问题
Sorry if it's just pure stupidity but I'm stuck at a file reading problem via C++. This is the CSV data that I'd like to read:
5;1;0;3;3;5;5;3;3;3;3;2;3;3;0
5;1;0;3;3;5;0;3;3;3;3;2;0;0;3
5;1;1;3;3;0;0;0;0;3;5;2;3;3;3
0;3;5;5;0;2;0;3;3;0;5;1;1;0;0
0;0;3;5;5;2;0;0;0;0;5;5;1;1;0
0;0;0;0;5;2;0;0;0;0;0;5;5;1;0
;;;;;;;;;;;;;;
Code;Bezeichnung;Kosten;;;;;;;;;;;;
0;Ebene;6;;;;;;;;;;;;
1;Fluss;10; (begrenzt nutzbar);;;;;;;;;;;
2;Weg;2;;;;;;;;;;;;
3;Wald;8;;;;;;;;;;;;
4;Brücke;5;;;;;;;;;;;;
5;Felswand;12;;;;;;;;;;;;
here, I'd like to read the first values (separated by ;;;;) and store it in a 2 dimensional array. Which would not be a problem if it was seperated completely by ';'. But if use
while (getline(csvread, s, ';'))
{
[...]
}
I get information like this: {5}{1}{0}{3}{3}{5}{5}{3}{3}{3}{3}{2}{3}{3}{0\n5}{1}
so it basically saves the newline and does not think of it as delimitator.
So is there an option to use getline even if you have two delimitators? Or am I completely off? I also thought about reading it line by line to a string, adding a ; to the string and rewriting it in a file in order to reuse getline using ;. But this can't seriously be the best option, right?
回答1:
you can use a splitting function like :
std::vector<std::string> split(const std::string& source, const std::string& delimiter){
std::vector<std::string> result;
size_t last = 0;
size_t next = 0;
while ((next = source.find(delimiter, last)) != std::string::npos){
result.push_back(source.substr(last, next - last));
last = next + delimiter.length();
}
result.push_back(source.substr(last));
return result;
}
now simply:
std::vector<std::vector<std::string>> parsedCSV;
while (getline(csvread, s, '\n'))
{
parsedCSV.push_back(split(s,";"));
}
回答2:
You should do the '\n'
and ';'
splitting separately:
while (getline(csvread, line, ';'))
{
// in here, split line by ;
std::vector<std::string> elems;
boost::split(elems, line, boost::is_any_of(";"));
// do something with elems
}
回答3:
I recently had to read csv-data as well and stumbled upon the same 'problem'. Here's what I did:
- Read in a full line with
getline(csvread, s)
, this will read up to the first newline. - Split the string on every occurence of
;
, I've used this StackOverflow answer as inspiration to split a string, the code is also listed below.
I didn't care much for performance as I only had to run this program once, I won't comment on the speed of this workaround.
Good luck!
Edit: apparently Boost offers code to split a string, that might be cleaner, consider the code below if you want to avoid Boost.
#include <string>
#include <sstream>
#include <vector>
// source: https://stackoverflow.com/a/236803/4841248
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
split(s, delim, elems);
return elems;
}
回答4:
try something like this:
std::vector<std::string> cells;
while (getline(csvread, s) ){
boost::split(cells, s, boost::is_any_of(";"));
....
}
来源:https://stackoverflow.com/questions/30171443/c-read-csv-file-separated-by-and-n