scanf函数读取字符串时的长度条件

区别的核心只有一个:是否限制最大读取长度(安全性)


一句话结论(先记住)

scanf("%59999s", s) 是安全写法,scanf("%s", s) 是不安全写法。


一、它们在“做什么”上的区别

scanf("%s", s);

  • 读取任意长度的“非空白字符串”
  • 不检查数组大小
  • 如果输入比 s 的容量大 → 缓冲区溢出(UB)

scanf("%59999s", s);

  • 最多读取 59999 个字符
  • 给字符串末尾留 1 个位置放 '\0'
  • 保证不会写越界

这里的 59999 必须 ≤ 数组容量 - 1


二、为什么加数字就“安全”了?

%s 的完整格式其实是:

%[最大宽度]s

你写的:

char s[60000];
scanf("%59999s", s);

意思是:

最多读 59999 个字符,然后自动补 '\0'

所以最多占用:

59999 + 1 = 60000

正好等于数组大小,完全不越界


三、如果不用宽度限制,会发生什么?(关键)

例子

char s[10];
scanf("%s", s);

输入:

abcdefghijklmnop

结果:

  • scanf一直写
  • 覆盖 s 后面的内存
  • 可能:
    • 程序崩溃
    • 输出乱码
    • 静默错误(最危险)

👉 这是 C 里最经典、最致命的 bug 来源之一


四、对比表(非常建议记)

写法 是否限制长度 是否可能溢出 是否推荐
scanf("%s", s) ❌ 否 ✅ 会 ❌ 不推荐
scanf("%59999s", s) ✅ 是 ❌ 不会 ✅ 推荐

五、那为什么很多教材/代码还在用 %s

原因只有两个:

  1. 示例代码为了简短
  2. 假设输入“绝对安全”(OJ 已保证长度)

但在真实代码 / 好习惯 / 面试中:

永远不要相信输入是安全的


六、和 fgets 的关系(顺便一提)

fgets(s, sizeof(s), stdin);
  • 本身就带长度限制
  • 能读空格
  • 更安全

但:

  • 会读入 '\n'
  • 需要额外处理

所以:

  • 读单词scanf("%Ns", s)
  • 读整行fgets

七、一句话总结(背下来)

scanf("%s", s) 不限制长度,可能越界;
scanf("%Ns", s) 明确限制最大读取字符数,是安全写法。

posted @ 2026-01-18 12:38  Leon_LL  阅读(0)  评论(0)    收藏  举报