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

C语言读取CSV文件时无法获取double类型评分值,返回NULL

CSV读取电影评分时Token始终为NULL的修复方案

问题背景

自定义struct movie结构体从CSV文件读取电影数据,实现按年份筛选、按年份展示最高评分、按语言筛选等功能,但提取double类型评分值时,token始终返回NULL,导致评分被设为默认值0.0,编译标准为--std=gnu99。

相关代码片段(Main.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct movie
{
    char *title;
    int year;
    char **lang;
    int numLang;
    double ratingValue;
    struct movie *next;
};

struct movie *createMovie(char *currLine)
{
    struct movie *currMovie = malloc(sizeof(struct movie));
    char *ptr;

    // 提取标题
    char *token = strtok_r(currLine, ",", &ptr);
    currMovie->title = calloc(strlen(token) + 1, sizeof(char));
    strcpy(currMovie->title, token);

    // 提取年份
    token = strtok_r(NULL, ",", &ptr);
    currMovie->year = atoi(token);

    // 提取语言(原问题代码)
    token = strtok_r(NULL, ",", &ptr);
    token = strtok_r(token, "[];", &ptr); // 复用ptr破坏逗号分割状态
    currMovie->lang = NULL;
    int numLang = 0;
    while (token != NULL)
    {
        currMovie->lang = realloc(currMovie->lang, (numLang + 1) * sizeof(char *));
        currMovie->lang[numLang] = calloc(strlen(token) + 1, sizeof(char));
        strcpy(currMovie->lang[numLang], token);
        numLang++;
        token = strtok_r(NULL, "[];", &ptr); // 继续复用ptr
    }
    currMovie->numLang = numLang;

    // 提取评分(ptr状态已破坏,无法找到正确token)
    token = strtok_r(NULL, "\n", &ptr);
    if (token != NULL)
    {
        if (sscanf(token, "%lf", &currMovie->ratingValue) != 1)
        {
            currMovie->ratingValue = 0.0;
            printf("Token: \"%s\". Invalid or missing rating value. Setting to default (0.0).\n", token);
        }
    }
    else
    {
        currMovie->ratingValue = 0.0;
        printf("Token is NULL. Invalid or missing rating value. Setting to default (0.0).\n");
    }

    currMovie->next = NULL;
    return currMovie;
}

struct movie *processFile(char *filePath)
{
    FILE *movieFile = fopen(filePath, "r");
    char *currLine = NULL;
    size_t len = 0;
    size_t nread;
    struct movie *head = NULL;
    struct movie *tail = NULL;

    while ((nread = getline(&currLine, &len, movieFile)) != -1)
    {
        struct movie *newNode = createMovie(currLine);
        if (newNode == NULL) continue;
        if (head == NULL)
        {
            head = newNode;
            tail = newNode;
        }
        else
        {
            tail->next = newNode;
            tail = newNode;
        }
    }
    free(currLine);
    fclose(movieFile);
    return head;
}

CSV文件片段

Title,Year,Languages,Rating Value
The Incredible Hulk,2008,[English;Portuguese;Spanish],6.8
Sherlock Holmes,2009,[English;French],7.6
Iron Man,2008,[English;Persian;Urdu;Arabic;Hungarian],7.9

程序输出异常

Token is NULL. Invalid or missing rating value. Setting to default (0.0).
...
Highest rated movie for each year:
2008 0.0 The Incredible Hulk
2009 0.0 Sherlock Holmes
...

问题原因

处理语言字段时,复用了分割CSV逗号的状态指针ptr。strtok_r的第三个参数用于保存当前分割状态,用同一个ptr分割语言的[];分隔符时,会破坏之前逗号分割的状态,导致后续调用strtok_r(NULL, "\n", &ptr)无法找到评分字段的token,返回NULL。

修复方案

处理语言字段时使用独立的状态指针,避免干扰原有的逗号分割状态。修改createMovie函数中的语言处理部分:

// 修复后的语言提取代码
token = strtok_r(NULL, ",", &ptr);
char *lang_ptr; // 新建独立状态指针
char *lang_token = strtok_r(token, "[];", &lang_ptr); // 用lang_ptr保存语言分割状态
currMovie->lang = NULL;
int numLang = 0;
while (lang_token != NULL)
{
    currMovie->lang = realloc(currMovie->lang, (numLang + 1) * sizeof(char *));
    currMovie->lang[numLang] = calloc(strlen(lang_token) + 1, sizeof(char));
    strcpy(currMovie->lang[numLang], lang_token);
    numLang++;
    lang_token = strtok_r(NULL, "[];", &lang_ptr); // 继续使用lang_ptr
}
currMovie->numLang = numLang;

修复后验证

修改后重新编译运行,将不再输出"Token is NULL"的提示,评分值会被正确提取。功能2的输出会变为:

Highest rated movie for each year:
2008 7.9 Iron Man
2009 7.6 Sherlock Holmes
2010 7.2 Iron Man 2
...

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 23:02:03