sscanf的后失踪%[^ - ]一个字符串的比赛

问题描述 投票:2回答:3

我有使用sscanf一个简单的程序。我遇到的问题是,匹配%[^-]s后,sscanf似乎只是停止匹配。

下面是简单的代码,明白我的意思。 %s%[^-]s %s比赛完全忽略。

注:我需要%[^-]s因为我需要我的程序同时匹配可能的字符串。

注2:我知道代码是完全不安全等,这只是一个例子!

#include <stdio.h>

int main(void) {
    int matches;
    int num1, num2, num3, num4;
    char *s1[10];
    char *s2[10];
    char *s3[40];
    char *s4[50];
    char *s5[50];
    char *s6[50];
    char *s7[50];

    char fileTest[] = "29 0 8:4 / / rw,relatime shared:1 - ext4 /dev/sda4 rw,errors=remount-ro";
    // char fileTest[] = "160 48 179:56 /inte /var/oil/gaol/org.something.org/media/internal ro,nosuid,relatime - ext4 /dev/mmccc rw,data=ordered";

    matches = sscanf(fileTest, "%d %d %d:%d %s %s %[^-]s %s",
                     &num1, &num2, &num3, &num4, s1, s2, s3, s4);

    printf("matches: %d\n", matches);
    printf("num1: %d\n", num1);
    printf("num2: %d\n", num2);
    printf("num3: %d\n", num3);
    printf("num4: %d\n", num4);
    printf("s1: %s\n", s1);
    printf("s2: %s\n", s2);
    printf("s3: %s\n", s3);
    printf("s4: %s\n", s4);

    return 0;
}
c scanf
3个回答
7
投票

需要注意的是s扫描设置后%[…]是字面s,而不是扫描集的一部分。在上下文中,%[^-]s永远比不上s,所以任何下列转换失败。该%[^-]部分吃掉任何不是一个破折号-(和s不是-,所以它得到chomped,用空格和其他事情一样),那么s不匹配(因为转换停止在-或字符串的结尾),所以扫描失败那里和最终%s从不匹配。

sscanf()的POSIX规范。阅读。重读它。重新再读一遍。再重新再读一遍。今天!而同样的明天。您可以缩减到一天两次一周的休息,那么一旦一个星期,每天和每周一次一个月,然后每月一次为今年余下时间,一年至少一次之后。函数的scanf()家庭可能是最困难的标准C函数使用得很好。

有你的代码的其他重大问题。特别是,char *s1[10];char s1[10];,并且类似地对于其它的阵列。或者你需要经过重大演习中的分配空间的阵列指向等。而且,正如你可能知道,%s(和%[^-])转换不限制的输入。使用%9s%49[^-]等,适当的大小。参见How to prevent scanf() causing a buffer overflow in C?


5
投票

格式说明,直到遇到一个%[^-] -匹配的一切;所以有此相匹配后,在缓冲区中的下一个字符要检查的格式字符串是-(如果有的话)。但是,如果你让这个模式遵循s,即%[^-]s,那么什么都不会匹​​配任何更多,因为-永远不匹配格式字符串所需s


2
投票

有你的代码中的多个问题:

  • 对于在字符类的sscanf格式是%[chars]%[^chars],有s之后没有拖尾]。在你的榜样,sscanf()将尝试在第三个字符串后匹配s和失败,防止后续%s的转换。
  • 目的地阵列s1通过s4char阵列,不char *的阵列。
  • 格式应该指定的最大字符数存储到目标阵列。你没有提到的代码是不安全的,所以你可能知道这一点,但最好是使它成为一个习惯这样做。
  • 因为%[^-]停止在-或输入字符串的末尾,通过%s解析过去的字符串将是-match计数将反映不存在-隔板。如果你想输入的其余部分,你应该使用%[^\n]

这里是一个修正版本:

#include <stdio.h>

int main(void) {
    int matches;
    int num1, num2, num3, num4;
    char s1[10], s2[10], s3[40], s4[50];

    char fileTest[] = "29 0 8:4 / / rw,relatime shared:1 - ext4 /dev/sda4 rw,errors=remount-ro";
    // char fileTest[] = "160 48 179:56 /inte /var/oil/gaol/org.something.org/media/internal ro,nosuid,relatime - ext4 /dev/mmccc rw,data=ordered";

    matches = sscanf(fileTest, "%d %d %d:%d %9s %9s %39[^-] - %49[^\n]",
                     &num1, &num2, &num3, &num4, s1, s2, s3, s4);

    printf("matches: %d\n", matches);
    printf("num1: %d\n", num1);
    printf("num2: %d\n", num2);
    printf("num3: %d\n", num3);
    printf("num4: %d\n", num4);
    printf("s1: %s\n", s1);
    printf("s2: %s\n", s2);
    printf("s3: %s\n", s3);
    printf("s4: %s\n", s4);

    return 0;
}

输出:

matches: 8
num1: 29
num2: 0
num3: 8
num4: 4
s1: /
s2: /
s3: rw,relatime shared:1
s4: ext4 /dev/sda4 rw,errors=remount-ro
© www.soinside.com 2019 - 2024. All rights reserved.