代码之家  ›  专栏  ›  技术社区  ›  Domanik Logan

试图从csv文件中获取双值,在C中始终为NULL

csv c
  •  2
  • Domanik Logan  · 技术社区  · 1 年前

    我需要一个 double 我的价值 Movie 结构。所以我的任务是从csv文件中读取(它将被提供),并输出某些信息,比如什么电影是用这种语言制作的,或者今年上映的电影,或者当年收视率最高的电影。无论如何。我遇到的问题是,当我有我的“令牌”时,尝试检索它作为NULL返回的值。

    主要的c 文件:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct movie
    {
        char *title;
        int year;
        char **lang;
        int numLang; // New variable to store the number of languages
        double ratingValue;
        struct movie *next;
    };
    
    /* Parse the curr line which is "," broken and create a movie struct with the data in curr line
    */
    struct movie *createMovie(char *currLine)
    {
        struct movie *currMovie = malloc(sizeof(struct movie));
        char *ptr;
    
        // title
        char *token = strtok_r(currLine, ",", &ptr);
        currMovie->title = calloc(strlen(token) + 1, sizeof(char));
        strcpy(currMovie->title, token);
    
        // year
        token = strtok_r(NULL, ",", &ptr);
        currMovie->year = atoi(token);
    
        // language
        token = strtok_r(NULL, ",", &ptr);
        token = strtok_r(token, "[];", &ptr);
        currMovie->lang = NULL; // Initialize to NULL
        int numLang = 0; // Initialize numLang
        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);
        }
    
        // Set numLang for the current movie
        currMovie->numLang = numLang;
    
        // rating value
        token = strtok_r(NULL, "\n", &ptr);
        if (token != NULL)  // Check if token is not NULL
        {
            // Use sscanf to directly extract the rating value as a float
            if (sscanf(token, "%lf", &currMovie->ratingValue) != 1)
            {
                // Handle the case where the conversion fails
                currMovie->ratingValue = 0.0;
                printf("Token: \"%s\". Invalid or missing rating value. Setting to default (0.0).\n", token);
            }
        }
        else
        {
            // Handle the case where the rating value is missing or invalid
            // For example, set it to a default value or display an error message.
            currMovie->ratingValue = 0.0;
            printf("Token is NULL. Invalid or missing rating value. Setting to default (0.0).\n");
        }
    
        // Set the next node to NULL
        currMovie->next = NULL;
    
        return currMovie;
    }
    
    /*
    * Return linked list of movies by parsing data from each line
    */
    struct movie *processFile(char *filePath)
    {
        // open file
        FILE *movieFile = fopen(filePath, "r");
    
        char *currLine = NULL;
        size_t len = 0;
        size_t nread;
    
        struct movie *head = NULL;
        struct movie *tail = NULL;
    
        // read file
        while ((nread = getline(&currLine, &len, movieFile)) != -1)
        {
            // Get new movie
            struct movie *newNode = createMovie(currLine);
    
            // Skip the header line
            if (newNode == NULL)
            {
                continue;
            }
    
            // id first node
            if (head == NULL)
            {
                // first node in the linked link, Set head and tail to node
                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
    Iron Man 2,2010,[English;French;Russian],7.2
    Iron Man 3,2013,[English],7.2
    Thor: Ragnarok,2017,[English],7.9
    The Avengers,2012,[English;Russian;Hindi],8.1
    Doctor Strange,2016,[English],7.5
    Avengers: Infinity War,2018,[English],8.5
    Avengers: Age of Ultron,2015,[English;Korean],7.4
    Thor,2011,[English],7
    Thor: The Dark World,2013,[English],7
    

    正如您在csv文件中看到的,在“评级值”之后,它移动到新行。问题是,当我制作电影“列表”时,我需要检索“评级值”。我正在使用编译 --std=gnu99 这是一个系统要求。我需要从中得到双倍的价值,如果能得到任何帮助,我将不胜感激。

    编辑这是我的输出

    flip3 ~/os1 998$ ./movies movies_sample_1.csv
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    Token is NULL. Invalid or missing rating value. Setting to default (0.0).
    
    1. Show movies released in the specified year
    2. Show highest rated movie for each year
    3. Show the title and year of release of all movies in a specific language
    4. Exit from the program
    
    Enter a choice from 1 to 4: 1
    Enter the year for which you want to see movies: 2008
    The Incredible Hulk
    Iron Man
    
    1. Show movies released in the specified year
    2. Show highest rated movie for each year
    3. Show the title and year of release of all movies in a specific language
    4. Exit from the program
    
    Enter a choice from 1 to 4: 2
    
    Highest rated movie for each year:
    0 0.0 Title
    2008 0.0 The Incredible Hulk
    2009 0.0 Sherlock Holmes
    2010 0.0 Iron Man 2
    2013 0.0 Iron Man 3
    2017 0.0 Thor: Ragnarok
    2012 0.0 The Avengers
    2016 0.0 Doctor Strange
    2018 0.0 Avengers: Infinity War
    2015 0.0 Avengers: Age of Ultron
    2011 0.0 Thor
    2014 0.0 Captain America: The Winter Soldier
    2003 0.0 Right on Track
    
    1. Show movies released in the specified year
    2. Show highest rated movie for each year
    3. Show the title and year of release of all movies in a specific language
    4. Exit from the program
    
    Enter a choice from 1 to 4: 3
    Enter the language for which you want to see movies: English
    2008 The Incredible Hulk
    2009 Sherlock Holmes
    2008 Iron Man
    2010 Iron Man 2
    2013 Iron Man 3
    2017 Thor: Ragnarok
    2012 The Avengers
    2016 Doctor Strange
    2018 Avengers: Infinity War
    2015 Avengers: Age of Ultron
    2011 Thor
    2013 Thor: The Dark World
    2017 Spider-Man: Homecoming
    2011 Captain America: The First Avenger
    2016 Captain America: Civil War
    2015 Ant-Man
    2014 Captain America: The Winter Soldier
    2018 Mary Queen of Scots
    2016 Revolting Rhymes Part One
    2017 The Glass Castle
    2016 Free Fire
    2003 Right on Track
    2012 Rise of the Guardians
    2012 Anna Karenina
    
    1. Show movies released in the specified year
    2. Show highest rated movie for each year
    3. Show the title and year of release of all movies in a specific language
    4. Exit from the program
    
    Enter a choice from 1 to 4: 4
    Exiting the program
    
    2 回复  |  直到 1 年前
        1
  •  2
  •   chqrlie    1 年前

    代码中存在多个问题:

    • 您使用相同的状态指针 ptr 以解析语言字段中的标记并查找封闭行。您应该使用两个独立的状态指针。这解释了报告的行为。

    • 使用 strdup 以分配字符串的副本。这只是一种简化。

    • 的类型 nread 应该是 ssize_t .

    • 要跳过标题行,只需读取并丢弃文件中的第一行即可。

    以下是修改后的版本:

    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct movie {
        char *title;
        int year;
        char **lang;
        int numLang; // New variable to store the number of languages
        double ratingValue;
        struct movie *next;
    };
    
    /* Parse the curr line which is "," broken and create a movie struct with the data in curr line
     */
    struct movie *createMovie(char *currLine)
    {
        struct movie *currMovie = malloc(sizeof(struct movie));
        if (!currMovie)
            return NULL;
    
        char *ptr;
        // title
        char *token = strtok_r(currLine, ",", &ptr);
        currMovie->title = strdup(token ? token : "");
    
        // year
        token = strtok_r(NULL, ",", &ptr);
        currMovie->year = token ? atoi(token) : 0;
    
        // language
        currMovie->lang = NULL;
        currMovie->numLang = 0;
    
        token = strtok_r(NULL, ",", &ptr);
        if (token) {
            int numLang = 0;
            char *ptr1;
            token = strtok_r(token, "[];", &ptr1);
            while (token != NULL) {
                currMovie->lang = realloc(currMovie->lang, (numLang + 1) * sizeof(char *));
                if (currMovie->lang == NULL)
                    break;
                currMovie->lang[numLang] = strdup(token);
                currMovie->numLang++;
                numLang++;
                token = strtok_r(NULL, "[];", &ptr1);
            }
        }
    
        // rating value
        token = strtok_r(NULL, "\n", &ptr);
        if (token) {
            if (sscanf(token, "%lf", &currMovie->ratingValue) != 1) {
                currMovie->ratingValue = 0.0;
                printf("Token: \"%s\". Invalid rating value. Setting to default (0.0).\n", token);
            }
        } else {
            currMovie->ratingValue = 0.0;
            printf("Missing rating value. Setting to default (0.0).\n");
        }
        currMovie->next = NULL;
        return currMovie;
    }
    
    /*
     * Return linked list of movies by parsing data from each line
     */
    struct movie *processFile(const char *filePath)
    {
        // open file
        FILE *movieFile = fopen(filePath, "r");
        if (movieFile == NULL) {
            fprintf(stderr, "cannot open %s: %s\n", filePath, strerror(errno));
            return NULL;
        }
    
        char *currLine = NULL;
        size_t len = 0;
        ssize_t nread;
    
        struct movie *head = NULL;
        struct movie *tail = NULL;
    
        // skip the header line
        getline(&currLine, &len, movieFile);
    
        // read file
        while ((nread = getline(&currLine, &len, movieFile)) >= 0)
        {
            // Get new movie
            struct movie *newNode = createMovie(currLine);
    
            if (newNode == NULL)
            {
                continue;
            }
    
            // id first node
            if (head == NULL)
            {
                // first node in the linked link, Set head and tail to node
                head = newNode;
                tail = newNode;
            }
            else
            {
                tail->next = newNode;
                tail = newNode;
            }
        }
        free(currLine);
        fclose(movieFile);
        return head;
    }
    
        2
  •  1
  •   pm100    1 年前

    您的问题是,您正在运行两个strtok_r序列,但使用相同的指针。

    更改以执行此操作

       char* ptr;
       char* ptr1;
    
    // language
    token = strtok_r(NULL, ",", &ptr);
    token = strtok_r(token, "[];", &ptr1);
        
         ...
         token = strtok_r(NULL, "[];", &ptr1);
    

    即扫描第三个“,”返回的令牌时,扫描使用新指针