将CSV文件中的值读入变量

时间:2013-09-11 09:14:19

标签: c file-io input scanf

我正在尝试编写一段简单的代码,将CSV文件中的值从最多100个条目中读取到结构数组中。

CSV文件行的示例:

1,MR,詹姆斯,奎格利,导演,200000,0

我使用以下代码读取值,但是当我打印出不正确的值时

for(i = 0; i < 3; i++) /*just assuming number of entries here to demonstrate problem*/
    {
    fscanf(f, "%d,%s,%s,%s,%s,%d,%d", &inArray[i].ID, inArray[i].salutation, inArray[i].firstName, inArray[i].surName, inArray[i].position, &inArray[i].sal, &inArray[i].deleted);
    } 

然后,当我打印出第一个名字时,所有值都分配给第一个名字:

for(j = 0; j < 3; j++) /* test by printing values*/
    {
    printf("Employee name is %s\n", inArray[j].firstName);
    } 

以这种方式提供ames,Quigley,Director,200000,0等等。我确定这是我如何格式化fscanf线,但我不能让它工作。

这是我正在阅读的结构:

typedef struct Employee
    {
    int ID;
    char salutation[4];
    char firstName[21];
    char surName[31];
    char position[16];
    int sal;
    int deleted;
    } Employee;

2 个答案:

答案 0 :(得分:17)

这是因为字符串%s可以包含逗号,因此它会被扫描到第一个字符串中。 scanf()格式化说明符中没有“预见”,格式规范字符串中的%s后跟逗号后面的内容无效。

使用字符组(搜索the manual获取 [)。

const int got = fscanf(f, "%d,%[^,],%[^,],%[^,],%[^,],%d,%d", &inArray[i].ID,
                       inArray[i].salutation, inArray[i].firstName,
                       inArray[i].surName, inArray[i].position, &inArray[i].sal, 
                       &inArray[i].deleted);

并学习检查返回值,因为I / O调用可能会失败!除非got为7,否则不要依赖有效数据。

为了让您的程序读取整个文件(多个记录,即行),我建议将整行添加到fgets()的(大)固定大小缓冲区中,然后使用sscanf()缓冲区来解析列值。这样更容易,并且确保您确实扫描单独的行,在循环中调用fscanf()不会,因为到fscanf()换行只是空格。

答案 1 :(得分:2)

也可以发表我的评论作为答案:

默认情况下,

%s会读取完整的字词。

它找到%d,整数部分,然后是,,然后它必须读取一个字符串。 ,在一个单词中被认为是有效的(它不是空格),所以它会一直读到行的末尾(直到那时才有空格),直到第一个逗号为止......其余的都是空的。 (From this answer)

您必须通过指定正则表达式来更改分隔符:

fscanf(f, "%d,%[^,],%[^,],%[^,],%[^,],%d,%d", &inArray[i].ID, inArray[i].salutation, inArray[i].firstName, inArray[i].surName, inArray[i].position, &inArray[i].sal, &inArray[i].deleted);

而不是%s,请使用%[^,],这意味着“抓住所有字符,并在找到,时停止。”

修改

%[^,]s很糟糕,在扫描设置结束后需要一个文字s ...谢谢@MichaelPotter

(来自Changing the scanf() delimiterReading values from CSV file into variables