我有一个使用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;
}
答案 0 :(得分:7)
请注意,s
扫描集之后的%[…]
是文字s
,而不是扫描集的一部分。在上下文中,%[^-]s
将永远与s
不匹配,因此以下任何转换都会失败。 %[^-]
部分吞噬了所有不是破折号-
的东西(而s
不是-
,因此它变得残缺不全,以及空格和其他所有内容),则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?
答案 1 :(得分:5)
格式说明符%[^-]
匹配所有内容,直到遇到-
为止;因此,在匹配此字符串之后,缓冲区中要检查格式字符串的下一个字符是-
(如果有)。但是,如果让此模式遵循s
,即%[^-]s
,则将不再匹配,因为-
从不匹配格式字符串中所需的s
。 / p>
答案 2 :(得分:2)
您的代码中存在多个问题:
字符类的sscanf
格式为%[chars]
或%[^chars]
,在s
之后没有尾随的]
。在您的示例中,sscanf()
将尝试在第三个字符串后匹配s
并失败,从而阻止后续%s
的转换。
目标数组s1
至s4
应该是char
数组,而不是char *
的数组。
格式应指定要存储到目标数组中的最大字符数。您确实提到了代码不安全,因此您可能已经意识到了这一点,但是最好养成这样做的习惯。
因为%[^-]
停在-
或输入字符串的末尾,所以%s
解析的最后一个字符串将是-
或{{1} }计数将反映缺少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;
}