【问题标题】:Cannot properly count elements in CSV after strtok in C在 C 中的 strtok 之后无法正确计算 CSV 中的元素
【发布时间】:2019-07-01 07:49:36
【问题描述】:

在我使用 strtok 以逗号和引号(双引号)分隔后,我有时只会看到正确的元素数量。通常 printf 的长度为 0,但偶尔为 6 和 1,代码没有变化。

我尝试只使用一个分隔符(逗号)并以不同的方式定义 strtok 的标记输出,并重新排列 while 循环中的语句顺序,其中该行的其他元素被认为是分隔的。这些是我用来测试代码 (test.csv) 的 .csv 文件的几行。它与 NOAA 以 .csv 格式提供降水数据的格式相同。

"STATION","NAME","DATE","PRCP","PRCP_ATTRIBUTES"
"US183459384","XYZ ABC 9.0 E, WA US","2019-01-06","0.65",",,N"
"US183459384","XYZ ABC 9.0 E, WA US","2019-01-12","0.46",",,N"
"US183459384","XYZ ABC 9.0 E, WA US","2019-01-13","0.09",",,N"
"US183459384","XYZ ABC 9.0 E, WA US","2019-01-14","0.01",",,N"
"US183459384","XYZ ABC 9.0 E, WA US","2019-01-15","0.60",",,N"
"US183459384","XYZ ABC 9.0 E, WA US","2019-01-16","1.93",",,N"

我的代码尝试如下。

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

#define BUFFER_SIZE 1024

int get_row(FILE *file, int row_num, char delim[]) {
    int n_line = 0;
    int field = 0;
    char row[BUFFER_SIZE], *line[BUFFER_SIZE];

    while (fgets(row, BUFFER_SIZE, file)) {
        if (n_line == row_num) {
            printf("Length of line %d is %ld elements!\n", n_line, strlen(row));
            char* element = strtok(row, delim);
            while (element != NULL) {
                printf("%s\n", element);
                line[field++] = strdup(element);
                element = strtok(NULL, delim);
            }
            return 0;
        } else {
          n_line++;
    }
    printf("There is no row %d in the file you selected.\n", row_num);
    return 0;
}

int main(int argc, char **argv) {
    FILE *file;
    char delim[]  = ", \"";

    file = fopen(”test.csv”, "r");
    if (!file) {
        printf("Error: could not open %s\n", file_name);
        return -1;
    }
    printf("Reading file...\n");
    get_row(file, 0, delim);
    fclose(file);
    return 0;
}

我希望结果显示为 5,但所有行的结果为 0 或 1,偶尔为 6。

【问题讨论】:

  • 至少这一行是错误的 while (row, BUFFER_SIZE, file)
  • 是的,抱歉,最初是一段时间(fgets(row,BUFFER_SIZE,file)){。我转移到 SO 时打错字了
  • 您不能使用strtok 来解析这样的 CSV。您的输入数据包含逗号和空格,因此strtok 将在每个逗号和空格处拆分这些字段。如果您的数据不包含引号,您可能会只使用引号作为分隔符,并跳过每隔一个字段(这将是实际字段之间的逗号)。
  • 参见例如this tutorial 提示

标签: c csv strtok fileparsing


【解决方案1】:

此程序不应编译,因为未定义 file_name。 此外,在 getrow 函数内部,没有元素应该等于字段,而不是缓冲区的长度。由于该字段中有逗号,因此逗号分隔符也不起作用。 以下代码适用于 test.csv 文件中的给定行

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

#define BUFFER_SIZE 1024

int get_row(FILE *file, int row_num, char delim[]) {
    int n_line = 0;
    int field = 0;
    char row[BUFFER_SIZE], *line[BUFFER_SIZE];

    while (fgets(row, BUFFER_SIZE, file)) {
        if (n_line == row_num) {
            char* element = strtok(row, delim);
            while (element != NULL) {
                if(strcmp(",", element) != 0 &&  strcmp("\n", element) != 0)
                {
                  printf("%s\n", element);
                  line[field++] = strdup(element);
                }
                element = strtok(NULL, delim);
            }
            printf("Length of line %d is %d elements!\n", n_line, field);
            return 0;
        } else {
          n_line++;
    }
  }
    printf("There is no row %d in the file you selected.\n", row_num);
    return 0;
}

int main(int argc, char **argv) {
    FILE *file;
    char delim[]  = "\"";
    char file_name[] = "test.csv";

    file = fopen(file_name, "r");
    if (!file) {
        printf("Error: could not open %s\n", file_name);
        return -1;
    }
    printf("Reading file...\n");
    get_row(file, 0, delim);
    fclose(file);
    return 0;
}

【讨论】:

    【解决方案2】:

    程序中有许多语法错误。 这应该有效:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define BUFFER_SIZE 1024
    
    int get_row(FILE *file, int row_num, char delim[]) {
        char row[BUFFER_SIZE];
    
        for (int i = 0; fgets(row, BUFFER_SIZE, file); i++) {
            if (i == row_num) {
                printf("Length of line %d is %ld elements!\n", i, strlen(row));
    
                char* element = strtok(row, delim);
                while (element) {
                    printf("%s\n", element);
                    element = strtok(NULL, delim);
                }
    
                break;
            }
        }
    
        printf("There is no row %d in the file you selected.\n", row_num);
    
        return 0;
    
    }
    
    int main() {
        FILE *file;
        char delim[]  = ", \"";
    
        file = fopen("test.csv", "r");
        if (!file) {
            puts("Error: could not open");
            return -1;
        }
    
        printf("Reading file...\n");
        get_row(file, 0, delim);
        fclose(file);
    
        return 0;
    }
    

    【讨论】:

    • 这不处理字段内的逗号。
    • @rtoijala 修复它
    • 编辑不能解决问题。现在,对于在任何字段中包含逗号、空格或双引号的任何行,您的输出都不正确。在对get_row的调用中将0更改为1,看看我的意思。
    猜你喜欢
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    • 2018-12-20
    • 2018-01-08
    • 2018-04-21
    • 1970-01-01
    相关资源
    最近更新 更多