从 csv 文件中读取,分隔 C 中的每一行和每个字段

Read from a csv file , separate every line and every field in C

我有一个 csv 文件,我必须在其中分隔该行中的每一行 (\n) 和每个字段 (,)。 我的目标是创建一个结构数组。数组的每个“框”中的每个结构必须包含每一行的 4 个字段。 我怎么能用c写呢? 我想使用 fscanf 和 fgets,但我不知道如何一起使用它们,因为使用 fgets 我想分割线,而使用 fscanf 我想分割字段。

最终情况:

| 0 , noto, 233460, 32209.073312 | 1, piangea, 4741192, 811.. | 2 ,spenti! , .... |

| position 0 in the array | position 1 in the array | position 2 in the array |

records.csv

0,诺托,233460,32209.073312
1,piangea,4741192,81176.622633
2,花!,1014671, 4476.013614
3,misericordia,496325,61628.929334
4,全多,4476757,10838.641053

main.c

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

struct _SortedArray {
    int id;
    char field1[12];
    int field2;
    float field3;
};

int main() {
    FILE *fd;
    int res;

    struct _SortedArray files[101];
    int n;


    fd = fopen("records.csv", "r");
    if (fd == NULL) {
        perror("Error");
        exit(1);
    }

    char r[100];
    n = 0;

    while (n<6) {

        if(fgets(r,100,fd)!=NULL){
            puts(r);
            fscanf(r, "%[^,],%[^,],%[^,],%[^\n]\n", &files[n].id, &files[n].field1, &files[n].field2, &files[n].field3);
        }

        n++;
    }

    for(int i=0;i<6;i++){
        printf(" INT:%c,CHAR:%s //",files[i].id, files[i].field1);
    }
    return 0;
}

您的代码包含各种小问题和主要不一致之处。主要的不一致是您应该使用 sscanf 而不是 fscanf 来处理 fgets.

返回的行

但这还不是全部:

  • misericordia 有 12 个字符。由于 C 字符串需要 NULL 终止符,因此 field1 的大小必须至少为 13
  • 格式字符要与字段类型一致
  • 当您读入一个 char 数组时,该数组会衰减为一个指针:您不能添加 &

所以该行可以变成:

sscanf(r, "%d,%[^,],%d,%f", &files[n].id, files[n].field1, &files[n].field2, &files[n].field3)

其他可能的改进:

  • _开头的标识符应保留给您不使用的标识符。接近一个意见,但在这里你最好使用 SortedArray
  • 尽可能用 sizeof 运算符替换大小的普通 魔法值 。如果您稍后更改大小,则必须在代码中的一个位置进行更改(最佳做法:不要重复自己)
  • 控制输入函数的结果(这里[s]scanf对错误的输入数据具有鲁棒性
  • 最终控制行尾不留任何内容
  • 只尝试打印尽可能多的行
  • 删除未使用的变量(一个好的编译器应该发出警告)
  • 始终将字符串输入限制为缓冲区的大小 (%12[^,])

代码可以变成:

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

struct SortedArray {
    int id;
    char field1[13];
    int field2;
    float field3;
};

int main() {
    FILE *fd;
    // int res;

    struct SortedArray files[101];
    int n;


    fd = fopen("records.csv", "r");
    if (fd == NULL) {
        perror("Error");
        exit(1);
    }

    char r[100];
    for (n=0; n<sizeof(files)/sizeof(files[0]); n++) {

        if(fgets(r,sizeof(r),fd)==NULL){
            break;
        }
            char dummy[2];    // to control nothing is left on end of line
           //puts(r);
           if (4 != sscanf(r, "%d,%12[^,],%d,%f%1s", &files[n].id, files[n].field1, &files[n].field2, &files[n].field3, dummy)) {
               perror("Incorrect line");
               fprintf(stderr, "Line %d : %s\n", n+1, r);
        }
    }

    for(int i=0;i<n;i++){
        printf(" INT:%d,CHAR:%s //",files[i].id, files[i].field1);
    }
    return 0;
}