2017-06-13 50 views
0

我的工作是从文件中读取文本的程序,并解析文本文字和操纵它们,我就是那样的使用的fscanf解析的话我怎么能检查时,我跳过线

的fscanf解析当
while (fscanf (fp, " %32[^ ,.\t\n]%*c", word) == 1) 

{ 
/*manipulate the text word by word 

} 

我想要写相邻的,我觉得字,其中线我发现她

有没有办法,我可以检查,当我下移一行
使用功能的fscanf当的方法吗?

+2

'fscanf'不区分行,实际上大多数格式说明符都忽略所有空格。尝试使用'fgets'来读取每行,然后使用字符串分割函数。 –

+0

...例如'strsep'或'strtok'及其派生词,如果你想分析单词。 –

+0

'fscanf(fp,“%32 [^,。\ t \ n]%* c”,单词)'在不同的地方跳过''\ n'':领先''''也许''* c“' 。使用'fgets()'来读取_line_。 – chux

回答

3

最稳健的建议是使用fgets()或许POSIX getline()读线,然后考虑使用 sscanf()解析每一行。您可能需要考虑how to use sscanf() in a loop。还有许多其他选项可用于解析该行而不是sscanf(),例如strtok_r()或较不理想的strtok() - 或者在Windows上,strtok_s(); strspn(), strcspn(), strpbrk();和其他不规范的功能。

如果您认为必须使用fscanf(),那么您可能需要捕获尾随上下文。这方面的一个简单的版本是:

char c; 
while (fscanf(fp, " %32[^ ,.\t\n]%c", word, &c) == 2) 
    … 

这抓住了单词后,假设有一个。如果您的文件没有以换行符结尾,则可能会丢失一个单词。错过换行也很容易。例如,如果行在换行符之前以句号结束(句号),则c将保存.,换行符将在下一次迭代循环中跳过。你可以克服用:

char s[33]; 
while (fscanf(fp, " %32[^ ,.\t\n]%32[ ,.\t\n]", word, s) == 2) 
    … 

注意格式字符串的长度必须大于变量声明的长度少一个!

成功调用fscanf()后,字符串s可能包含多个换行符和空格等。 fscanf()函数大多不关心换行符,并且如果s的扫描集是数据文件中的内容,它将在一行中读取多个换行符。

如果你明确地从fscanf()捕捉状态,可以是,没有一个换行符(或者一个标点符号)结尾的文件,或引起其他问题更加敏感:

char s[33]; 
int rc; 
while ((rc = fscanf(fp, " %32[^ ,.\t\n]%32[ ,.\t\n]", word, s)) != EOF) 
{ 
    switch (rc) 
    { 
    case 2: 
     …proceed as normal, checking s for newlines. 
     break; 
    case 1: 
     …probably an overlong word or EOF without a newline. 
     break; 
    case 0: 
     …probably means the next character is one of comma or dot. 
     …spaces, tabs, newlines will be skipped without detection 
     …by the leading space in the format string. 
     break; 
    default: 
     assert(0); 
     break; 
    } 
} 

如果你开始关心约!?;:'"字符 - 更不用说() - 生活变得更加复杂依然。事实上,在这一点上,sscanf()的替代品开始看起来好多了。

这是很难正确地使用scanf()家庭的功能。他们只是新手的工具,至少一旦你开始需要做任何复杂的事情。你可以看看A beginner's guide to not using scanf(),其中包含很多有价值的信息。我不完全相信最后几个应该是防弹用途scanf()的例子。 (正确使用sscanf()会稍微简单一些,但是您仍然需要了解详细信息。)

1

fgets()然后读线使用sscanf解析它们:

char buff[1024]; 
int lineno = 0; 
int offset = 0; 
while (fgets(buff, 1024, fp)) { 
    lineno++; 
    offset = 0; 
    while (sscanf(buff + offset, " %32[^ ,.\t\n]%*c", word) == 1) 
    { 
    /* manipulate the text word by word */ 

    } 
} 

在第二环路必须增加缓冲器,以便正确地解析线适当偏移。为此,例如,您可以使用%n来获取读取字节。

+3

但请注意[在循环中使用'sscanf()'](http://stackoverflow.com/questions/3975236/how-to-use-sscanf-in-loops)。 –

+0

谢谢,我补充说。 @JonathanLeffler –