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

C语言实现CSV地震数据筛选遇问题,求筛选逻辑及代码修正

地震数据CSV筛选代码修正与逻辑说明

我有一份存储地震数据的CSV文件,想要实现让用户按日期范围、城市、区域、里氏震级筛选数据并打印结果的功能。已经定义了结构体,尝试用strtok处理CSV的逗号分隔,但代码报错多,也没理清筛选逻辑。附上问题代码和CSV文件截图,求修正代码并明确筛选逻辑。

问题代码(原始错误版本)

int sorgu(){

    FILE *fp;  //dosya pointer'ı

    fp = fopen("/Users/Desktop/earthquake.csv" , "r");

    int val=0;
    int min=0;
    int max=0;
    char *sp;  //string pointer
    char line[LINE];
    int filtre=0;
    struct earthquake;

    printf("***For which element do you want to filter?***
");
    printf("PRESS 1 FOR DATE RANGE.
");
    printf("PRESS 2 FOR CITY.
");
    printf("PRESS 3 FOR DISTRICT.
");
    printf("PRESS 4 FOR RICHTER VALUE.
");
    scanf("%d" , &val);

    switch(filtre){

        case 1:
        printf("Enter the lower value for year.");
        scanf("%d" , &min);
        printf("Enter the upper value for year.");
        scanf("%d" , &max);

        while(fgets(line, LINE, fp) != NULL){

            sp=strtok(line, ",");  //string başından ilk virgülü görene kadar
            struct earthquake.id = atoi(sp);  //id değerini int değere çevirip earthquake.id'ye atar

            sp=strtok(NULL, ",");  //kaldığı virgülden itibaren diğer virgüle kadar
            strcpy(earthquake.date, sp);  //sp'yi earthquake.date'e kopyalar

           if(min<=date.upLimit && max>=date.topLimit){
               printf("Earthquakes in the range you specify: 
" , );
           }
        }



    }



    fclose(fp); 
}

CSV文件截图

地震数据CSV截图


修正后的完整代码

#define LINE 1024

// 匹配CSV列的结构体定义
struct earthquake {
    int id;
    char date[20];
    char time[20];
    double latitude;
    double longitude;
    double depth;
    double magnitude;
    char city[50];
    char district[50];
};

int sorgu(){
    FILE *fp;
    int val = 0;
    int min_year = 0, max_year = 0;
    char *sp;
    char line[LINE];
    struct earthquake eq;
    char filter_str[50];
    double min_mag = 0, max_mag = 0;

    // 文件打开错误检查
    fp = fopen("/Users/Desktop/earthquake.csv", "r");
    if (fp == NULL) {
        printf("无法打开文件!\n");
        return -1;
    }

    printf("***请选择筛选条件***\n");
    printf("1 - 日期范围(按年份筛选)\n");
    printf("2 - 城市\n");
    printf("3 - 区域\n");
    printf("4 - 里氏震级\n");
    scanf("%d", &val);
    getchar(); // 吸收输入后的换行符

    // 跳过CSV表头行
    fgets(line, LINE, fp);

    switch(val) {
        case 1:
            printf("请输入起始年份:");
            scanf("%d", &min_year);
            printf("请输入结束年份:");
            scanf("%d", &max_year);
            getchar();

            printf("您指定范围内的地震数据:\n");
            while(fgets(line, LINE, fp) != NULL) {
                sp = strtok(line, ",");
                eq.id = atoi(sp);

                sp = strtok(NULL, ",");
                strcpy(eq.date, sp);

                // 从DD.MM.YYYY格式中提取年份
                char *year_str = strrchr(eq.date, '.') + 1;
                int year = atoi(year_str);

                if (year >= min_year && year <= max_year) {
                    printf("%s", line);
                }
            }
            break;

        case 2:
            printf("请输入要筛选的城市名称:");
            fgets(filter_str, sizeof(filter_str), stdin);
            filter_str[strcspn(filter_str, "\n")] = '\0'; // 去掉换行符

            printf("匹配该城市的地震数据:\n");
            while(fgets(line, LINE, fp) != NULL) {
                // 跳过前7列,定位到城市列
                sp = strtok(line, ",");
                for(int i=0; i<7; i++) {
                    sp = strtok(NULL, ",");
                }
                strcpy(eq.city, sp);

                if (strcmp(eq.city, filter_str) == 0) {
                    printf("%s", line);
                }
            }
            break;

        case 3:
            printf("请输入要筛选的区域名称:");
            fgets(filter_str, sizeof(filter_str), stdin);
            filter_str[strcspn(filter_str, "\n")] = '\0';

            printf("匹配该区域的地震数据:\n");
            while(fgets(line, LINE, fp) != NULL) {
                // 跳过前8列,定位到区域列
                sp = strtok(line, ",");
                for(int i=0; i<8; i++) {
                    sp = strtok(NULL, ",");
                }
                strcpy(eq.district, sp);

                if (strcmp(eq.district, filter_str) == 0) {
                    printf("%s", line);
                }
            }
            break;

        case 4:
            printf("请输入最小震级:");
            scanf("%lf", &min_mag);
            printf("请输入最大震级:");
            scanf("%lf", &max_mag);
            getchar();

            printf("震级范围内的地震数据:\n");
            while(fgets(line, LINE, fp) != NULL) {
                // 跳过前6列,定位到震级列
                sp = strtok(line, ",");
                for(int i=0; i<6; i++) {
                    sp = strtok(NULL, ",");
                }
                eq.magnitude = atof(sp);

                if (eq.magnitude >= min_mag && eq.magnitude <= max_mag) {
                    printf("%s", line);
                }
            }
            break;

        default:
            printf("无效的选择!\n");
            break;
    }

    fclose(fp);
    return 0;
}

核心修正点与筛选逻辑说明

代码修正点

  1. 结构体使用修正:补充完整结构体定义,定义结构体变量eq,通过变量正确访问成员
  2. 文件操作修正:增加fopen失败的错误判断,避免空指针操作;跳过CSV表头行,避免处理标题数据
  3. 分支变量修正:switch使用用户输入的val而非未赋值的filtre
  4. 输入处理修正:用getchar()吸收换行符,避免fgets读取空行;对用户输入的字符串去掉换行符
  5. 格式错误修正:修复printf的无效格式问题,改为直接打印匹配的CSV行

筛选逻辑说明

  • 日期范围筛选:从CSV的日期字符串(格式DD.MM.YYYY)中提取年份,转为整数后与用户输入的起止年份比较,保留年份在区间内的数据
  • 城市/区域筛选:定位到CSV对应的城市/区域列,将列字符串与用户输入的关键词做精确匹配(如需模糊匹配可改用strstr函数),保留匹配成功的数据
  • 里氏震级筛选:将CSV的震级列转为浮点数,与用户输入的震级区间比较,保留震级在区间内的数据

内容的提问来源于stack exchange,提问作者keeprunnin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 10:20:25