我经常看到人们劝阻其他人不要使用 scanf
并说有更好的选择。然而,我最终看到的是 “不要使用 scanf
” 或 “这是一个正确的格式字符串”,而且从来没有任何示例提到的“更好的选择”。
例如,让我们来看这段代码:
scanf("%c", &c);
这会读取上次转换后留在输入流中的空白。通常建议的解决方案是使用:
scanf(" %c", &c);
或者不使用scanf
。
由于 scanf
不好,有哪些 ANSI C 选项可以转换 scanf
通常可以处理的输入格式(例如整数、 float 和字符串)不使用 scanf
?
最佳答案
最常见的读取输入的方式是:
使用固定大小的
fgets
,这通常是建议的,并且使用
fgetc
,如果您只读取单个char
,这可能很有用。
要转换输入,您可以使用多种函数:
strtoll
, 将字符串转换为整数strtof
/d
/ld
,将字符串转为 floatsscanf
,它并不像简单地使用scanf
那样那么糟糕,尽管它确实有下面提到的大部分缺点在纯 ANSI C 中没有解析分隔符分隔的输入的好方法。要么使用 POSIX 的
strtok_r
,要么使用strtok
,它不是线程-安全的。你也可以 roll your own使用strcspn
和strspn
的线程安全变体,因为strtok_r
不涉及任何特殊的操作系统支持。这可能有点矫枉过正,但您可以使用词法分析器和解析器(
flex
和bison
是最常见的例子)。无需转换,直接使用字符串
由于我没有详细说明为什么 scanf
在我的问题中不好,所以我将详细说明:
使用转换说明符
%[...]
和%c
,scanf
不会占用空白。这显然并不广为人知,正如this question的许多重复所证明的那样。 .在引用
scanf
的参数(特别是字符串)时,对于何时使用一元&
运算符存在一些混淆。很容易忽略
scanf
的返回值。这很容易因读取未初始化的变量而导致未定义的行为。很容易忘记在
scanf
中防止缓冲区溢出。scanf("%s", str)
与gets
一样糟糕,甚至更糟。使用
scanf
转换整数时无法检测到溢出。 事实上,溢出导致undefined behavior在这些函数中。
关于c - 我可以使用什么来代替 scanf 进行输入转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58403537/