简体   繁体   English

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

[英]In C, what is a safe alternative to sscanf?

I found online that in C++ there's an alternative, but what about plain-old C? 我在网上发现,在C ++中有一个替代方案,但是普通的C呢? I appreciate any tips or advice. 我感谢任何提示或建议。

It depends on what you want to do with it. 这取决于你想用它做什么。

Since you have the string in memory, you can safely avoid buffer overflows by being careful about the arguments you pass. 由于您在内存中有字符串,因此可以通过小心传递的参数来安全地避免缓冲区溢出。 For example, if you're scanning into a string, using "%s" , just use a target buffer big enough to hold the biggest string that could possibly be there (and make sure that the source buffer is a valid string, ie, that it's '\\0' -terminated). 例如,如果您使用"%s"扫描字符串,只需使用足够大的目标缓冲区来保存可能存在的最大字符串(并确保源缓冲区是有效字符串,即,这是'\\0'终止的)。

One danger of all the *scanf() functions is that if you're scanning a numeric value, and the input value is too big to be represented in the target type, the behavior is undefined. 所有*scanf()函数的一个危险是,如果您正在扫描数值,并且输入值太大而无法在目标类型中表示,则行为未定义。 For example, this program: 例如,这个程序:

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

has undefined behavior (unless INT_MAX is really really big). 有未定义的行为(除非INT_MAX真的很大)。

You can safely scan numeric values using the strto*() functions: strtol() , strtoll() , strtoul() , strtoull() , strtof() , strtod() , strtold() . 您可以使用strto*()函数安全地扫描数值: strtol()strtoll()strtoul()strtoull()strtof()strtod()strtold() Their behavior on errors is a bit tricky, but at least it's well defined. 他们对错误的行为有点棘手,但至少它的定义很明确。

I believe you're looking for the "m" modifier. 我相信你正在寻找“m”修饰符。 It dynamically allocates memory to hold the extracted string, so as to avoid buffer overflows. 它动态分配内存来保存提取的字符串,以避免缓冲区溢出。 The only drawback is that it's a GNU extension, so eg MSVC probably won't recognize it. 唯一的缺点是它是GNU扩展,所以例如MSVC可能无法识别它。

Here is an existing Stack Overflow answer on that topic. 这是该主题的现有Stack Overflow答案

Here's an example of how to use it: 以下是如何使用它的示例:

#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;
}

Under Windows, you can use sscanf_s (see https://msdn.microsoft.com/en-us/library/t6z7bya3.aspx ) which require you to provide the buffer length for every %s match as an argument right after the buffer argument. 在Windows下,您可以使用sscanf_s (请参阅https://msdn.microsoft.com/en-us/library/t6z7bya3.aspx ),它要求您在缓冲区参数之后立即为每个%s匹配提供缓冲区长度作为参数。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM