C++ CSV文件读取项目求助:赛事数据排序与距离查询功能故障
解决游泳赛事CSV数据的读取、排序与查询问题
Hey there! Let's work through this C++ project issue together. Handling CSV data for swimming events and getting the sorting right is totally doable—let's break down the steps to fix your time-sorting problem and build out all the required features.
第一步:用结构体替代动态二维数组(更易维护)
首先,别用动态二维数组了,用一个struct来封装选手数据会清晰太多。这样你不用记哪个索引对应姓名/时间/距离,代码可读性拉满:
#include <iostream> #include <vector> #include <fstream> #include <sstream> #include <algorithm> #include <string> // 定义选手数据结构体 struct Swimmer { std::string name; double timeInSeconds; // 把时间转换成秒数,方便排序和比较 int distance; // 参赛距离,比如50/100/200米 };
这里关键是把时间转换成数值类型(秒)——这大概率是你之前按时间排序失败的原因!如果直接存时间字符串(比如"01:23.45"),字符串排序会按字符顺序来,完全不符合实际时间的大小逻辑。
第二步:读取CSV文件到vector
接下来写一个函数读取CSV,处理每一行的字段分割,并且把时间字符串转换成秒数:
// 把时间字符串(如"mm:ss.cc")转换成秒数 double convertTimeToSeconds(const std::string& timeStr) { size_t colonPos = timeStr.find(':'); size_t dotPos = timeStr.find('.'); int minutes = std::stoi(timeStr.substr(0, colonPos)); int seconds = std::stoi(timeStr.substr(colonPos + 1, dotPos - colonPos - 1)); int centiseconds = std::stoi(timeStr.substr(dotPos + 1)); return minutes * 60 + seconds + centiseconds / 100.0; } // 读取CSV文件到vector std::vector<Swimmer> readSwimmingCSV(const std::string& filePath) { std::vector<Swimmer> swimmers; std::ifstream file(filePath); std::string line; // 跳过表头(如果CSV有表头的话) std::getline(file, line); while (std::getline(file, line)) { std::stringstream ss(line); std::string token; Swimmer s; // 读取姓名(假设第一个字段是姓名) std::getline(ss, token, ','); s.name = token; // 读取时间字符串,转换成秒数 std::getline(ss, token, ','); s.timeInSeconds = convertTimeToSeconds(token); // 读取参赛距离 std::getline(ss, token, ','); s.distance = std::stoi(token); swimmers.push_back(s); } return swimmers; }
第三步:实现按时间和距离排序
现在排序就简单了!用std::sort配合自定义比较器,完全解决你之前的时间排序问题:
按时间升序排序(最快在前)
void sortByTime(std::vector<Swimmer>& swimmers) { std::sort(swimmers.begin(), swimmers.end(), [](const Swimmer& a, const Swimmer& b) { return a.timeInSeconds < b.timeInSeconds; // 升序,最快的在前面 }); }
按距离排序(可搭配时间二次排序)
如果要先按距离分组,再按时间排序:
void sortByDistanceThenTime(std::vector<Swimmer>& swimmers) { std::sort(swimmers.begin(), swimmers.end(), [](const Swimmer& a, const Swimmer& b) { if (a.distance != b.distance) { return a.distance < b.distance; // 先按距离升序 } return a.timeInSeconds < b.timeInSeconds; // 同距离按时间升序 }); }
第四步:按距离查询最快成绩
可以写一个函数遍历vector,找到对应距离的最小时间;如果数据量很大,也可以提前用std::map缓存每个距离的最快成绩,提高查询效率:
单次查询版本
Swimmer findFastestByDistance(const std::vector<Swimmer>& swimmers, int targetDistance) { Swimmer fastest; fastest.timeInSeconds = 1e9; // 初始设一个很大的时间 for (const auto& s : swimmers) { if (s.distance == targetDistance && s.timeInSeconds < fastest.timeInSeconds) { fastest = s; } } return fastest; }
预缓存版本(适合多次查询)
#include <map> std::map<int, Swimmer> buildFastestByDistanceMap(const std::vector<Swimmer>& swimmers) { std::map<int, Swimmer> fastestMap; for (const auto& s : swimmers) { auto it = fastestMap.find(s.distance); if (it == fastestMap.end() || s.timeInSeconds < it->second.timeInSeconds) { fastestMap[s.distance] = s; } } return fastestMap; }
测试示例
最后写个主函数测试一下:
int main() { // 读取CSV auto swimmers = readSwimmingCSV("swimming_events.csv"); // 按时间排序 sortByTime(swimmers); std::cout << "按时间排序结果:\n"; for (const auto& s : swimmers) { std::cout << s.name << " | " << s.timeInSeconds << "秒 | " << s.distance << "米\n"; } // 查询100米最快成绩 auto fastest100 = findFastestByDistance(swimmers, 100); std::cout << "\n100米最快成绩:\n" << fastest100.name << " | " << fastest100.timeInSeconds << "秒\n"; return 0; }
你之前排序失败的常见原因排查
- 直接用字符串比较时间:比如"02:00.00"字符串比"01:59.99"大,但实际时间更长,字符串排序会搞反顺序,转换成数值就解决了。
- 比较器逻辑写反:如果用了
>而不是<,就会按降序排列,最快的在后面。 - 数据类型不匹配:比如把时间存在
string里,没有转换成数值类型,导致比较逻辑错误。
内容的提问来源于stack exchange,提问作者baddoh
相关产品推荐
相关产品推荐

