且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用c从csv文件中获取具有精确数据的特定行?

更新时间:2023-09-05 09:42:22


i我只想删除那些以字符 A开头的行。

i want to get only those row which start with character "A"

我想删除A和老虎之间的数字,

i want to remove the number which coming between A and tiger,

如果我对您的理解是正确的,而您只想存储以'A'开头的行,那么我会调整您的用 fgets()读取每一行,然后检查缓冲区中的第一个字符是否为'A',如果是这样,请继续; 并获得下一行。对于那些以'A'开头的行,只需使用 sscanf 将数据解析为结构体数组记录

If I understand you correctly and you only want to store rows beginning with 'A', then I would adjust your approach to read each line with fgets() and then check whether the first character in the buffer is 'A', if so, continue; and get the next line. The for those lines that do start with 'A', simply use sscanf to parse the data into your array of struct records.

第二部分是删除'A'之间的数字 tiger ,您的存储和您的输出之间是有区别的(这在只存储以'A'开头的记录中起作用),但是对于那些存储在以'A'开始的行中的结构/ code>,您可以简单地不输出 pin 结构成员来获取所需的输出。

For your second part of removing the number between 'A' and "tiger", there is a difference between what you store and what you output (this comes into play in storing only records beginning with 'A' as well), but for those structs stored where the line starts with 'A', you can simply not-output the pin struct member to get the output you want.

一次读取一行的方法仅需要声明一个附加的字符数组(缓冲区),下面称为 buf ,以将每个行读入 fgets(),例如

The approach to reading a line at a time will simply require that you declare an additional character array (buffer), called buf below, to read each line into with fgets(), e.g.

    char buf[3 * NUMLETTERS] = "";
    ...
    /* read each line into buf until a max of NUMLETTERS struct filled */
    while (count < NUMLETTERS && fgets (buf, sizeof buf, fp)) {   
        record_t tmp = { .Refdes = "" };    /* temporary struct to read into */
        if (*buf != 'A')                    /* if doesn't start with A get next */
            continue;
        /* separate lines beginning with 'A' into struct members */
        if (sscanf (buf, " %99[^,],%d,%99[^\n]",
                    tmp.Refdes, &tmp.pin, tmp.NetName) == 3)
            records[count++] = tmp;         /* assign tmp, increment count */
        else
            fprintf (stderr, "%d A record - invalid format.\n", count + 1);
    }

使用它的简短示例,(因为我们不确定删除 的目的),我们包含了一个预处理器条件,该条件只会输出 .Refdes .NetName 成员默认情况下,但是如果您 #define WITHPIN 或在编译字符串中包含定义(例如, -DWITHPIN ),它也将输出 .pin 成员。

A short example putting that to use and (since we are not sure what "remove" is intended to be), we have included a pre-processor conditional that will only output the .Refdes and .NetName members by default, but if you either #define WITHPIN or include the define in your compile string (e.g. -DWITHPIN) it will output the .pin member as well.

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

#define NUMLETTERS 100

typedef struct {
    char Refdes[NUMLETTERS];
    int pin;
    char NetName[NUMLETTERS];
} record_t;

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

    record_t records[NUMLETTERS];
    char buf[3 * NUMLETTERS] = "";
    int count = 0, i;
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

    /* read each line into buf until a max of NUMLETTERS struct filled */
    while (count < NUMLETTERS && fgets (buf, sizeof buf, fp)) {   
        record_t tmp = { .Refdes = "" };    /* temporary struct to read into */
        if (*buf != 'A')                    /* if doesn't start with A get next */
            continue;
        /* separate lines beginning with 'A' into struct members */
        if (sscanf (buf, " %99[^,],%d,%99[^\n]",
                    tmp.Refdes, &tmp.pin, tmp.NetName) == 3)
            records[count++] = tmp;         /* assign tmp, increment count */
        else
            fprintf (stderr, "%d A record - invalid format.\n", count + 1);
    }

    if (fp != stdin)   /* close file if not stdin */
        fclose (fp);

    for (i = 0; i < count; i++)
#ifdef WITHPIN
        printf ("%-8s %2d     %s\n",
                records[i].Refdes, records[i].pin, records[i].NetName);
#else
        printf ("%-8s     %s\n", records[i].Refdes, records[i].NetName);
#endif
}

示例用法/输出

$ ./bin/getaonly dat/getasonly.txt
A            tiger
A1           dog
A2           mouse
A23          pouch

如果定义 -DWITHPIN 在编译字符串中,那么您将获得所有三个输出:

If you define -DWITHPIN in your compile string, then you will get all three outputs:

$ ./bin/getaonly dat/getasonly.txt
A         1     tiger
A1        7     dog
A2        9     mouse
A23       9     pouch

注意:,使用存储在数组中的数据,您可以将输出格式调整为所需的任何格式)

(note: with the data stored in your array, you can adjust the output format to anything you need)

由于存在不确定性,您是否要存储全部并仅输出以'A'开头的记录,还是只想存储以'A'-让我知道是否需要进行更改,很高兴为您提供进一步的帮助。

Since there is some uncertainty whether you want to store all and output only records beginning with 'A' or only want to store records beginning with 'A' -- let me know if I need to make changes and I'm happy to help further.