凯撒密码(Caesar Cipher)JavaScript大小写保留逻辑求助
凯撒密码实现中保留大小写的正确逻辑方案
你的核心问题在于先将整个字符串转小写处理,再单独标记大写位置后修改,这个过程中字符串的索引操作会因为字符替换导致后续位置偏移,同时移位计算的逻辑可以更简洁。下面是正确的实现思路和代码:
正确实现思路
- 逐个处理每个字符,无需提前统一转小写
- 区分字符的大小写,分别基于
'A'(ASCII 65)或'a'(ASCII 97)计算移位 - 使用模运算处理字母循环(比如z后移3位到c),避免复杂的边界判断
- 非字母字符直接保留,不参与移位
优化后的代码
function ceasarCipher(word, cipher) { let result = ''; // 确保偏移量在0-25范围内,避免过大或负数偏移 cipher = cipher % 26; if (cipher < 0) cipher += 26; for (const char of word) { if (/[A-Z]/.test(char)) { // 处理大写字母 const originalPos = char.charCodeAt(0) - 'A'.charCodeAt(0); const newPos = (originalPos + cipher) % 26; result += String.fromCharCode(newPos + 'A'.charCodeAt(0)); } else if (/[a-z]/.test(char)) { // 处理小写字母 const originalPos = char.charCodeAt(0) - 'a'.charCodeAt(0); const newPos = (originalPos + cipher) % 26; result += String.fromCharCode(newPos + 'a'.charCodeAt(0)); } else { // 非字母直接添加 result += char; } } return result; } // 测试案例 console.log(ceasarCipher("x?Y!Z", 3)); // 输出:a?B!C console.log(ceasarCipher("hello", 2)); // 输出:jgnnq
原代码问题分析
- 索引偏移问题:你先把原字符串转小写生成
newWord,再通过trackCasing中的索引去修改大写,但每次slice操作会破坏原索引对应关系,导致后续大写位置修改错误 - 移位逻辑冗余:手动判断
i+cipher>25的方式可以用模运算替代,更简洁且避免边界错误 - 双重循环效率低:外层遍历每个字符,内层遍历字母表,时间复杂度为O(n*26),而直接用ASCII码计算是O(n),效率更高
原代码及HTML参考
原JavaScript代码
function ceasarCiper(word,cipher){ let word2 = word word = word.toLowerCase() //let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" let alphabet = "abcdefghijklmnopqrstuvwxyz" let newWord = "" for (let j = 0; j < word.length; j++){ if (!word[j].match(/[a-zA-Z]/i)){ newWord += word[j] } for (let i = 0; i < alphabet.length; i++){ if (alphabet[i] === word[j] && (i+cipher) > 25){ let remainder = (i+cipher) - 25 newWord += alphabet[remainder-1] } else{ if(alphabet[i] === word[j]){ console.log(cipher) console.log(alphabet[i + cipher], i, i+cipher) newWord += alphabet[i+cipher] } } }; }; console.log(word2) let trackCasing = [] for (let i = 0; i < word2.length; i++){ if(word2[i].match(/^[A-Z]*$/)){ trackCasing.push(i) } } console.log(trackCasing) let upWord = "" trackCasing.forEach(function(item){ console.log(newWord[item].toUpperCase()) upWord = newWord[item].toUpperCase() newWord = newWord.slice(0, item) + newWord.slice(item + 1) //newWord = newWord.slice(0, item) + newWord[item].toUpperCase() + newWord.slice(item) //console.log(upWord) newWord = newWord.slice(0, item) + upWord + newWord.slice(item) upWord = "" }) return newWord }; //console.log(ceasarCiper("hello", 2)) console.log(ceasarCiper("x?Y!Z", 3)) //failed test cases /* for (let i = 0; i < newWord.length; i++){ for (let j = 0; j < trackCasing.length; j++){ if (i === trackCasing[j]){ answer += newWord[i].toUpperCase() } else( answer += newWord[i] ) } } answer = [...new Set(answer)].join("")*/ /*let counter = trackCasing.length //string.replace(searchValue, replaceValue); while(counter){ for (let i = 0; i < trackCasing.length; i++){ console.log(trackCasing[i]) let a = newWord.replace(newWord.charAt(trackCasing[i]), newWord.charAt(trackCasing[i]).toUpperCase()) counter-- console.log(a) } }*/
原HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script type="" src="test4.js"></script> <title>Document</title> </head> <body> </body> </html>
内容的提问来源于stack exchange,提问作者Jermain Singleton
相关产品推荐
相关产品推荐

