简体   繁体   English

C 中的 fgets 和 sscanf

[英]fgets and sscanf in C

I have a file I'm trying to extract the integers and characters out of.我有一个文件,我试图从中提取整数和字符。

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

My current code is:我当前的代码是:

while(fgets(line, sizeof(line), snakeFile) != NULL)
{
    if(sscanf(line, "%d %d", &ROW, &COL) == 2)
    {
        printf("ROW: %d, COL: %d\n", ROW, COL);
    }
    
    else
    {
        sscanf(line, "%d %d %c\n", &xPos, &yPos, &zType);
        printf("xPos: %d, yPos: %d, zType: %c\n", xPos, yPos, zType);
    }

}

However I get as the output:但是我得到的是 output:

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

I would like it to get the first two integers and store it in ROW and COL and then the rest of the lines underneath it stored in xPos, yPos and zType respectively.我希望它获取前两个整数并将其存储在 ROW 和 COL 中,然后它下面的行的 rest 分别存储在 xPos、yPos 和 zType 中。

You appear to be using the condition您似乎正在使用条件

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

to determine whether you are currently processing the first line or not.以确定您当前是否正在处理第一行。 However, this condition is unable to determine this, because that condition will be true with all lines, not just the first one.但是,此条件无法确定这一点,因为该条件对所有行都为真,而不仅仅是第一行。 The function scanf will successfully match 2 numbers and will then ignore the rest of the line. function scanf将成功匹配 2 个数字,然后将忽略该行的 rest。

One thing you could do would be to change that line to您可以做的一件事是将该行更改为

if ( sscanf(line, "%d %d %c\n", &xPos, &yPos, &zType) == 3 )

and to swap the contents of the if and the else block.并交换ifelse块的内容。 This should work, because this condition will be true for all lines except the first one.这应该可行,因为除了第一行之外,所有行都满足此条件。

However, a simpler solution would be to not attempt to handle the first line inside the loop, but to instead handle that line outside the loop:但是,更简单的解决方案是不尝试处理循环内的第一行,而是在循环外处理该行:

if( sscanf( line, "%d %d", &ROW, &COL) != 2 )
{
    fprintf( stderr, "Conversion failure!\n" );
    exit( EXIT_FAILURE );    
}

printf("ROW: %d, COL: %d\n", 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: %c\n",
             xPos, yPos, zType
        );
    }
    else
    {
        fprintf(
            stderr,
            "Warning: Conversion failure occurred on one line! This could\n"
            "be harmless, for example it could be caused by an empty\n"
            "line at the end of the file.\n"
        );
    }
}

Note that you may have to add #include <stdlib.h> to be able to call the function exit .请注意,您可能必须添加#include <stdlib.h>才能调用 function exit

sscanf(line, "%d %d", &ROW, &COL) == 2 matches every line of OP's sample as each line begins with 2 numbers. sscanf(line, "%d %d", &ROW, &COL) == 2匹配 OP 样本的每一行,因为每行以 2 个数字开头。


A real neat way of testing if the entire line was scanned uses " %n" to store the offset of the scan.测试行是否被扫描的一种真正巧妙的方法是使用" %n"来存储扫描的偏移量。

This works well even if the last line of the file lacked a '\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] == '\0') {
  printf("ROW: %d, COL: %d\n", ROW, COL);
} else {
  int n = 0;
  sscanf(line, "%d %d %c %n", &xPos, &yPos, &zType, &n);
  if (n > 0 && line[n] == '\0') {
    printf("xPos: %d, yPos: %d, zType: %c\n", xPos, yPos, zType);
  } else {
    printf("No match\n");
  }
}

This also works well if the scan included a required suffix.如果扫描包含必需的后缀,这也很有效。

Consider input like:考虑如下输入:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM