简体   繁体   English

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

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

I have a csv file in which I have to separate every line (\\n) and every field (,) in this line.我有一个 csv 文件,我必须在其中分隔该行中的每一行 (\\n) 和每个字段 (,)。 My goal is to create an array of structs.我的目标是创建一个结构数组。 Every struct in each "box" of the array must contains 4 fields of every line.数组的每个“盒子”中的每个结构都必须包含每行的 4 个字段。 How can I write it in c?我怎样才能用c写它? I thought to use fscanf and fgets but I don't know how to use them together because with fgets I want to divide lines while with fscanf i want to divide fields .我想使用 fscanf 和 fgets 但我不知道如何将它们一起使用,因为使用 fgets 我想分割线而使用 fscanf 我想分割字段。

Final situation :最终情况:

| 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记录.csv

0,noto,233460,32209.073312 0,noto,233460,32209.073312
1,piangea,4741192,81176.622633 1,piangea,4741192,81176.622633
2,spenti!,1014671, 4476.013614 2,senti!,1014671, 4476.013614
3,misericordia,496325,61628.929334 3,悲惨,496325,61628.929334
4,quando,4476757,10838.641053 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;
}

Your code contains various little problems and a major inconsistency.您的代码包含各种小问题和重大不一致。 The major inconsistency is that you should use sscanf instead of fscanf to process the line returned by fgets .主要的不一致是您应该使用sscanf而不是fscanf来处理fgets返回的行。

But that is not all:但这还不是全部:

  • misericordia has 12 characters. misericordia 有 12 个字符。 As C strings require a NULL terminator, field1 must have at least 13 as size由于 C 字符串需要 NULL 终止符,因此field1大小必须至少为 13
  • the format characters should be consistent with the type of the fields格式字符应与字段类型一致
  • when you read into a char array, the array decays to a pointer: you must not add th &当你读入一个 char 数组时,该数组衰减为一个指针:你不能添加 th &

So the line could become:所以这条线可以变成:

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

Other possible improvements:其他可能的改进:

  • identifiers starting with _ should be reserved for those that you do not use._开头的标识符应保留给您不使用的标识符。 Close to an opinion, but here you should better use SortedArray接近一个意见,但在这里你应该更好地使用SortedArray
  • replace plain magic values for sizes with the sizeof operator where you can.尽可能用sizeof运算符替换大小的普通魔术值 If you later change a size, you will have to change it in one single place in your code (best practice: Don't Repeat Yourself)如果稍后更改大小,则必须在代码中的一个位置更改它(最佳实践:不要重复自己)
  • control the result of input functions (here [s]scanf to be robust against erroneous input data控制输入​​函数的结果(这里[s]scanf对错误的输入数据具有鲁棒性
  • eventually control that nothing is left at the end of line最终控制行尾不留任何东西
  • only try to print as many lines as you could read只尝试打印尽可能多的行
  • remove unused variables (a nice compiler should emit warnings)删除未使用的变量(一个好的编译器应该发出警告)
  • always limit input of string to the size of the buffer ( %12[^,] )始终将字符串的输入限制为缓冲区的大小( %12[^,]

The code could become:代码可以变成:

#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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从file.csv读取并将每个值保存在数组C的字符串中 - How to read from a file.csv and save every value in a string of array C FileReader 从 CSV 逗号分隔文件中每隔一行跳过 - FileReader skipping every other line from CSV comma delimitted file C++ 从文本文件中读取每两行并在向量中安全 - C++ Read every second line from a text file and safe in vector Python:从文本文件到数组的每一行读取第n个值 - Python: read nth value on every line from text file into array 从文件中每4个字节读取3个字节数组 - Read 3 of every 4 bytes from file into bytearray 展开文本文件中的每一行 - Explode every line from text file Perl-如何从分隔的txt文件中读取每一行并进行处理 - Perl - How to read every single line from delimited txt file and process it 在Java中,我需要读取一个文本文件并将每一行放在单独的数组中。 但是每次阅读文本文件时,我都无法分开 - In Java I need to read a text file and put each line in a separate array. But every time I read the text file I cannot split the lines C ++:使用fgetc读取csv文件,并在分号“;”上使用单独的单词 - C++ : read csv file with fgetc and separate words on semicolon “;” 读取文本文件并将每一行另存为字符串(C ++) - Reading a text file and saving every line as a string (C++)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM