[英]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.