C:fscanf - 第一个字符匹配时的无限循环

时间:2010-09-30 09:14:29

标签: c scanf

我正在尝试使用fscanf解析文本(CSS)文件,并提取出与此模式匹配的所有语句:

@import“some / file / somewhere.css”;

为此,我设置了以下循环:

FILE *file = fopen(pathToSomeFile, "r");
char *buffer = (char *)malloc(sizeof(char) * 9000);

while(!feof(file))
{
    // %*[^@] : Read and discard all characters up to a '@'
    // %8999[^;] : Read up to 8999 characters starting at '@' to a ';'.
    if(fscanf(file, "%*[^@] %8999[^;]", buffer) == 1)
    {
        // Do stuff with the matching characters here.
        // This code is long and not relevant to the question.
    }
}

这非常有效,因为文件中的第一个字符不是'@'。 (从字面上看,CSS文件中第一个'@'字符前的单个空格将使代码运行正常。)

但是如果CSS文件中的第一个字符是'@',那么我在调试器中看到的是无限循环 - 执行进入while循环,命中fscanf语句,但不输入'if '声明(fscanf失败),然后永远继续循环。

我相信我的fscanf格式化程序可能需要一些调整,但我不确定如何继续。对于为什么会发生这种情况的任何建议或解释?

谢谢。

3 个答案:

答案 0 :(得分:2)

我不是scanf模式语法的专家,但我对你的解释是:

  • 匹配非空'@'字符的非空序列,然后
  • 匹配最多8999个非';'字符的非空序列

所以是的,如果你的字符串以'@'开头,那么第一部分就会失败。

认为如果你用一些空格开始你的格式字符串,那么fscanf会占用你数据字符串中的任何前导空格,即只是" %8999[^;]"

答案 1 :(得分:1)

Oli已经说过为什么fscanf失败了。由于故障是fscanf的正常状态,因此繁忙的循环不是fscanf故障的结果,而是缺少处理的结果。

即使您的格式正确(在您的特殊情况下),您也必须处理fscanf故障,因为您无法确定输入始终是否可以通过格式匹配。实际上,您可以确定存在比匹配输入更多的不匹配输入。

答案 2 :(得分:0)

您的格式字符串执行以下操作:

  • 读取(并丢弃)1个或多个非@字符
  • 读取(并丢弃)0个或更多空格字符(由于格式字符串中的空格)
  • 读取并存储1到8999个非;字符

不幸的是,没有用于从用户定义的集合中读取“零个或多个”字符的格式说明符。

如果您不关心某行上的多个@include语句,可以将代码更改为读取单行(使用fgets),然后从中提取@include语句(如果第一个字符不相等) @,您可以将当前格式字符串与sscanf一起使用,否则,您可以使用sscanf(line, "%8999[^;]", buffer))。

如果应该正确处理一行上的多个@include statemens,您可以使用getc检查要读取的下一个字符,然后将其与ungetc一起放回。