C:fscanf-第一个字符匹配时的无限循环
我正在尝试使用fscanf解析文本(CSS)文件,并拉出与此模式匹配的所有语句: @导入“some/file/somewhere.css” 为此,我设置了以下循环:C:fscanf-第一个字符匹配时的无限循环,c,scanf,C,Scanf,我正在尝试使用fscanf解析文本(CSS)文件,并拉出与此模式匹配的所有语句: @导入“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 t
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格式化程序可能需要一些调整,但我不确定如何继续。对于为什么会发生这种情况,有什么建议或解释吗
谢谢。我不是
scanf
模式语法方面的专家,但我对你的解释是:
- 匹配非“@”字符的非空序列,然后
- 匹配最多8999个非空序列“;”代码>字符
“@”
开头,那么第一部分将失败
我认为,如果您用一些空格开始格式化字符串,那么
fscanf
将吃掉数据字符串中的任何前导空格,即简单地%8999[^;]“
Oli已经说过fscanf失败的原因。由于故障是fscanf的正常状态,所以忙循环不是fscanf故障的结果,而是缺少对它的处理
即使您的格式正确(在您的特殊情况下),您也必须处理fscanf故障,因为您无法确保输入始终与格式匹配。实际上,您可以确保存在比匹配输入多得多的非匹配输入。您的格式字符串执行以下操作:
- 读取(并丢弃)1个或多个非
字符@
- 读取(并丢弃)0个或更多空白字符(由于格式字符串中的空格)
- 读取并存储1到8999个非代码代码>字符
@
,您可以将当前格式字符串与sscanf一起使用,否则,您可以使用sscanf(行),%8999[^;]”,缓冲区)
)
如果一行中有多个@include语句需要正确处理,则可以使用
getc
检查下一个要读取的字符,然后使用ungetc
将其放回您的字符串开头似乎缺少一个%
。这是一个复制粘贴错误,还是一个bug?哎呀。在尝试诊断格式化程序的问题时,我删除了第一个%s。我已经把它放回了上面的代码中,但是它的存在并不能解决这个问题。这个问题既不是关于objective-c,也不是关于cocoa。因此,你应该删除这些标记。对Bryan不相关的建议:用设置几个变量和调用一两个函数来替换//这段代码很长,…
,不要使用scanf
来编写解析器。+1:这是一个很好的观点fscanf
不是您想要的,除非您能绝对保证您的输入文件是100%格式良好的。您最好使用自定义解析器。谢谢Tilo。我知道我能应付失败。但我的问题是,输入文件是100%格式良好的;如果在我用fscanf('@'符号)查找的第一个字符之前有零个字符,那么它就失败了。@Bryan:我的答案(没有回答你原来的问题;)的要点是,如果你像你的问题一样在循环中使用fscanf,那么你不仅“可以”处理错误,而且“必须”处理它。因为——正如现实所表明的那样——你不能保证fscanf不会失败,即使你认为它不应该在你的输入上失败。如果您在提问时已经理解了这一点,那么像“为什么该输入行上的fscanf失败”这样的问题可能会更清楚,而不提及循环。您是正确的-%8999[^;]“
将导致前导空格被丢弃。谢谢。我相信这已经在当前的格式化程序中捕获到:“%*[^@]%8999[^;]”对于一个不以“@”开头的文件,fscanf会正确地丢弃空白。@Bryan:的确如此。但是您当前的格式化程序不能使用以“@”
开头的行,而我的建议可以!谢谢你,巴特。不幸的是,我确实关心单行上的多个@import语句,90%的情况下,该行会以“@”开头。如果真的没有办法让fscanf将第一个字符识别为匹配的字符,那么看起来我必须手动执行。