【发布时间】:2021-10-28 21:45:53
【问题描述】:
我正在调试一些遗留代码。它使用 fscanf 和 [] 格式说明符来读取一些波浪号 (~) 分隔值。文件格式很简单——value~value。 value 可以是所有空格。如果第一个值全是空格,则失败。下面是一个精简的示例...
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
char b1[100], b2[100];
FILE *fp = fopen( "temp_out", "r" );
for ( int i = 0; i < 6; i++ )
{
int n = fscanf( fp, "%[^~]~%[^\n]\n", b1, b2 );
printf("fscanf converted %d '%s' '%s'\n", n, n>0?b1:"",n>1?b2:"");
}
fclose( fp );
}
我的输入文件是……
line1~blah
~blah2
blah~
这是在 RedHat 上使用 gcc 8.4.1 编译的。
如果我运行它,我会得到...
fscanf converted 2 'line1' 'blah'
fscanf converted 0 '' ''
fscanf converted 0 '' ''
fscanf converted 0 '' ''
fscanf converted 0 '' ''
fscanf converted 0 '' ''
只转换第一行。
但是,如果我交换前 2 行输入...
~blah2
line1~blah
blah~
有效...
fscanf converted 2 ' ' 'blah2'
fscanf converted 2 'line1' 'blah'
fscanf converted 2 'blah' ' '
fscanf converted 0 '' ''
fscanf converted 0 '' ''
fscanf converted 0 '' ''
我可以将该行放在一个字符串中,然后 sscanf 就可以工作了。我可以使用 fgets+sscanf,这很有效,所以这是一种变通方法,但是这种模式在遗留代码中无处不在,我想知道是什么。
有什么想法吗?
【问题讨论】:
-
请参阅What is the effect of trailing white space in a
scanf()format string?,然后决定不要在格式字符串中使用尾随空格。最好通过阅读行(fgets()或 POSIXgetline())然后解析您提到的那些(sscanf())作为解决方法——这几乎可以肯定是解决问题的最佳(最简单)方法。 -
填充数组时必须使用 field-width 修饰符,否则
fscanf()并不比gets()更安全。如果遇到长行,您将需要"%99[^~]~%99[^\n]"以防止写入超出数组末尾。有关缓冲区溢出问题的详细信息,请参阅:Why gets() is so dangerous it should never be used!。
标签: c scanf format-specifiers