c++ scanf和printf用法_c++ C语言风格输入输出

C++中不推荐使用scanf/printf,因其缺乏类型安全、易因格式符与参数类型不匹配导致崩溃或错误;应优先使用cin/cout,并在必须使用时严格校验格式符、避免混用流、检查返回值。

在 C++ 中直接用 scanfprintf 是可行的,但不是推荐做法——它们属于 C 标准库(),不支持 C++ 类型安全、重载或流操作语义,容易因格式符错配导致未定义行为。

为什么 scanf 容易崩溃或读错数据

scanf 要求格式字符串与变量地址严格匹配,且不检查类型。常见错误包括:

  • 忘记加 & 取地址(如对 int x; 写成 scanf("%d", x)
  • %dlong long(应为 %lld)或 float(应为 %f,但变量必须是 float*,不是 double*
  • 输入缓冲区残留(如前一个 scanf("%d") 后用户多按了回车,下一个 scanf("%c") 会直接读到换行符)

示例问题代码:

#include 
int main() {
    int x;
    char c;
    scanf("%d", x);     // ❌ 缺少 &x,栈破坏
    scanf("%c", &c);  // ❌ 可能读到上个输入留下的 \n
}

printf 的格式符和参数类型必须一一对应

printf 不做运行时类型检查,传错类型会导致输出乱码、截断甚至段错误(尤其在 64 位系统上):

  • int%dlong%ldlong long%lld
  • size_t(如 vector::size() 返回值)应使用 %zu,而非 %d%lu
  • std::string::c_str() 可传给 %s,但直接传 std::string 对象会编译失败(无隐式转换)

错误示例:

std::vector v = {1,2,3};
printf("size: %d\n", v.size()); // ❌ %d 匹配 int,但 size() 返回 size_t → 输出可能为负或截断

正确写法:

printf("size: %zu\n", v.size()); // ✅

混用 cin/coutscanf/printf 前必须同步关闭

默认情况下,C++ 流(cin/cout)和 C 流(stdin/stdout)是独立缓冲的。混用会导致:

  • 输出顺序错乱(printf 立即刷屏,cout 可能延迟)
  • 输入阻塞(cin >> x 后再用 scanf 读字符,可能跳过预期输入)

解决方法:在 main() 开头加

std::ios::sync_with_stdio(false); // 解绑 cin/cout 与 stdin/stdout
cin.tie(nullptr);                 // 解绑 cin 与 cout

注意:一旦调用该设置,就不能再混用 cinscanf(否则行为未定义)。若已用 scanf,就全程用 C 风格;若用 cin,就别碰 scanf

替代方案:什么时候真该用 scanf/printf

仅在以下场景可考虑保留 C 风格 I/O:

  • ACM/ICPC 等 OJ 平台要求极致输入速度(关闭同步后 scanfcin 快约 2–3 倍)
  • 对接遗留 C 接口,或日志函数只接受 printf-style 格

    式串
  • 需要精确控制浮点数输出格式(如 printf("%.6f", x)std::fixed 更简洁)

但即便如此,也要确保:

  • 所有格式符与参数类型完全匹配
  • 不混用 C/C++ 风格流
  • 对用户输入做容错处理(如检查 scanf 返回值是否等于期望读取项数)

例如安全读整数:

int x;
if (scanf("%d", &x) != 1) {
    // 输入失败,处理错误
}

真正麻烦的不是语法,而是格式符和类型的隐式契约——它不报错,只在某个平台、某种优化级别下突然崩掉。