凯撒密码(Caesar Cipher)移位问题:字母越界后转换异常求助
凯撒密码程序问题修复
我尝试开发一个凯撒密码(Caesar Cipher)程序,采用逐个字母转换为ASCII码、移位后再转回文本的实现方式,但仅当移位后字母不超过z时程序才能正常运行。
原代码:
const checkPunctuation = (text) => { return /[.,#!$%^&*;:{}=\-_`~()]/g.test(text); }; const ASCIIConverter = (text) => { return text.split("").map((char) => { return checkPunctuation(char)? char : char.charCodeAt(); }); }; const caesarCipher = (text, shift) => { return ASCIIConverter(text) .map((code) => (code + shift) % 26) .map((charCode) => String.fromCharCode(charCode)) .join(""); };
测试代码:
console.log(caesarCipher("pizza!", 2));
- 预期输出:
wpggh! - 实际输出:带标记的方框乱码字符
问题分析
- ASCII码逻辑错误:直接对字母的原始ASCII码执行
(code + shift) %26完全错误。比如小写字母p的ASCII码是112,112+2=114,114%26=10,对应ASCII的换行符,自然输出乱码。 - 混合类型处理bug:
ASCIIConverter返回的数组同时包含字符串(标点)和数字(字母ASCII码),后续map处理时,标点字符串加数字会变成拼接字符串,再取模会得到NaN,最终转换为无效字符。 - 未处理循环移位:原逻辑没考虑移位后超出z(或Z)的情况,也没支持负移位。
修复后的代码
// 判断是否为小写字母 const isLowerCase = (char) => /[a-z]/.test(char); // 判断是否为大写字母 const isUpperCase = (char) => /[A-Z]/.test(char); const caesarCipher = (text, shift) => { return text.split("").map((char) => { if (isLowerCase(char)) { // 转换为a-z的相对索引(0-25) const relativeCode = char.charCodeAt(0) - 'a'.charCodeAt(0); // 计算移位后的索引,处理负移位情况 const shiftedCode = (relativeCode + shift) % 26; const adjustedCode = shiftedCode < 0 ? shiftedCode + 26 : shiftedCode; // 转回ASCII码并转为字符 return String.fromCharCode(adjustedCode + 'a'.charCodeAt(0)); } else if (isUpperCase(char)) { // 大写字母逻辑同理 const relativeCode = char.charCodeAt(0) - 'A'.charCodeAt(0); const shiftedCode = (relativeCode + shift) % 26; const adjustedCode = shiftedCode < 0 ? shiftedCode + 26 : shiftedCode; return String.fromCharCode(adjustedCode + 'A'.charCodeAt(0)); } else { // 非字母字符直接返回 return char; } }).join(""); };
验证说明
运行console.log(caesarCipher("pizza!", 7));会得到预期输出wpggh!,说明原测试代码中的shift参数可能写错(从p到w需要移位7位而非2位)。如果使用shift=2,输出应为rkkec!,符合凯撒密码的移位规则。
内容的提问来源于stack exchange,提问作者hello_qwerty
相关产品推荐
相关产品推荐

