如何在C++中将CSV数据读取到结构体向量的指针中?
如何在C++中将CSV数据读取到结构体的向量中?
我来帮你搞定这个CSV解析的问题!你已经完成了开头读取列名的部分,现在只需要在循环里把每一行的字段解析到你的Csv结构体里,再塞进向量里就行。
核心思路是:把每一行的字符串流拆分成单个字段,将前四个字段转换成浮点数赋值给结构体的a-d成员,最后一个字段直接作为字符串赋值给e,再把这个结构体对象添加到你的向量指针指向的容器中。
修改后的完整代码如下(重点看数据读取的循环部分):
#include <vector> #include <iostream> #include <fstream> #include <string> #include <sstream> #include <stdexcept> // 可选,用于异常处理 struct Csv{ float a; float b; float c; float d; std::string e; }; int main(){ std::string colname; std::ifstream *myFile = new std::ifstream("iris.csv"); std::vector<Csv> *csv = new std::vector<Csv>; std::string line; // Read the column names if(myFile->good()) { std::getline(*myFile, line); std::stringstream ss(line); while(std::getline(ss, colname, ',')){ std::cout<<colname<<std::endl; } } // Read data, line by line while(std::getline(*myFile, line)) { std::stringstream ss(line); Csv row; // 创建一个临时结构体对象存储当前行数据 std::string field; try { // 解析第一个浮点数字段 std::getline(ss, field, ','); row.a = std::stof(field); // 解析第二个浮点数字段 std::getline(ss, field, ','); row.b = std::stof(field); // 解析第三个浮点数字段 std::getline(ss, field, ','); row.c = std::stof(field); // 解析第四个浮点数字段 std::getline(ss, field, ','); row.d = std::stof(field); // 解析最后一个字符串字段(无逗号分隔,读到行尾) std::getline(ss, field); row.e = field; // 将当前行数据加入向量 csv->push_back(row); } catch (const std::invalid_argument& e) { // 处理转换失败的情况,比如字段不是合法的浮点数 std::cerr << "Invalid data format in line: " << line << std::endl; std::cerr << "Error: " << e.what() << std::endl; continue; } catch (const std::out_of_range& e) { std::cerr << "Number out of range in line: " << line << std::endl; std::cerr << "Error: " << e.what() << std::endl; continue; } } // 可选:测试输出读取到的数据 std::cout << "\nRead " << csv->size() << " rows of data:" << std::endl; for(const auto& item : *csv) { std::cout << item.a << ", " << item.b << ", " << item.c << ", " << item.d << ", " << item.e << std::endl; } // 记得释放动态分配的内存 delete myFile; delete csv; return 0; }
几个关键细节说明:
- 用
std::getline(ss, field, ',')按逗号拆分每个字段,前四个字段通过std::stof转换成浮点数。 - 最后一个字段直接用
std::getline(ss, field),因为Iris数据集的最后一列是类别名称,没有逗号分隔,直接读取到行尾即可。 - 加入了异常处理(
try-catch块),可以处理数据格式错误的情况,避免程序崩溃。 - 最后别忘了释放你用
new分配的ifstream和vector内存,避免内存泄漏。
另外提一句:其实在C++里,除非特别需要,一般不需要用new创建这些对象,直接用栈上的对象(比如std::ifstream myFile("iris.csv");和std::vector<Csv> csv;)会更简单安全,也不用手动释放内存。不过既然你指定要用指针,上面的代码就保持了你的写法。
内容的提问来源于stack exchange,提问作者Eka
相关产品推荐
相关产品推荐

