Search code examples
javascriptstringfor-in-loopencryption

Caesar Cipher in javascript: cipher broken


I'm building a Caesar Cipher in javascript. It uses a randomly set variable called currentkey as the cipher's key. it can be a number from -25 to +25, skipping 0.

I can't figure out why the function returns undefined in the beginning of the string, or why it translates the same letter for as long as the string goes, or even why that letter doesn't get translated at all.

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;
}

For example, running convertKey("example") returns undefinedeeeeeee (undefined + 7 times the first letter in "example").


Solution

  • The undefined is a result of not initializing c_text before you try concatenate it with _x.

    The code only works on one letter because alphabet.indexOf(x) returns -1 (not found). When using o_text = "abc", x equals 0, 1, and 2. Thus, the index of 0, 1, or 2 in alphabet is nonexistent (indicated by the -1 result). You need to relate those numbers back to o_text by changing indexOf(x) to indexOf(o_text[x]). Also, to prevent going outside the bounds of your array, you need a modulus operation to wrap values greater than 26 (I've used alphabet.length to allow this code to work with other alphabets) back around into a valid region. Thus, the correct code would be as follows (note: I've moved 'w' in your array into its proper location alphabetically, as I assumed its location in your example was an error and not intentional):

    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'));
    

    This alert's fghijklmnopqrstuvwxyzabcde