fgets and sscanf in C

  • 本文关键字:in sscanf and fgets c c89
  • 更新时间 :
  • 英文 :


我有一个文件,我试图提取整数和字符。

10 20
0 0 #
1 0 |
2 0 |
3 0 |
3 1 -
3 2 -
3 3 -
3 4 >

我当前的代码是:

while(fgets(line, sizeof(line), snakeFile) != NULL)
{
if(sscanf(line, "%d %d", &ROW, &COL) == 2)
{
printf("ROW: %d, COL: %dn", ROW, COL);
}

else
{
sscanf(line, "%d %d %cn", &xPos, &yPos, &zType);
printf("xPos: %d, yPos: %d, zType: %cn", xPos, yPos, zType);
}
}

但是我得到的输出是:

ROW: 10, COL: 20
ROW: 0, COL: 0
ROW: 1, COL: 0
ROW: 2, COL: 0
ROW: 3, COL: 0
ROW: 3, COL: 1
ROW: 3, COL: 2
ROW: 3, COL: 3
ROW: 3, COL: 4

我希望它获得前两个整数并将其存储在ROW和COL中,然后将其下面的其余行分别存储在xPos, yPos和zType中。

您似乎正在使用条件

if(sscanf(line, "%d %d", &ROW, &COL) == 2)

来确定当前是否正在处理第一行。然而,这个条件无法确定这一点,因为该条件对所有行都为真,而不仅仅是第一行。函数scanf将成功匹配2个数字,然后忽略该行的其余部分。

你可以做的一件事是将这行改为

if ( sscanf(line, "%d %d %cn", &xPos, &yPos, &zType) == 3 )

和交换ifelse块的内容。这应该可以工作,因为除了第一行之外,该条件对所有行都为真。

然而,一个更简单的解决方案是不尝试处理循环内的第一行,而是在循环外处理该行:
if( sscanf( line, "%d %d", &ROW, &COL) != 2 )
{
fprintf( stderr, "Conversion failure!n" );
exit( EXIT_FAILURE );    
}
printf("ROW: %d, COL: %dn", ROW, COL);
while ( fgets(line, sizeof(line), snakeFile) != NULL )
{
if ( sscanf(line, "%d %d %c", &xPos, &yPos, &zType) == 3 )
{
printf(
"xPos: %d, yPos: %d, zType: %cn",
xPos, yPos, zType
);
}
else
{
fprintf(
stderr,
"Warning: Conversion failure occurred on one line! This couldn"
"be harmless, for example it could be caused by an emptyn"
"line at the end of the file.n"
);
}
}

注意,您可能必须添加#include <stdlib.h>才能调用函数exit

sscanf(line, "%d %d", &ROW, &COL) == 2匹配OP样本的每行,因为每行以2个数字开头。


一种真正简洁的测试整行是否被扫描的方法是使用" %n"来存储扫描的偏移量。

即使文件的最后一行缺少'n',也可以正常工作。

// if(sscanf(line, "%d %d", &ROW, &COL) == 2)
int n = 0;
sscanf(line, "%d %d %n", &ROW, &COL, &n);
if (n > 0 && line[n] == '') {
printf("ROW: %d, COL: %dn", ROW, COL);
} else {
int n = 0;
sscanf(line, "%d %d %c %n", &xPos, &yPos, &zType, &n);
if (n > 0 && line[n] == '') {
printf("xPos: %d, yPos: %d, zType: %cn", xPos, yPos, zType);
} else {
printf("No matchn");
}
}

如果扫描包含所需的后缀,这也可以很好地工作。

考虑如下输入:

< 0 0 # >
< 1 0 | >
< 2 0 | >

然后用" < %d %d %c > %n"扫描

最新更新