You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:42:36