【问题标题】:C - sscanf ignoring comma from csv file and reading the same piece of data twiceC - sscanf 忽略 csv 文件中的逗号并读取相同的数据两次
【发布时间】:2020-10-18 17:47:43
【问题描述】:

我正在尝试从 CSV 文件中读取结构。出于某种原因,社会安全号码的值也在读取地址,并且地址被第二次读取到 newBin.address 中。看起来 sscanf 在读取文件时忽略了分隔社交和地址的逗号,但在继续读取地址时确实注册了它。任何帮助表示赞赏。

#include <stdio.h>
#include<string.h>
#include<stdlib.h>
#define STRSIZE 70

typedef struct BIN_DATA {
        unsigned int user_number;
        char name[32];
        char social_security[10];
        char address[32];
} BIN_DATA;

int main()
{
    // Define variables.
    FILE *in, *out;
    char str[STRSIZE];

    // New BIN.
    BIN_DATA newBin;

    // Open files.
    in = fopen("updated.txt", "r");


    // Check files.
    if(in == NULL)
    {
            puts("Could not open file");
            exit(0);
    }

    while(fgets(str, STRSIZE, in) != NULL)
    {
            memset(&newBin, '\0', sizeof(BIN_DATA));
            sscanf(str, "%6u, %[^,], %[^,], %[^\n\r]", &newBin.user_number, newBin.name,\
                            newBin.social_security, newBin.address);
            printf("%u. %s. %s. %s.\n", newBin.user_number, newBin.name,\
                            newBin.social_security, newBin.address);
    }



    return 0;
}

正在读取的文件:

289383,Estefana Lewey,591-82-1520,"9940 Ohio Drv, 85021"
930886,Burl Livermore,661-18-3839,"226 Amherst, 08330"
692777,Lannie Crisler,590-36-6612,"8143 Woods Drv, 20901"
636915,Zena Hoke,510-92-2741,"82 Roehampton St, 47905"
747793,Vicente Clevenger,233-46-1002,"9954 San Carlos St., 55016"
238335,Lidia Janes,512-92-7402,"348 Depot Ave, 29576"
885386,Claire Paladino,376-74-3432,"587 Front Ave, 32703"
760492,Leland Stillson,576-55-8588,"9793 Boston Lane, 08610"
516649,Wes Althouse,002-58-0518,"8597 Annadale Drive, 06514"
641421,Nadia Gard,048-14-6428,"218 George Street, 29150"

【问题讨论】:

  • 你好。您应该知道您的 scanf 将在具有特殊字符作为值的列上失败。例如,字符串可能是“8597 Annadale\n Drive”。话虽如此,您接下来的所有scanf 都会读取错误的数据。
  • 感谢您的意见。有没有办法解决特殊字符的失败?

标签: c csv parsing


【解决方案1】:

正如 cmets 中所述,social_security 成员没有分配足够的空间来保存您正在读取的数据。它需要至少为 12 以保持 SSN 的结尾带有终止符。

至于你在 sscanf() 中使用的格式字符串,它几乎是正确的。但是,您需要限制最大字符串长度以匹配您的存储空间,例如,name 为 32,您应该将其限制为 31 个字符,在结尾处保留一个字符作为终止符。

我将social_security字段更改为char social_security[12];,然后将格式字符串更改为sscanf如下:

"%6u, %31[^,], %11[^,], %31[^\n\r]"

我能够使用示例输入文件运行修改后的代码,以获得您描述的输出。您也可以在链接中尝试:

Runnable code

【讨论】:

  • 太棒了,谢谢!那项工作,我认为将社交字符设置为 10 的原因是我应该将“-”修剪掉,我只是一步一步地进行。这是我将研究的下一个问题。
  • 请注意,这将捕获地址周围的双引号,如果地址不在最后一列中,它将无法正常工作。正确地完成这项工作需要库代码——不是非常大或复杂的库代码,但通常需要设计用于处理 CSV 格式的代码。另请参阅RFC 4180 — Comma-Separated Variable Format
猜你喜欢
  • 2018-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-13
相关资源
最近更新 更多