C++实现凯撒密码加密小写z密钥≥6输出重音字符如何修复?
问题原因
问题本质是signed char类型溢出导致判断逻辑失效:
- 绝大多数C++编译器中
char默认是带符号类型,取值范围为-128 ~ 127 - 小写字母
'z'的ASCII值为122,当密钥≥6时,122 + 6 = 128超出signed char的最大值,发生整数溢出,值变为负数 - 此时
if (letter > 'z')判断条件(即判断是否大于122)对负数永远不成立,回绕逻辑不会触发,最终输出的是溢出后对应扩展ASCII表的重音字符 - 大写字母
'Z'的ASCII值为90,加常规密钥不会超过127,不会触发溢出,因此逻辑正常;密钥≤5时'z'+key ≤ 127,溢出不触发,判断也正常,完全符合你遇到的现象
修复方案
推荐使用「偏移量模运算」的写法,从根源避免溢出问题,逻辑也更清晰不易出错,修改后的encrypt函数如下:
string encrypt(string msg, int key) { // 先对key取模,避免密钥过大 key = key % 26; // 兼容负密钥场景,仅处理正加密的话可省略 if (key < 0) key += 26; char letter; for (int i = 0; i < msg.length(); i++) { letter = msg[i]; if (letter >= 'a' && letter <= 'z') { // 先转成0-25的偏移量,加密钥后模26再转回ASCII int offset = letter - 'a'; offset = (offset + key) % 26; msg[i] = offset + 'a'; } else if (letter >= 'A' && letter <= 'Z') { int offset = letter - 'A'; offset = (offset + key) % 26; msg[i] = offset + 'A'; } } return msg; }
临时兼容方案(保留原有逻辑)
如果你不想修改原有的回绕计算逻辑,仅需把char letter;改为unsigned char letter;即可,unsigned char取值范围为0~255,只要密钥不超过133都不会溢出,原有判断逻辑可以正常触发。
内容的提问来源于stack exchange,提问作者CJB 128
相关产品推荐
相关产品推荐

