C语言 将 CSV 文件中的值读入变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18737117/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Reading values from CSV file into variables
提问by Dawson
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.
我正在尝试编写一段简单的代码来从最多 100 个条目的 CSV 文件中读取值到一个结构数组中。
Example of a line of the CSV file:
CSV 文件的一行示例:
1,Mr,James,Quigley,Director,200000,0
1,Mr,James,Quigley,Director,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,0and so on in that way. I am sure it's how i format the fscanf line but I can't get it to work.
ames,Quigley,Director,200000,0以这种方式给予等等。我确定这是我格式化 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;
回答by unwind
This is because a string %scan contain the comma, so it gets scanned into the first string. There's no "look-ahead" in the scanf()formatting specifier, the fact that the %sis followed by a comma in the format specification string means nothing.
这是因为一个字符串%s可以包含逗号,所以它会被扫描到第一个字符串中。scanf()格式说明符中没有“前瞻” ,事实上%s格式说明字符串中的后面跟一个逗号没有任何意义。
Use character groups (search the manualfor [).
使用字符组(搜索手册的[)。
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! Don't depend on the data being valid unless gotis 7.
并学习检查返回值,因为 I/O 调用可能会失败!不要依赖数据是否有效,除非got是 7。
To make your program read the entire file (multiple records, i.e. 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. 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.
为了让您的程序读取整个文件(多条记录,即行),我建议使用 将整行加载到(大)固定大小的缓冲区中fgets(),然后sscanf()在该缓冲区上使用来解析列值。这更容易,并且将确保您确实扫描单独的行,fscanf()循环调用不会,因为fscanf()换行只是空白。
回答by ppeterka
Might as well post my comment as an answer:
不妨发表我的评论作为答案:
%sreads a full word by default.
%s默认读取一个完整的单词。
It finds the %d, the integer part, then the ,, and then it has to read a string. ,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)
它找到%d,整数部分,然后是,,然后它必须读取一个字符串。,在一个单词中被认为是有效的(它不是空格),所以它会一直读到行尾(在此之前没有空格),直到第一个逗号......其余的都是空的。(来自这个答案)
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
编辑
%[^,]sis bad, it would need a literal safter the end of the scanset... Thanks @MichaelPotter
%[^,]s不好,s在扫描集结束后需要一个文字......谢谢@MichaelPotter
(From Changing the scanf() delimiterand Reading values from CSV file into variables)

