1

我正在用javascript构建一个凯撒密码。它使用一个随机设置的变量,称为currentkey密码密钥。它可以是从 -25 到 +25 的数字,跳过 0。

我无法弄清楚为什么函数在字符串的开头返回 undefined,或者为什么只要字符串继续翻译同一个字母,甚至为什么那个字母根本没有被翻译。

var currentkey = 5  //for example
function convertKey(str) {
    var o_text = str;
    var o_letters = o_text.split("");
    var alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','x','y','w','z']
    var c_text, _x = "";
    for (x in o_letters) {
        if (currentkey > 0) {
            _x = alphabet[alphabet.indexOf(x) + currentkey]
        } else {
            _x = alphabet[alphabet.indexOf(x) + (26 - currentkey)]
        }
        c_text = c_text + _x;
    }
    return c_text;
}

例如,运行convertKey("example")返回undefinedeeeeeee(未定义+“示例”中第一个字母的 7 倍)。

4

6 回答 6

3

在 JavaScript 中实现凯撒密码算法非常有趣,因为 JavaScript 缺乏真正的模运算符。% 只是除法的提醒。阅读这篇文章以获得更多解释。

但是,您可以轻松地将模数定义为自定义函数,然后继续执行 Caesar Cipher - 这是一种非常简单的加密形式,其中原始消息中的每个字母都向左或向右移动某个职位数。

要解密消息,我们只需将字母移回相同数量的位置。

例子:

  • 如果我们将所有字母移动 3 个位置,则 JAVASCRIPT 变为 MDYDVFULSW
  • 如果我们将所有字母向后移动 3 个位置,MDYDVFULSW 将返回 JAVASCRIPT。

如果在移动一个字母后超出了字母范围,那么该字母将被包裹在字母表中。示例:字母 Z 移动 3 个位置后变为 C。

这种“环绕”效果意味着使用模数。用数学术语来说,上面可以表示为:

En(x) = (x + n) mod 26

Dn(x) = (x – n) mod 26

在不使用适当的模运算符的情况下尝试在 JavaScript 中实现此算法将产生不正确的结果或非常神秘且难以理解的代码。

通过使用自定义模函数,代码以相同的方式表达数学方程:

// Function will implement Caesar Cipher to
// encrypt / decrypt the msg by shifting the letters
// of the message acording to the key
function encrypt(msg, key)
{
    var encMsg = "";

    for(var i = 0; i < msg.length; i++)
    {
        var code = msg.charCodeAt(i);

        // Encrypt only letters in 'A' ... 'Z' interval
        if (code >= 65 && code <= 65 + 26 - 1)
        {
            code -= 65;
            code = mod(code + key, 26);
            code += 65;
        }

        encMsg += String.fromCharCode(code);
    }

    return encMsg;
}

// Implement modulo by replacing the negative operand 
// with an equivalent positive operand that has the same wrap-around effect
function mod(n, p)
{
    if ( n < 0 )
        n = p - Math.abs(n) % p;

    return n % p;
}

玩得开心!

加密一些消息以试用代码。请记住:如果您使用正密钥进行加密,请使用互补的负密钥对其进行解密。您还可以使用此代码对出现在网络和新闻组上的那些 ROT13 消息进行解码。

如果您想了解其他在 JavaScript 中实现取模的方法,请参阅本文开头提到的文章。

于 2018-06-09T04:15:56.047 回答
2

(1) 你没有正确地遍历你的数组o_letters

(2) 你的数组越界了。

for (var i = 0; i < o_letters.length; i++) {
    _x = alphabet[(alphabet.indexOf(o_letters[i]) + currentkey + 26) % 26]
    c_text = c_text + _x;
}

此外,在您的代码中,您根本不需要.split("")

我会这样做:

var currentkey = 5  //for example
function convertKey(str) {
    var ret = '';
    for (var i = 0; i < str.length; i++) {
        ret += String.fromCharCode((str.charCodeAt(i) + currentKey + 26) % 26);
    }
    return ret;          
}

或者更简洁(但效率较低):

function convertKey(str) {
    return str.split('').map(function(c) {
       return String.fromCharCode((c.charCodeAt(0) + currentKey + 26) % 26);
    }).join('');       
}
于 2013-11-03T01:41:41.073 回答
2

这是在尝试将其与 连接之前undefined未初始化的结果。c_text_x

该代码仅适用于一个字母,因为alphabet.indexOf(x)返回-1(未找到)。使用 时o_text = "abc"x等于 0、1 和 2。因此,alphabet不存在 0、1 或 2 in 的索引(由-1结果指示)。您需要o_text通过更改indexOf(x)为来关联这些数字indexOf(o_text[x])。此外,为了防止超出数组的范围,您需要一个模运算将大于 26 的值(我曾经alphabet.length允许此代码与其他字母一起使用)包装回一个有效区域。因此,正确的代码如下(注意:我已按字母顺序将数组中的 'w' 移动到其正确位置,因为我假设它在您的示例中的位置是一个错误而不是故意的):

var currentkey = 5  //for example
function convertKey(str) {
    var o_text = str;
    var o_letters = o_text.split("");
    var alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
    var c_text="", _x = "";
    for (x in o_letters) {
        if (currentkey > 0) {
            _x = alphabet[(alphabet.indexOf(o_letters[x]) + currentkey) % alphabet.length]
        } else {
            _x = alphabet[(alphabet.indexOf(o_letters[x]) + (26 - currentkey)) % alphabet.length]
        }
        c_text = c_text + _x;
    }
    return c_text;
}

alert(convertKey('abcdefghijklmnopqrstuvwxyz'));

此警报的fghijklmnopqrstuvwxyzabcde

于 2013-11-03T02:03:42.927 回答
1

// 在https://www.freecodecamp.org/challenges/caesars-cipher工作

function rot13(str){    

var res = [];

var currentPosition;

var shiftedPosition;

for (var i = 0; i<str.length; i++){
    currentPosition = str.charCodeAt(i);

    if (currentPosition<65 || currentPosition>90){
    res.push(String.fromCharCode(currentPosition));
    }

    shiftedPosition = str.charCodeAt(i) - 13;

    if (currentPosition>=65 && shiftedPosition <65){
    res.push(String.fromCharCode(91-(13-(currentPosition-65))));
    }

    if (currentPosition>=78 && currentPosition<=90){
    res.push(String.fromCharCode(shiftedPosition));
    }
  }
return res.join('');`enter code here`
}

// Change the inputs below to test

rot13("GUR DHVPX OEBJA QBT WHZCRQ BIRE GUR YNML SBK.");
于 2017-08-07T17:33:14.117 回答
0

这是一个更简单的答案:

var rot = {
  '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',
  ' ': ' ',
  '.': '.',
  '!': '!',
  '?': '?'
};

// Change the inputs below to test
rot13("SERR CVMMN!");
// FREE CODE CAMP

function rot13(str) {
  var index = [];
  for (var key in str) {
    for (var property in rot) {
      if (str[key] === property) {
        index.push(rot[property]);
      }
    }
  }
  return index.join('');
}

于 2019-02-22T01:20:47.483 回答
0
function rot13(str) {
const alphabet1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXY';
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
return str
  .split('')
  .map(function(char) {  
    const pos = alphabet.indexOf(char);
    return pos >=0? alphabet1[pos+13] : char;     
  })
  .join('');
}
rot13("SERR PBQR PNZC");

  
于 2020-06-21T14:15:01.010 回答