在C中,什么是sscanf的安全替代品?

时间:2012-02-12 01:37:40

标签: c

我在网上发现,在C ++中有另一种选择,但是普通的C呢?我感谢任何提示或建议。

3 个答案:

答案 0 :(得分:8)

这取决于你想用它做什么。

由于您在内存中有字符串,因此可以通过小心传递的参数来安全地避免缓冲区溢出。例如,如果您使用"%s"扫描字符串,只需使用足够大的目标缓冲区来保存可能存在的最大字符串(并确保源缓冲区是有效的字符串,即,它是'\0' - 已终止)。

所有*scanf()函数的一个危险是,如果您正在扫描数值,并且输入值太大而无法在目标类型中表示,则行为未定义。例如,这个程序:

#include <stdio.h>
int main(void) {
    const char *s = "999999999999999999999999999";
    int n;
    sscanf(s, "%d", &n);
    printf("n = %d\n", n);
    return 0;
}

有未定义的行为(除非INT_MAX真的很大)。

您可以使用strto*()函数安全地扫描数值:strtol()strtoll()strtoul()strtoull()strtof(),{{ 1}},strtod()。他们在错误上的行为有点棘手,但至少它的定义很明确。

答案 1 :(得分:4)

我相信你正在寻找“m”修饰符。它动态分配内存来保存提取的字符串,以避免缓冲区溢出。唯一的缺点是它是GNU扩展,所以例如MSVC可能无法识别它。

这是关于该主题的existing Stack Overflow answer

以下是如何使用它的示例:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    char *str;
    printf("Enter your name:\n");
    scanf("%ms", &str);

    printf("Hello %s!\n", str);
    free(str);
    return 0;
}

答案 2 :(得分:2)

在Windows下,您可以使用sscanf_s(请参阅https://msdn.microsoft.com/en-us/library/t6z7bya3.aspx),它要求您在缓冲区参数之后立即为每个%s匹配提供缓冲区长度作为参数。

例如,sscanf_s( tokenstring, "%s", s, (unsigned)_countof(s) );