0

我试图读取格式为 (int,int) 的输入,其中在开头和第一个 ( , ( 和第一个 int 之间,在第一个 int 和逗号之间等等之间可能有 N 个空格,依此类推,直到最后也可以是 ) 和输入结尾之间的 N 个空格。

例如:$ _( int, int )___ ._作空格。

到目前为止,我有这个,但它不工作:

scanf("%*[](%*[]%d%*[],%*[]%d%*[])%*[])")

my%*[]将用于忽略空格。

有人可以帮助我吗?

4

4 回答 4

0

"%*[]"忽略空格。 "%*[](%*[]"说要消耗']', '(', '%', '*','['字符。

//  v---v  scanset
"%*[](%*[]"

"%*[ ]"确实消耗空格,但只消耗空格,而不是所有空格。

使用" "to 忽略所有空格(包括'\n')。


给定任意数量的空白使用$ _( int, int )___ .的格式_

int n = 0;
int result = scanf(" $ (%d ,%d ) .%n", &int1, &int2, &n);
if ((result != 2) || (n == 0)) {
  ; // failed, handle error.
}

让我们分解 scanf() 格式

" "匹配 0 到无限数量的空白。
"$" match a '$'
"(" match'('
"%d"匹配任意数量的前导空格,然后查找int,存储在相应的int *.
"," match ','
")" match ')'
"." match将到目前为止已解析'.'
"%n"的数量保存到相应的. 执行此指令不会影响结果。charint *scanf()

%n如果需要比此解决方案中建议的更具体的扫描,则可以散布使用。

于 2013-10-24T04:44:14.987 回答
0

scanf() 和 sscanf() 通常希望跳过空格。格式中的一个空格足以指定它。因为您只关心这两个 int,所以您不需要向 scanf() 提供有关第二个 int 之后的任何信息。line如果可以接受,只需从第一个空格之后的空格开始查看,(然后一直到最后一个 int。这是一个使用一些“指针魔术”的示例,其中line是一个字符缓冲区,并且没有测试 ptr+1 处是否有任何内容:

char *ptr = 0;
int x = 0, y = 0, n = 0;

for( ptr = line; *ptr; p++ )
    if( *ptr == '(' ) break;
n = sscanf( ptr+1, " %d, %d", &x, &y );

n 将包含分配的字段数(在这种情况下应该是两个),并且 x 和 y 是您感兴趣的两个整数。

同样,要使用 scanf(),您可以捕获并丢弃第一部分:

n = scanf( "%s ( %d, %d", garbage, &x, &y );

垃圾是一个足够大的字符缓冲区,你永远不必看。在这种情况下,n 将是 3。

于 2013-10-23T22:45:03.583 回答
0

试试这个:scanf("%*[ ](%*[ ]%d%*[ ],%*[ ]%d%*[ ])%*[ ]",&a,&b);whereab是两个整数。在您的问题中,缺少整数变量的部分。

于 2013-10-23T22:39:12.730 回答
0

我现在知道这是一个老问题,但它仍然可以在搜索中找到。我偶然发现它正在寻找其他东西,并惊讶于还没有简单的正确答案。

假设 N 不是特定数量的空格,则要使用的格式字符串是 " (%d%1s%d )" 将其分解,

  • " " 扫描 0 个或多个空白字符
  • "(" 匹配左括号
  • "%d" 读取第一个整数,跳过它之前的任何空格
  • "%1s" 跳过逗号前的任何空格并读取一个 1 字符的字符串,它应该是一个逗号
  • "%d" 读取第二个整数,再次跳过空格
  • " " 扫描 0 个或多个空白字符
  • ")" 匹配右括号

下面是一个使用 sscanf() 的示例程序,它采用与 fprintf() 相同的格式字符串。

#include <stdio.h>

int main(void) {
    const char tests[] =
        "(1,2)"
        "(3, 4   )"
        "  (   5 , 6   )"
        "  (7 ,8)"
    ;

    const char *string_to_scan = tests;
    for ( ;  ; ) {
        int n1, n2;
        int n_char_read;
        char s[2];
        const int rc_scan = sscanf(string_to_scan, " (%d%1s%d )%n",
                &n1, s, &n2, &n_char_read);
        if (rc_scan == EOF) { /* End of string reached */
            break;
        }
        if (rc_scan != 3 || *s != ',') {
            (void) fprintf(stderr, "Scan error!\n");
            break;
        }
        (void) fprintf(stdout, "Read %d characters. n1=%d and n2=%d\n",
                n_char_read, n1, n2);
        string_to_scan += n_char_read;
    }

    return 0;
}

输出:

Read 5 characters. n1=1 and n2=2
Read 9 characters. n1=3 and n2=4
Read 15 characters. n1=5 and n2=6
Read 8 characters. n1=7 and n2=8

请注意,%n 用于单步执行测试字符串。重要的是在格式字符串中使用 %1s 而不是 %s,以防止在读取 (1,,2) 之类的格式错误的字符串时缓冲区溢出。

另一种稍微复杂但更紧凑的替代方法使用 [,] 仅扫描数字之间的逗号,并且不使用 * 抑制将其分配给任何变量。请注意,在带有 [,] 的说明符之前需要一个前导空格来跳过任何前导空格,这不会像使用 %s 那样自动发生。

int main(void) {
    const char tests[] =
        "(1,2)"
        "(3, 4   )"
        "  (   5 , 6   )"
        "  (7 ,8)"
    ;

    const char *string_to_scan = tests;
    for ( ;  ; ) {
        int n1, n2;
        int n_char_read;
        const int rc_scan = sscanf(string_to_scan, " (%d %*1[,]%d )%n",
                &n1, &n2, &n_char_read);
        if (rc_scan == EOF) { /* End of string reached */
            break;
        }
        if (rc_scan != 2) {
            (void) fprintf(stderr, "Scan error!\n");
            break;
        }
        (void) fprintf(stdout, "Read %d characters. n1=%d and n2=%d\n",
                n_char_read, n1, n2);
        string_to_scan += n_char_read;
    }
}
于 2019-12-27T19:05:18.507 回答