将CSV文件中的值读入变量
我正在尝试编写一段简单的代码来读取CSV文件中的值,最多包含100个条目到一个结构数组中。
CSV文件的一行示例:
1,先生,詹姆斯,奎格利,主任,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;
这是因为字符串%s
可以包含逗号,因此它会被扫描到第一个字符串中。 scanf()
格式化说明符中没有“预见”, %s
后面跟着格式规范字符串中的逗号这一事实没有任何意义。
使用字符组( 在 [ ]中搜索手册 。
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()
,换行只是空格。
不妨发表我的评论作为答案:
%s
默认读取一个完整的单词。
它找到%d
,整数部分,然后是,
然后它必须读取一个字符串。 ,
在一个单词中被认为是有效的(它不是空格),所以它一直读到行的末尾(直到那时才有空格),直到第一个逗号才开始……其余的都是空的。 (从这个回答)
您必须通过指定正则表达式来更改分隔符:
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
很糟糕,在扫描集结束后需要一个文字…谢谢@MichaelPotter
(从更改scanf()分隔符和从CSV文件读取值到变量 )