我正在尝试使用 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!
收到:(带标记的方框字符)
charCodeAt
可能只是返回 ASCII 中的索引。您需要的是 [0..n)
范围内的索引,在本例中 n
是 26。与 fromCharCode
相同的问题当然是在应用 %26
后接收到微小的值。通常,您可以减去/添加 A
或 a
的值以使值进入正确的范围。
一般来说,我建议添加将 ASCII 索引转换为字母表索引并再次转换回来的方法。这些可以单独测试。这种高度简洁的代码的问题是调试起来很糟糕;映射“流”中的值时会发生太多事情。
一个问题是代码错误地减少了值。 比如A的charcode是65,变成了20。 如果大小写无关紧要,您可以使用
String.fromCharCode((charCode - 65)%26 + 65)
这会将值置于大写字母的正确范围内。
一些问题:
有成千上万的字符不是字母,也不在您的标点符号正则表达式中。最好检查 letters:如果它不是英文字母表中的字符,则保持不变。
return checkPunctuation(char) ? char : char.charCodeAt()
是个坏主意:这意味着映射是混合类型:字符串(原始字符)或数字(它的代码点)。这会影响对这些值的进一步处理。见下一点
.map((code) => (code + shift) % 26)
期望 code
是一个数字,但它也可以是一个字符(标点符号,见上一点),然后 + shift
将执行字符串连接,在这种情况下 % 26
将产生 NaN
。这显然不是预期的。
.map((code) => (code + shift) % 26)
产生 0 到 25(和 NaN
)之间的数字,这不是字母的 ASCII 码,而是控制字符。
.map((charCode) => String.fromCharCode(charCode))
会将控制代码(和 NaN
)转换为它们的字符表示,也就是您看到的那些框。在转换为字符串之前,您需要将字母 'a' 的 ASCII 码添加回它。
示例调用错误。移动 2 不会给出“wpggh!”结果。为此,您需要使用 7 的移位(因为“w”出现在字母表中字母“p”之后的 7 个字母)。
这里是建议的更正:
const convertRange = (text, regex, a, shift) =>
text.replace(regex, letter =>
String.fromCharCode(
(letter.charCodeAt() - a.charCodeAt() + shift) % 26 + a.charCodeAt()
)
);
const caesarCipher = (text, shift) => {
text = convertRange(text, /[A-Z]/g, 'A', shift); // Cypher uppercase
return convertRange(text, /[a-z]/g, 'a', shift); // Cypher lowercase
};
console.log(caesarCipher("pizza!", 7));
这是一个有效的 Caesar's Cypher 函数,它将仅旋转 ASCII 字符 [A-Z] 和 [a-z]:
function cc(str,n){
return str.split("").map(c=>{
let a=c.charCodeAt(0)-1
if (a>63&&a<90||a>95&&a<122){
let off=64+Math.floor(a/96)*32
a=(a%32+n)%26+off;
}
return String.fromCharCode(a+1);
}).join("");
}
console.log(cc("Most fabulous - our Pizzas!",7));