C++读取复杂CSV文件遇getline匹配错误,寻求解决
C++读取CSV文件到Struct向量的问题与修复
问题概述
用C++读取.csv文件并存储到struct的vector中,小型简单文件可运行,但无法适配复杂大文件。当前遇到编译错误:error: no matching function for call to 'getline(std::string&, char)',尝试直接将输入存入vector但因操作复杂未能成功。
当前代码
#include <string> #include <fstream> #include <iomanip> #include <vector> #include <sstream> using namespace std; struct Entry { string eb, ed, ee, ef, eh, ei, ej, el, ek, em, en, er, es, et, eu, ev, ew, ex, ey, ez, ea, eg, ec, eo, ep, eq; friend ostream& operator<<(ostream& os, const Entry e); friend istream& operator>>(istream& is, Entry& e); }; Entry parse_Line(ifstream &source); bool read_File(const char*); void write_File(vector <Entry>& data); //overloading operator << and >> to be able to print out the information needed. ostream& operator<<(ostream& os, const Entry e) { os << "d: " << e.ed << " e: " << e.ee << " f: " << e.ef << " h: " << e.ei << " m: " << e.em << "\n"; return os; } istream& operator>>(istream& is, Entry& e){ getline(e.ea, ','); getline(is >> ws, e.eb, ','); getline(is >> ws, e.ec, ','); getline(is >> ws, e.ed, ','); getline(is >> ws, e.ee, ','); getline(is >> ws, e.ef, ','); getline(is >> ws, e.eg, ','); getline(is >> ws, e.eh, ','); getline(is >> ws, e.ei, ','); getline(is >> ws, e.ej, ','); getline(is >> ws, e.ek, ','); getline(is >> ws, e.el, ','); getline(is >> ws, e.em, ','); getline(is >> ws, e.en, ','); getline(is >> ws, e.eo, ','); getline(is >> ws, e.ep, ','); getline(is >> ws, e.eq, ','); getline(is >> ws, e.er, ','); getline(is >> ws, e.es, ','); getline(is >> ws, e.et, ','); getline(is >> ws, e.eu, ','); getline(is >> ws, e.ev, ','); getline(is >> ws, e.ew, ','); getline(is >> ws, e.ex, ','); getline(is >> ws, e.ey, ','); return(is >> e.ez); } Entry parse_Line(ifstream& source){ string eb, ed, ee, ef, eh, ei, ej, el, ek, em, en, er, es, et, eu, ev, ew, ex, ey, ez, ea, eg, ec, eo, ep, eq; Entry tempEntry; //scan a line from the file source >> ea >> eb >> ec >> ed >> ef >> eg >> eh >> ei >> ej >> ek >> el >> em >> en >> eo >> ep >> eq >> er >> es >> et >> eu >> ev >> ew >> ex >> ey >> ez; /*while(getline(str, word, ',')) row.push_back(word); content.push_back(row);*/ //assign data to tempEntry tempEntry.ea = ea; tempEntry.eb = eb; tempEntry.ec = ec; tempEntry.ed = ed; tempEntry.ee = ee; tempEntry.ef = ef; tempEntry.eg = eg; tempEntry.eh = eh; tempEntry.ei = ei; tempEntry.ej = ej; tempEntry.ek = ek; tempEntry.el = el; tempEntry.em = em; tempEntry.en = en; tempEntry.eo = eo; tempEntry.ep = ep; tempEntry.eq = eq; tempEntry.er = er; tempEntry.es = es; tempEntry.et = et; tempEntry.eu = eu; tempEntry.ev = ev; tempEntry.ew = ew; tempEntry.ex = ex; tempEntry.ey = ey; tempEntry.ez = ez; return tempEntry; } bool read_File(const char* fileName, vector <Entry>& allData){ //take in file name and name of struct created to store data. string line; ifstream fileInput; fileInput.open(fileName, ios::in); if (fileInput.is_open()){ // take each line, put it into the parse_Line function, then put it into the allData vector. for (Entry e; fileInput >> e; allData.push_back(move(e))); fileInput.close(); write_File(allData); return true; } else { return false; } } void write_File(vector <Entry>& data){ //use vector passed in and print it to console for now. will change to printing a new csv file for (int i=0; i<=data.size(); i++ ){ cout << data[i] << " "; } return; } int main (int argc, char* argv[]) { //check for file if (argc < 2){ return(cout << "No file name specified\n"),1; } //read in file name to a function using following: string str(argv[1]); vector <Entry> data; if (!read_File(argv[1], data)){ return(cout << "That file name is invalid\n"), 2; } const char* nameStr = str.c_str(); read_File(nameStr, data); return 0; }
输入文件示例
3902,string1,3,string two,string three,string 4,string five,230,string 6,string seven,string 8,string nine,stringten,string11,string12,string13,43,34,89,string 14,string 15,string 16,string 17,string eighteen,string nineteen,string twenty,string twenty one,string 22
92,b,324,c,d,e,f,g,h,i,j,k,l,m,n,43l,93403,392,r,s,t,u,v,w,x,y,z
问题分析与修复
1. 编译错误根源
getline(e.ea, ',')调用错误:std::getline的第一个参数必须是istream对象,不能直接传string。正确写法应为getline(is >> ws, e.ea, ',')。
2. CSV字段读取问题
parse_Line函数中用>>运算符读取会被空格截断,无法处理包含空格的CSV字段(如示例中的string two)。operator>>中最后用is >> e.ez同样会被空格/换行截断,应改为getline(is >> ws, e.ez)(读取到行末)。
3. 其他逻辑错误
write_File中循环条件i<=data.size()会导致越界访问,应改为i < data.size()。main函数中重复调用read_File,会导致数据被重复读取存入vector。- 需确保CSV的字段数量与
Entry结构体的成员数量完全匹配,否则会出现读取错位。
修复后的代码
#include <string> #include <fstream> #include <iomanip> #include <vector> #include <sstream> #include <iostream> using namespace std; struct Entry { string ea, eb, ec, ed, ee, ef, eg, eh, ei, ej, ek, el, em, en, eo, ep, eq, er, es, et, eu, ev, ew, ex, ey, ez; friend ostream& operator<<(ostream& os, const Entry& e); friend istream& operator>>(istream& is, Entry& e); }; bool read_File(const char* fileName, vector<Entry>& allData); void write_File(const vector<Entry>& data); ostream& operator<<(ostream& os, const Entry& e) { os << "d: " << e.ed << " e: " << e.ee << " f: " << e.ef << " h: " << e.ei << " m: " << e.em << "\n"; return os; } istream& operator>>(istream& is, Entry& e){ // 按顺序读取所有字段,处理带空格的内容 getline(is >> ws, e.ea, ','); getline(is >> ws, e.eb, ','); getline(is >> ws, e.ec, ','); getline(is >> ws, e.ed, ','); getline(is >> ws, e.ee, ','); getline(is >> ws, e.ef, ','); getline(is >> ws, e.eg, ','); getline(is >> ws, e.eh, ','); getline(is >> ws, e.ei, ','); getline(is >> ws, e.ej, ','); getline(is >> ws, e.ek, ','); getline(is >> ws, e.el, ','); getline(is >> ws, e.em, ','); getline(is >> ws, e.en, ','); getline(is >> ws, e.eo, ','); getline(is >> ws, e.ep, ','); getline(is >> ws, e.eq, ','); getline(is >> ws, e.er, ','); getline(is >> ws, e.es, ','); getline(is >> ws, e.et, ','); getline(is >> ws, e.eu, ','); getline(is >> ws, e.ev, ','); getline(is >> ws, e.ew, ','); getline(is >> ws, e.ex, ','); getline(is >> ws, e.ey, ','); // 最后一个字段读取到行末 getline(is >> ws, e.ez); return is; } bool read_File(const char* fileName, vector<Entry>& allData){ ifstream fileInput(fileName); if (!fileInput.is_open()){ return false; } Entry e; // 逐行读取解析 string line; while (getline(fileInput, line)) { istringstream iss(line); if (iss >> e) { allData.push_back(e); } } fileInput.close(); write_File(allData); return true; } void write_File(const vector<Entry>& data){ for (size_t i = 0; i < data.size(); ++i ){ cout << data[i]; } } int main (int argc, char* argv[]) { if (argc < 2){ cout << "No file name specified\n"; return 1; } vector<Entry> data; if (!read_File(argv[1], data)){ cout << "That file name is invalid\n"; return 2; } return 0; }
优化说明
- 调整
Entry成员顺序,与CSV字段顺序对应,避免读取错位。 - 改用
istringstream逐行解析CSV,确保每行数据独立处理,适配大文件。 - 修复
getline调用错误、循环越界、重复读取等问题。 - 传递
Entry对象时使用引用,减少拷贝开销。
内容的提问来源于stack exchange,提问作者pnwdino
相关产品推荐
相关产品推荐

