如何对读取到struct的CSV数据按员工数列执行选择排序?代码故障求助
问题分析与代码修正
你的代码在CSV读取、排序逻辑上存在多处问题,导致无法正常运行,下面逐一指出并给出修正方案:
一、CSV读取部分的问题与修复
存在的问题:
- 循环终止条件与分隔符错误:用
!inputFile.eof()判断循环会导致最后一行重复读取;若你的CSV是Excel默认的逗号分隔格式,却用'|'作为getline终止符,会把整行拆成错误片段。 - 无意义的内部循环:
for (int i = 0; i < 1e4; i++)会反复读取同一个stringstream,导致vector插入大量重复数据。 - 字符串读取截断:用
>>读取字段时,遇到空格就停止,无法正确读取带空格的字段(比如公司名称、描述)。 - 变量命名混乱:
swimmer与业务逻辑不符,建议改为org或organization提升可读性。
修复后的读取代码:
假设CSV字段用逗号分隔,带空格的字段用双引号包裹(Excel导出标准格式),这里实现简单的CSV字段解析:
#include <vector> #include <fstream> #include <sstream> #include <string> #include <iostream> #include <algorithm> // 确保Details结构体定义正确,number_of_employees改为整数类型 struct Details { int index; std::string organization_Id; std::string name; std::string website; std::string country; std::string description; int founded; std::string industry; int number_of_employees; // 关键:用int存储员工数,而非string }; // 辅助函数:解析CSV单个字段(处理带引号的情况) std::string parseCSVField(std::stringstream& ss) { std::string field; char c; ss >> c; if (c == '"') { // 读取带引号的字段,直到下一个双引号 while (ss.get(c) && c != '"') { field += c; } // 跳过引号后的逗号 ss.ignore(); } else { // 普通字段,读取到逗号为止 ss.putback(c); std::getline(ss, field, ','); } return field; } std::vector<Details> readCSV(const std::string& filePath) { std::vector<Details> results; std::ifstream inputFile(filePath); if (!inputFile.is_open()) { std::cerr << "无法打开目标文件!" << std::endl; return results; } std::string line; // 跳过表头(如果CSV包含表头) std::getline(inputFile, line); while (std::getline(inputFile, line)) { std::stringstream ss(line); Details org; // 逐个解析字段并转换类型 org.index = std::stoi(parseCSVField(ss)); org.organization_Id = parseCSVField(ss); org.name = parseCSVField(ss); org.website = parseCSVField(ss); org.country = parseCSVField(ss); org.description = parseCSVField(ss); org.founded = std::stoi(parseCSVField(ss)); org.industry = parseCSVField(ss); org.number_of_employees = std::stoi(parseCSVField(ss)); results.push_back(org); } inputFile.close(); return results; }
二、选择排序部分的问题与修复
存在的问题:
- 数据类型错误:员工数是数值,用
string存储会导致字符串比较逻辑错误(比如"100"字符串小于"99",但数值上100更大)。 - 参数不够灵活:接受数组参数不如直接用
vector<Details>&,避免手动处理指针和大小,更安全。 - 代码可读性差:
minvalue = data[minindex = index].number_of_employees把赋值和取值写在一起,易出错。
修复后的排序代码:
void selectionSort(std::vector<Details>& data) { int size = data.size(); for (int startScan = 0; startScan < size - 1; startScan++) { int minIndex = startScan; int minValue = data[startScan].number_of_employees; for (int index = startScan + 1; index < size; index++) { if (data[index].number_of_employees < minValue) { minIndex = index; minValue = data[index].number_of_employees; } } // 直接用std::swap交换元素,简洁安全 std::swap(data[minIndex], data[startScan]); } }
三、排序后保存到新CSV
添加保存函数,将排序后的数据写入新文件:
void saveCSV(const std::vector<Details>& data, const std::string& filePath) { std::ofstream outputFile(filePath); if (!outputFile.is_open()) { std::cerr << "无法创建输出文件!" << std::endl; return; } // 写入表头 outputFile << "index,organization_id,name,website,country,description,founded,industry,number_of_employees\n"; for (const auto& org : data) { // 带空格的字段用双引号包裹,符合CSV标准 outputFile << org.index << "," << "\"" << org.organization_Id << "\"," << "\"" << org.name << "\"," << "\"" << org.website << "\"," << "\"" << org.country << "\"," << "\"" << org.description << "\"," << org.founded << "," << "\"" << org.industry << "\"," << org.number_of_employees << "\n"; } outputFile.close(); }
四、主函数调用示例
int main() { std::vector<Details> orgs = readCSV("C:/Users/Mubashra Zaman/Downloads/organizations-100.csv"); if (orgs.empty()) { std::cerr << "未读取到有效数据!" << std::endl; return 1; } selectionSort(orgs); saveCSV(orgs, "C:/Users/Mubashra Zaman/Downloads/sorted_organizations.csv"); std::cout << "排序完成并已保存到新文件!" << std::endl; return 0; }
内容的提问来源于stack exchange,提问作者Mub Malik
相关产品推荐
相关产品推荐

