我正在从包含3列(坐标ID,x线和y线)的文本文件中读取。 所有值都用制表符(\ t)隔开。当我尝试使用fscanf()创建列表时,它将不会打印我的第一行,而将最后一行打印两次。
while ((fgets(buffer, BUFFER_SIZE, fptr)) != NULL)
{
fscanf(fptr,"%d%f%f", &id, &xc, &yc);
tempValue.xyID = id;
tempValue.x = xc;
tempValue.y = yc;
addToList(nodeID++, tempValue);
}
printList();
上面的代码不适用于scanf,但是当我这样做时:
while ((fgets(buffer, BUFFER_SIZE, fptr)) != NULL)
{
tempValue.xyID = atoi(strtok(buffer,"\t"));
tempValue.x = atoi(strtok(NULL, "\t"));
tempValue.y = atoi(strtok(NULL, "\t"));
addToList(nodeID++, tempValue);
}
printList();
上面的代码可以完美运行,我想知道fscanf在做什么,谢谢!
答案 0 :(得分:2)
如果使用fgets()
将文件中的一行读取到内存中,则需要使用sscanf(buffer, ...)
来扫描该行。如果调用fscanf(fptr, ...)
,则基本上是在丢弃刚读取的行,并从文件中读取下一行数据。
看到最后一行两次的原因很可能是因为fscanf()
在到达文件末尾时被调用了。如果它无法读取任何数据,则传递给fscanf()
的变量将不会被覆盖。您不是在检查fscanf()
的返回值以确保您实际读取了新数据,而是始终调用addToList()
,然后它将使用上一次对{的调用存储的值将一个项添加到列表中。 {1}}。
您的第二次尝试有效,因为您现在实际上正在解析读取到缓冲区的数据。请注意,您不会再次检查调用的函数的所有返回值是否存在错误。如果您尝试读取包含少于三个项目的行的文件,则第二个版本将崩溃,因为fscanf()
将返回strtok()
,然后您将有效地调用NULL
。另外,atoi(NULL)
会静默忽略任何错误,例如,当它尝试解析的字符串不包含有效数字时,它将返回0。如果您想使用atoi()
,则最好使用strtol()
确保您正确解析了一个值。