Fscan结构

时间:2018-10-27 15:18:54

标签: c scanf singly-linked-list

我正在从包含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在做什么,谢谢!

1 个答案:

答案 0 :(得分:2)

如果使用fgets()将文件中的一行读取到内存中,则需要使用sscanf(buffer, ...)来扫描该行。如果调用fscanf(fptr, ...),则基本上是在丢弃刚读取的行,并从文件中读取下一行数据。

看到最后一行两次的原因很可能是因为fscanf()在到达文件末尾时被调用了。如果它无法读取任何数据,则传递给fscanf()的变量将不会被覆盖。您不是在检查fscanf()的返回值以确保您实际读取了新数据,而是始终调用addToList(),然后它将使用上一次对{的调用存储的值将一个项添加到列表中。 {1}}。

您的第二次尝试有效,因为您现在实际上正在解析读取到缓冲区的数据。请注意,您不会再次检查调用的函数的所有返回值是否存在错误。如果您尝试读取包含少于三个项目的行的文件,则第二个版本将崩溃,因为fscanf()将返回strtok(),然后您将有效地调用NULL。另外,atoi(NULL)会静默忽略任何错误,例如,当它尝试解析的字符串不包含有效数字时,它将返回0。如果您想使用atoi(),则最好使用strtol()确保您正确解析了一个值。