简体   繁体   English

将CSV文件中的值读入变量

[英]Reading values from CSV file into variables

I am trying to write a simple piece of code to read values from a CSV file with a max of 100 entries into an array of structs. 我正在尝试编写一段简单的代码,以从CSV文件中读取值(最多100个条目)到一个结构数组中。

Example of a line of the CSV file: CSV文件的一行示例:

1,Mr,James,Quigley,Director,200000,0 1,詹姆斯先生,奎格利先生,导演,200000,0

I use the following code to read in the values, but when I print out the values they are incorrect 我使用以下代码读取值,但是当我打印出值时,它们是不正确的

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

Then when I print out the first name, the values are all assigned to the first name: 然后,当我打印出名字时,所有值都分配给名字:

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

Gives ames,Quigley,Director,200000,0 and so on in that way. 这样ames,Quigley,Director,200000,0等。 I am sure it's how i format the fscanf line but I can't get it to work. 我敢肯定这是我格式化fscanf行的方式,但我无法使其正常工作。

Here is my struct I'm reading into: 这是我正在阅读的结构:

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

This is because a string %s can contain the comma, so it gets scanned into the first string. 这是因为字符串%s可以包含逗号,因此将其扫描到第一个字符串中。 There's no "look-ahead" in the scanf() formatting specifier, the fact that the %s is followed by a comma in the format specification string means nothing. scanf()格式说明符中没有“向前看”,在格式说明字符串中%s后跟逗号的事实没有任何意义。

Use character groups (search the manual for [ ). 使用字符组( 在手册中搜索[ ]。

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);

And learn to check the return value , since I/O calls can fail! 并学习检查返回值 ,因为I / O调用可能会失败! Don't depend on the data being valid unless got is 7. 除非got是7,否则不要依赖于数据是否有效。

To make your program read the entire file (multiple records, ie lines), I would recommend loading entire lines into a (large) fixed-size buffer with fgets() , then using sscanf() on that buffer to parse out the column values. 为了使您的程序读取整个文件(多条记录,即行),我建议使用fgets()将整行加载到(大)固定大小的缓冲区中,然后在该缓冲区上使用sscanf()解析出列值。 That is much easier and will ensure that you really do scan separate lines, calling fscanf() in a loop will not, since to fscanf() a linefeed is just whitespace. 这样会容易得多,并且可以确保您确实确实扫描了单独的行,而不会在循环中调用fscanf() ,因为对于fscanf() ,换行符只是空白。

Might as well post my comment as an answer: 最好将我的评论作为答案:

%s reads a full word by default. 默认情况下, %s读完整的单词。

It finds the %d , the integer part, then the , , and then it has to read a string. 它找到%d ,整数部分,然后是,然后必须读取一个字符串。 , is considered valid in a word (it is not a whitespace), so it reads until the end of the line (there is no whitespace until then), not until the first comma... And the rest remains empty. ,在一个单词中被认为是有效的(不是空格),因此它一直读到行尾(直到那时为止都没有空格),直到第一个逗号才读取...,其余部分保持空白。 (From this answer) (从这个答案)

You have to change the separator with specifying a regex: 您必须通过指定正则表达式来更改分隔符:

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);

Instead of %s , use %[^,] , which means "grab all chars, and stop when found a , ". 取而代之的%s ,使用%[^,] ,意思是“抓住所有字符,并停止时发现, ”。

EDIT 编辑

%[^,]s is bad, it would need a literal s after the end of the scanset... Thanks @MichaelPotter %[^,]s很不好,在扫描集结束后需要一个文字s ...谢谢@MichaelPotter

(From Changing the scanf() delimiter and Reading values from CSV file into variables ) (从更改scanf()分隔符并将值从CSV文件读取为变量开始

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM