c - 我可以使用什么来代替 scanf 进行输入转换?

标签 c scanf

我经常看到人们劝阻其他人不要使用 scanf 并说有更好的选择。然而,我最终看到的是 “不要使用 scanf“这是一个正确的格式字符串”,而且从来没有任何示例提到的“更好的选择”

例如,让我们来看这段代码:

scanf("%c", &c);

这会读取上次转换后留在输入流中的空白。通常建议的解决方案是使用:

scanf(" %c", &c);

或者不使用scanf

由于 scanf 不好,有哪些 ANSI C 选项可以转换 scanf 通常可以处理的输入格式(例如整数、 float 和字符串)不使用 scanf?

最佳答案

最常见的读取输入的方式是:

  • 使用固定大小的 fgets,这通常是建议的,并且

  • 使用 fgetc,如果您只读取单个 char,这可能很有用。

要转换输入,您可以使用多种函数:

  • strtoll, 将字符串转换为整数

  • strtof/d/ld,将字符串转为 float

  • sscanf,它并不像简单地使用 scanf 那样那么糟糕,尽管它确实有下面提到的大部分缺点

  • 在纯 ANSI C 中没有解析分隔符分隔的输入的好方法。要么使用 POSIX 的 strtok_r,要么使用 strtok,它不是线程-安全的。你也可以 roll your own使用 strcspnstrspn 的线程安全变体,因为 strtok_r 不涉及任何特殊的操作系统支持。

  • 这可能有点矫枉过正,但您可以使用词法分析器和解析器(flexbison 是最常见的例子)。

  • 无需转换,直接使用字符串


由于我没有详细说明为什么 scanf 在我的问题中不好,所以我将详细说明:

  • 使用转换说明符 %[...]%cscanf 不会占用空白。这显然并不广为人知,正如this question的许多重复所证明的那样。 .

  • 在引用 scanf 的参数(特别是字符串)时,对于何时使用一元 & 运算符存在一些混淆。

  • 很容易忽略scanf 的返回值。这很容易因读取未初始化的变量而导致未定义的行为。

  • 很容易忘记在scanf 中防止缓冲区溢出。 scanf("%s", str)gets 一样糟糕,甚至更糟。

  • 使用 scanf 转换整数时无法检测到溢出。 事实上,溢出导致undefined behavior在这些函数中。


关于c - 我可以使用什么来代替 scanf 进行输入转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58403537/

相关文章:

c - C 中的 fork() 信号子进程和父进程

c++ - 尝试扫描到全局 int 时出现奇怪的错误

检查用户是否输入了 int - C

C fprintf 编码字符串跳过

c - 当存在 powl() 时,sscanf() 会导致链接失败

将 char* 转换为字符串,然后分配给结构成员 : initialization makes integer from pointer

c - gcc 禁用几行代码的所有警告

c - 我对 C 编程完全陌生,并且不断遇到段错误

c - vim 保持自动完成弹出窗口

c - 为什么 `scanf()` 函数将 %s 和 %c 视为同一类型?