一个只破译第二个字母的破译器
A decipher which only deciphers every second letter
所以我正在制作一个函数来破译 rot13 或凯撒密码的变体。但出于某种原因,它每隔一个字母就会破译一次……我不知道该改变或做什么。谢谢
function rot13(str) {
let regexp = /\w/gi;
let obj = {
"A": "N",
"B": "O",
"C": "P",
"D": "Q",
"E": "R",
"F": "S",
"G": "T",
"H": "U",
"I": "V",
"J": "W",
"K": "X",
"L": "Y",
"M": "Z",
"N": "A",
"O": "B",
"P": "C",
"Q": "D",
"R": "E",
"S": "F",
"T": "G",
"U": "H",
"V": "I",
"W": "J",
"X": "K",
"Y": "L",
"Y": "M",
};
for (let i = 0; i < str.length; i++) {
if (regexp.test(str[i])) {
str = str.replace(str[i], obj[str[i]]);
}
};
return str;
}
console.log(rot13("SERR"));
//output: FEER
//wanted output: FREE
这似乎工作正常
const rot13 = (str) => {
const base = 'A'.charCodeAt()
return str
.split('')
.map(c => String.fromCharCode(((c.charCodeAt() - base + 13) % 26) + base)).join('')
}
console.log(rot13('SERR'))
您有两个问题:
- 在正则表达式上使用
g
标志时,正则表达式变为有状态的,并且 .test
方法会跟踪它在字符串中搜索的位置。 From MDN:
As with exec()
(or in combination with it), test()
called multiple times on the same global regular expression instance will advance past the previous match.
这意味着当你使用全局标志时,一旦正则表达式匹配了一个字符,它将不会匹配另一个直到它被重置:
const rgx = /\w/g;
console.log("Different results!:", rgx.test("a"), rgx.test("a"))
这就是您看到的“每个其他字符”替换的原因,因为循环中的 if 条件只会在每隔一次通过时执行。
要解决此问题,请避免在正则表达式上使用 g
标志,除非您需要有状态的行为。
第二期:
- 当使用
.replace
方法并将字符串作为第一个参数时,只会替换该字符串的第一个实例。
这意味着如果您要替换的字符出现得较早,则将交换较早的字符,而不是当前索引处的字符。
console.log("Only the first is replaced!:", "aaaa".replace("a", "b"))
对此进行调整的一种方法是不使用 .replace
尝试交换字符,而是使用 .slice
重建字符串,同时更改其对应字符的编码字符。此方法确保更改的字符是您当前索引处的字符 i
:
str = str.slice(0, i) + obj[str[i]] + str.slice(i+1)
综上所述,您可以像这样修改代码段:
function rot13(str) {
let regexp = /\w/i; // No global match!
let obj = {
"A": "N",
"B": "O",
"C": "P",
"D": "Q",
"E": "R",
"F": "S",
"G": "T",
"H": "U",
"I": "V",
"J": "W",
"K": "X",
"L": "Y",
"M": "Z",
"N": "A",
"O": "B",
"P": "C",
"Q": "D",
"R": "E",
"S": "F",
"T": "G",
"U": "H",
"V": "I",
"W": "J",
"X": "K",
"Y": "L",
"Z": "M",
};
for (let i = 0; i < str.length; i++) {
if (regexp.test(str[i])) {
str = str.slice(0, i) + obj[str[i]] + str.slice(i+1)
}
};
return str;
}
console.log(rot13("SERR"));
//output: FREE
所以我正在制作一个函数来破译 rot13 或凯撒密码的变体。但出于某种原因,它每隔一个字母就会破译一次……我不知道该改变或做什么。谢谢
function rot13(str) {
let regexp = /\w/gi;
let obj = {
"A": "N",
"B": "O",
"C": "P",
"D": "Q",
"E": "R",
"F": "S",
"G": "T",
"H": "U",
"I": "V",
"J": "W",
"K": "X",
"L": "Y",
"M": "Z",
"N": "A",
"O": "B",
"P": "C",
"Q": "D",
"R": "E",
"S": "F",
"T": "G",
"U": "H",
"V": "I",
"W": "J",
"X": "K",
"Y": "L",
"Y": "M",
};
for (let i = 0; i < str.length; i++) {
if (regexp.test(str[i])) {
str = str.replace(str[i], obj[str[i]]);
}
};
return str;
}
console.log(rot13("SERR"));
//output: FEER
//wanted output: FREE
这似乎工作正常
const rot13 = (str) => {
const base = 'A'.charCodeAt()
return str
.split('')
.map(c => String.fromCharCode(((c.charCodeAt() - base + 13) % 26) + base)).join('')
}
console.log(rot13('SERR'))
您有两个问题:
- 在正则表达式上使用
g
标志时,正则表达式变为有状态的,并且.test
方法会跟踪它在字符串中搜索的位置。 From MDN:
As with
exec()
(or in combination with it),test()
called multiple times on the same global regular expression instance will advance past the previous match.
这意味着当你使用全局标志时,一旦正则表达式匹配了一个字符,它将不会匹配另一个直到它被重置:
const rgx = /\w/g;
console.log("Different results!:", rgx.test("a"), rgx.test("a"))
这就是您看到的“每个其他字符”替换的原因,因为循环中的 if 条件只会在每隔一次通过时执行。
要解决此问题,请避免在正则表达式上使用 g
标志,除非您需要有状态的行为。
第二期:
- 当使用
.replace
方法并将字符串作为第一个参数时,只会替换该字符串的第一个实例。
这意味着如果您要替换的字符出现得较早,则将交换较早的字符,而不是当前索引处的字符。
console.log("Only the first is replaced!:", "aaaa".replace("a", "b"))
对此进行调整的一种方法是不使用 .replace
尝试交换字符,而是使用 .slice
重建字符串,同时更改其对应字符的编码字符。此方法确保更改的字符是您当前索引处的字符 i
:
str = str.slice(0, i) + obj[str[i]] + str.slice(i+1)
综上所述,您可以像这样修改代码段:
function rot13(str) {
let regexp = /\w/i; // No global match!
let obj = {
"A": "N",
"B": "O",
"C": "P",
"D": "Q",
"E": "R",
"F": "S",
"G": "T",
"H": "U",
"I": "V",
"J": "W",
"K": "X",
"L": "Y",
"M": "Z",
"N": "A",
"O": "B",
"P": "C",
"Q": "D",
"R": "E",
"S": "F",
"T": "G",
"U": "H",
"V": "I",
"W": "J",
"X": "K",
"Y": "L",
"Z": "M",
};
for (let i = 0; i < str.length; i++) {
if (regexp.test(str[i])) {
str = str.slice(0, i) + obj[str[i]] + str.slice(i+1)
}
};
return str;
}
console.log(rot13("SERR"));
//output: FREE