关于C#:sscanf的返回值

Return Value of sscanf

我正在阅读有关sscanf的信息,并且遇到了这个问题:

Return Value
Each of these functions [including s_sscanf()] returns the number of fields that are successfully converted and assigned; the return value does not include fields that were read but not assigned. A return value of 0 indicates that no fields were assigned. The return value is EOF for an error or if the end of the string is reached before the first conversion.

我正在为我的输入文件进行错误检查,我想确保获得有效的行,所以我尝试使用sscanf,但如何确保行中没有比我期望的更多的字段。 因此,如果我一行中有3个值,但我只需要两个值,那对我来说这是无效的行,但是当我使用sscanf时,我只读入2个变量,其余的均被忽略。 我如何检查整行以确保该行中没有垃圾,但是我不确定该期待什么,所以它不像我可以添加另一个变量,因为用户可以输入任何内容。 有人向我提到您可以在sscanf函数中使用*,但我不确定我如何无法在代码中实现它的任何地方找到它。


scanf()系列函数返回成功进行分配的次数。如果代码需要三个输入项,则无法仅凭sscanf()返回的值来判断是否提供了三个或更多输入项。

scanf()函数通过读取字符,尝试匹配该字符,进行分配(如果适用),然后移至下一个字符或从函数调用返回来操作。有一个转换说明符%n,用于存储到目前为止在此过程中读取的字符数(不增加读取的字符数)。此转换说明符可用于确定是否已通过调用sscanf()耗尽了输入。

下面的代码提供了一个演示。 fgets()收集的输入行包含换行符,除非输入太大而无法放入缓冲区数组中。 buffer[]足够大,可以存储合理大小的输入,但是更健壮的代码将更仔细地处理过大的输入。当sscanf()扫描输入字符串时,将依次读取每个字符,直到出现失败的匹配或到达字符串的末尾为止,因此匹配"%d %d %d %n"之后期望的读取字符数与输入的长度相同字符串,包括任何结尾的空格字符。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>
#include <string.h>

#define BUF_SZ  1024

int main(void)
{
    char buffer[BUF_SZ];
    int x, y, z;
    int pos;

    printf("Enter three integers:");
    fflush(stdout);

    // get user input
    if (fgets(buffer, sizeof buffer, stdin) != NULL) {

        // first check: does input match 3 integers?
        if (sscanf(buffer,"%d %d %d %n", &x, &y, &z, &pos) != 3) {
            puts("Incorrectly formatted input");
        } else {
            // second check: did sscanf() finish at the end of the buffer?
            int expected = strlen(buffer);
            if (pos != expected) {
                puts("Extra input in buffer");
                printf("expected = %d, pos = %d\
"
, expected, pos);
        } else {
            // everything OK
            printf("You entered: %d, %d, %d\
"
, x, y, z);
            }
        }
    }

    return 0;
}

互动示例:

1
2
3
4
5
6
7
8
9
10
>$ ./a.out
Enter three integers: 1 2 3
You entered: 1, 2, 3
>$ ./a.out
Enter three integers: 1 2
Incorrectly formatted input
>$ ./a.out
Enter three integers: 1 2 3 4
Extra input in buffer
expected = 8, pos = 6

如果希望甚至禁止尾随空白字符,则可以使用"%d %d %d%n"代替。请注意,为了使此功能起作用,必须从buffer[]中删除换行符,以便将其不算作额外的输入。一种典型的方法是使用buffer[strcspn(buffer,"\
\
")] = '\\0'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
int main(void)
{
    char buffer[BUF_SZ];
    int x, y, z;
    int pos;

    printf("Enter three integers:");
    fflush(stdout);

    // get user input
    if (fgets(buffer, sizeof buffer, stdin) != NULL) {

        // first check: does input match 3 integers?
        if (sscanf(buffer,"%d %d %d%n", &x, &y, &z, &pos) != 3) {
            puts("Incorrectly formatted input");
        } else {
            // remove trailing newline character
            buffer[strcspn(buffer,"\
\
"
)] = '\\0';
            // second check: did sscanf() finish at the end of the buffer?
            int expected = strlen(buffer);
            if (pos != expected) {
                puts("Extra input in buffer");
                printf("expected = %d, pos = %d\
"
, expected, pos);
        } else {
            // everything OK
            printf("You entered: %d, %d, %d\
"
, x, y, z);
            }
        }
    }

    return 0;
}


首先,您可以为确定必须存在的值提供转换说明符,然后添加"分配分配修饰符"以捕获所有剩余输入。我不确定您是在谈论sscanf,fscanf还是scanf。我将仅使用scanf进行说明。
下面的程序读取2个整数,并将所有剩余的输入放入一个字符串变量中,该变量的大小是动态分配的:

更新:使用sscanf而不是scanf。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
    int a,b;
    char *s;
    int n;
    char src[]="1 2 This is the remainder";
    n=sscanf(src,"%d %d %m[^\
]"
,&a,&b,&s);
    if(n>2)
        printf("s=%s\
"
, s), free(s);
    return 0;
}

$ ./a.out
s=This is the remainder