c - strtok 在这种情况下到底是如何工作的?

标签 c strtok

我一直在开发一个程序,该程序读取包含姓名、年龄和 GPA 值的 CSV 文件。 该代码似乎可以很好地读取文件,但我在解析它时遇到问题,因为程序没有正确标记值。由于某种原因,它正确读取该行,然后当我尝试使用 strtok 解析它时,它每次都只获取名称。 CSV 的格式为:

name1, age1, GPA,
name2, age2, GPA,

等等

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


typedef struct Student{
    char name[50];
    int age;
    double GPA;
};

int main(int argc, char *argv[]){

    FILE *fp;
    char buffer[255];
    struct Student students[100];
    int i = 0;

    if (argc != 2){
        printf("Incorrect input\n\n");
        exit(-1);
    }

    fp = fopen(argv[1], "r");
    if(fp == NULL){
            printf("Error: Empty File\n\n");
            exit(-1);
    }

    //takes the next line of the CSV and puts it in the next student
    while(fgets(buffer, 255, fp) != NULL){

        printf("%s\n", buffer);
        strcpy(students[i].name, strtok(buffer, ","));      
        printf("%s\n", buffer);
        students[i].age = atoi(strtok(buffer, ","));
        printf("%s\n", buffer);
        students[i].GPA = atof(strtok(buffer, ","));
        printf("%s\n", buffer);
        i++;
    }

    for(int i = 0; i < 9; i++)
    {
        printf("%s, %d, %f\n", students[i].name, students[i].age, students[i].GPA);
    }
}

最佳答案

您的代码的此修订版可以正常工作(只要数据中没有格式错误):

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

struct Student
{
    char    name[32];
    int     age;
    double  GPA;
};

int main(int argc, char *argv[])
{
    FILE *fp;
    char buffer[255];
    struct Student students[100];

    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s grades-file\n", argv[0]);
        exit(-1);
    }

    fp = fopen(argv[1], "r");
    if (fp == NULL)
    {
        fprintf(stderr, "%s: failed to open file %s for reading\n", argv[0], argv[1]);
        exit(-1);
    }

    int i;
    for (i = 0; fgets(buffer, sizeof(buffer), fp) != NULL; i++)
    {
        char *token;
        buffer[strcspn(buffer, "\n")] = '\0';
        printf("[%s]\n", buffer);
        strcpy(students[i].name, (token = strtok(buffer, ",")));
        printf("[%s] [%s]\n", buffer, token);
        students[i].age = atoi((token = strtok(NULL, ",")));
        printf("[%s] [%s]\n", buffer, token);
        students[i].GPA = atof((token = strtok(NULL, ",")));
        printf("[%s] [%s]\n", buffer, token);
    }

    for (int j = 0; j < i; j++)
    {
        printf("%s, %d, %.1f\n", students[j].name, students[j].age, students[j].GPA);
    }

    return 0;
}

请注意,此代码捕获 tokenstrtok() 的返回值。在调用任何其他函数之前,它应该检查 token 不为 null,因此编写的代码相当脆弱。 strcspn() 调用可以在输入行末尾换行,但如果行末尾没有换行,也可以正常工作。

还要注意 strtok() 如何切割字符串。一旦它隔离了第一个标记,就会用 null 代替分隔符 (,)。此后,buffer 不会改变 - 因此代码也会打印 token

数据文件:

Gavin Thomas, 12, 67.3
Adelie Newman, 13, 89.214
Karen Gibson, 15, 94.599

示例输出(程序csv17):

$ csv17 data.csv
[Gavin Thomas, 12, 67.3]
[Gavin Thomas] [Gavin Thomas]
[Gavin Thomas] [ 12]
[Gavin Thomas] [ 67.3]
[Adelie Newman, 13, 89.214]
[Adelie Newman] [Adelie Newman]
[Adelie Newman] [ 13]
[Adelie Newman] [ 89.214]
[Karen Gibson, 15, 94.599]
[Karen Gibson] [Karen Gibson]
[Karen Gibson] [ 15]
[Karen Gibson] [ 94.599]
Gavin Thomas, 12, 67.3
Adelie Newman, 13, 89.2
Karen Gibson, 15, 94.6
$

关于c - strtok 在这种情况下到底是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49228889/

相关文章:

c - C中的strtok段错误

c - 以更快的方式找出变量中没有设置的位

c# - 如何在 C# 中编写类似于 String.isNullOrEmpty 的 C 代码

c - 如何删除重复的数字

在 Linux 上运行时,C fgets 函数不起作用

c - strtok坏了吗?或者只是棘手?

c - 错误的 Visual Studio 程序集输出?

c - C中嵌套strtok函数问题

c - 在 C 中使用 strtok 为结构体赋值

C - 以相同字母开头和结尾的单词