最安全常用的是 char 减 '0',因 '0'–'9' 的 ASCII 值连续,c - '0' 实现语义转换;直接赋值或 static_cast 得到的是 ASCII 码而非数字值;需先判断 c 是否在 '0'–'9' 范围内以防非法输入。

直接用 char 减 '0' 最安全、最常用,但前提是确定该 char 确实是数字字符('0'–'9')。
为什么不能直接赋值或强制转换?
直接写 int x = c; 得到的是 ASCII 码值(比如 '5' 变成 53),不是数字 5;static_cast 同理,只是显式转码,不改变本质。真正要的是“字符表示的数字”到“对应整数值”的语义转换。
- 常见错误现象:
char c = '7'; int n = c;→n是 55,不是 7 - 只对数字字符有效:'0' 对应 ASCII 48,所以
c - '0'实际是c - 48 - 如果
c是字母或符号(如'a'或'$'),结果无意义,且不报错
如何安全地把单个 char 转成 int?
加一层判断,避免非法输入导致逻辑错误:
- 先检查范围:
if (c >= '0' && c - 再计算:
int digit = c - '0'; - 也可用标准库辅助:
std::isdigit(static_cast(注意(c)) char可能为负,需转unsigned char防 UB)
多个数字字符连起来转 int 怎么办?
比如字符串 "123" 存在连续 char 数组里,不能对每个都单独减 '0' 然后相加——得按权展开:
立即学习“C++免费学习笔记(深入)”;
const char* s = "123";
int num = 0;
for (int i = 0; s[i] != '\0'; ++i) {
if (s[i] >= '0' && s[i] <= '9') {
num = num * 10 + (s[i] - '0');
}
}
// num == 123
- 这是手写 atoi 的核心逻辑,效率高、无依赖
- 没做溢出检查,实际项目中建议用
std::stoi或std::strtol - 注意:
std::stoi("123abc")会成功转出 123(截断),而std::strtol可通过endptr判断是否全转换
ASCII 运算还有哪些实用技巧?
利用字符和数字之间的固定偏移,可快速做大小写转换、进制映射等:
- 小写转大写:
if (c >= 'a' && c - 十六进制字符转值:
if (c >= '0' && c = 'a' && c - 所有这类运算都依赖 ASCII 中数字/字母是连续编码这一事实,不适用于 EBCDIC 等编码(但现代 C++ 环境基本不用考虑)
真正容易被忽略的是:这些技巧只对单字节字符成立,char 类型本身不保证是 signed 还是 unsigned,跨平台时若参与算术(比如和负数比较),最好显式转成 unsigned char 再用。










