使用scanf跳过N个空格

时间:2013-10-23 21:48:35

标签: c scanf

我试图以格式(int,int)读取一个输入,其中在beggining和1st(,(和第一个int之间,第一个int和逗号之间)之间可能有N个空格,依此类推结尾处也可以是N个白色空格)和输入结束。

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

到目前为止,我有这个,但它无法正常工作:

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

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

有人能帮助我吗?

4 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

scanf()和sscanf()通常想要跳过空格。格式化中的一个空格足以指定它。因为你只关心这两个int,所以你不需要给scanf()任何有关第二个int之后的内容的信息。如果可以接受,只需从刚刚超过第一个line的空格开始查看(,然后再查看最后一个int。这是一个使用一些'指针魔术'的例子,其中line是一个char缓冲区,并没有测试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将包含分配的字段数(在这种情况下应为2),x和y是您感兴趣的两个整数。

类似地,使用scanf(),你可以抓住并扔掉第一部分:

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

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

答案 2 :(得分:0)

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

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

让我们打破scanf()格式

"$"匹配'$'
" "匹配0到无限数量的空格。
"("匹配'('
"%d"匹配任意数量的前导空格,然后查找int,并存储在相应的int *中。
","匹配','
")"匹配')'
"."匹配'.'
"%n"将目前为止解析的char个数保存到相应的int *中。对此指令起作用不会影响scanf()结果。

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

答案 3 :(得分: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;
    }
}