我在网上发现,在C ++中有另一种选择,但是普通的C呢?我感谢任何提示或建议。
答案 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) );
。