C 中的 fgets 和 sscanf
fgets and sscanf in C
我有一个文件,我正在尝试从中提取整数和字符。
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: %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);
}
}
但是我得到的输出是:
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 %c\n", &xPos, &yPos, &zType) == 3 )
并交换 if
和 else
块的内容。这应该有效,因为除了第一行之外的所有行都满足此条件。
但是,更简单的解决方案是不尝试处理循环内的第一行,而是处理循环外的那一行:
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"
);
}
}
请注意,您可能需要添加 #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] == '[=10=]') {
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] == '[=10=]') {
printf("xPos: %d, yPos: %d, zType: %c\n", xPos, yPos, zType);
} else {
printf("No match\n");
}
}
如果扫描包含必需的后缀,这也很有效。
考虑如下输入:
< 0 0 # >
< 1 0 | >
< 2 0 | >
然后用" < %d %d %c > %n"
扫描
我有一个文件,我正在尝试从中提取整数和字符。
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: %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);
}
}
但是我得到的输出是:
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 %c\n", &xPos, &yPos, &zType) == 3 )
并交换 if
和 else
块的内容。这应该有效,因为除了第一行之外的所有行都满足此条件。
但是,更简单的解决方案是不尝试处理循环内的第一行,而是处理循环外的那一行:
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"
);
}
}
请注意,您可能需要添加 #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] == '[=10=]') {
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] == '[=10=]') {
printf("xPos: %d, yPos: %d, zType: %c\n", xPos, yPos, zType);
} else {
printf("No match\n");
}
}
如果扫描包含必需的后缀,这也很有效。
考虑如下输入:
< 0 0 # >
< 1 0 | >
< 2 0 | >
然后用" < %d %d %c > %n"
扫描