-1

I'm very new to python so bear with me. I'm putting together a little crypto puzzle and part of it requires a substitution cipher. In this case each letter is replaced with three random letters. Every time I run this code it throws an error when I try to encrypt something:

Traceback (most recent call last):
File "/home/pi/Desktop/expansion cipher.py", line 159, in <module>
crypt()
File "/home/pi/Desktop/expansion cipher.py", line 142, in crypt
print encrypt(txt)
File "/home/pi/Desktop/expansion cipher.py", line 127, in encrypt
ctxt = ctxt + exp_ciph(ptxt[counter])
File "/home/pi/Desktop/expansion cipher.py", line 121, in exp_ciph
return cur_exp
UnboundLocalError: local variable 'cur_exp' referenced before assignment

Here is my code:

def rev_ciph(char):
    if char == "gps":
        cur_rev = "_"
    if char == "evl":
        cur_rev = "."
    if char == "jkb":
        cur_rev = "e"
    if char == "bhj":
        cur_rev = "t"
    if char == "szk":
        cur_rev = "a"
    if char == "nwu":
        cur_rev = "o"
    if char == "dpl":
        cur_rev = "i"
    if char == "sbg":
        cur_rev = "n"
    if char == "dsl":
        cur_rev = "s"
    if char == "yhq":
        cur_rev = "p"
    if char == "sav":
        cur_rev = "h"
    if char == "gfs":
        cur_rev = ","
    if char == "rtg":
        cur_rev = "d"
    if char == "fqu":
        cur_rev = "l"
    if char == "rjt":
        cur_rev = "u"
    if char == "sbv":
        cur_rev = "c"
    if char == "yqm":
        cur_rev = "m"
    if char == "ywh":
        cur_rev = "f"
    if char == "drt":
        cur_rev = "y"
    if char == "zfd":
        cur_rev = "w"
    if char == "asn":
        cur_rev = "g"
    if char == "fzj":
        cur_rev = "p"
    if char == "rka":
        cur_rev = "b"
    if char == "kzv":
        cur_rev = "v"
    if char == "lah":
        cur_rev = "k"
    if char == "rma":
        cur_rev = "x"
    if char == "fqn":
        cur_rev = "q"
    if char == "vrq":
        cur_rev = "j"
    if char == "tfv":
        cur_rev = "z"
    return cur_rev

def exp_ciph(char):
    if char == "_":
        cur_exp = "gps"
    if char == ".":
        cur_exp = "evl"
    if char == "e":
        cur_exp = "jkb"
    if char == "t":
        cur_exp = "bhj"
    if char == "a":
        cur_exp = "szk"
    if char == "o":
        cur_exp = "nwu"
    if char == "i":
        cur_exp = "dpl"
    if char == "n":
        cur_exp = "sbg"
    if char == "s":
        cur_exp = "dsl"
    if char == "p":
        cur_exp = "yhq"
    if char == "h":
        cur_exp = "sav"
    if char == ",":
        cur_exp = "gfs"
    if char == "d":
        cur_exp = "rtg"
    if char == "l":
        cur_exp = "fqu"
    if char == "u":
        cur_exp = "rjt"
    if char == "c":
        cur_exp = "sbv"
    if char == "m":
        cur_exp = "yqm"
    if char == "f":
        cur_exp = "ywh"
    if char == "y":
        cur_exp = "drt"
    if char == "w":
        cur_exp = "zfd"
    if char == "g":
        cur_exp = "asn"
    if char == "p":
        cur_exp = "fzj"
    if char == "b":
        cur_exp = "rka"
    if char == "v":
        cur_exp = "kzv"
    if char == "k":
        cur_exp = "lah"
    if char == "x":
        cur_exp = "rma"
    if char == "q":
        cur_exp = "fqn"
    if char == "j":
        cur_exp = "vrq"
    if char == "z":
        cur_exp = "tfv"
    return cur_exp

def encrypt(ptxt):
    ctxt = "Ciphertext: "
    counter = 0
    while counter <= len(ptxt):
        ctxt = ctxt + exp_ciph(ptxt[counter])
        counter += 1
    return ctxt

def decrypt(ctxt):
    ptxt = "Plaintext: "
    counter = 0
    while counter <= len(ctxt):
        ptxt = ptxt + rev_ciph(ctxt[counter])
        counter += 1
    return ptxt

def crypt():
    print
    txt = raw_input("Plaintext: ")
    print encrypt(txt)
    print

def ucrypt():
    print
    txt = raw_input("Ciphertext: ")
    print decrypt(txt)
    print

ex_code = False
while ex_code == False:
    print "(1) Encrypt"
    print "(2) Decript"
    print "(3) Exit"
    print
    mchoc = raw_input("What would you like to do(1,2,3?): ")
    if mchoc == "1":
        crypt()
    if mchoc == "2":
        ucrypt()
    if mchoc == "3":
        ex_code = True
    print

1 Answers1

0

You have two problems. The first is that you aren't handling all possible inputs. Having just copied and tested you code, I see that you get UnboundLocalError: local variable 'cur_exp' referenced before assignment if and only if you try to encrypt something that includes a character that isn't handled by exp_ciph(char) (or rev_ciph(char) for that matter). Neither of these functions handles capital letters, for instance. Python is ALWAYS case sensitive, and regards capital and lower case letters as entirely different characters. Your functions also don't handle other characters, such as "," and ";". If you give the program a string to encrypt that includes a character not handled by your first two functions, then, when that character comes up, all of the conditions for the if statements in these functions are false, and thus cur_exp is never created and assigned a value. When one of these functions then tries to return cur_exp, it finds that cur_exp doesn't exist. That is the source of the error you describe above.

If you input a string consisting ONLY of lower case letters and possibly "_", the you get an entirely different error, namely:

IndexError: string index out of range

This is because the function encrypt(ptxt) always goes looking for one more character than a string has. In Python (and, I think, every programming language) the elements in an iterable such as a string or a list are indexed by their OFFSET from the first item; that is, how many items are in front of it. So, if you have a string foo with 4 charachters:

foo = "abcd"

then:

foo[0] == "a"
foo[1] == "b"
foo[2] == "c"
foo[3] == "d"

There is no foo[4]. Calling foo[4] will raise exactly the above error. The len(object) function returns the number of items in an iterable. So, keeping with the above example,

len(foo) == 4

and thus calling

foo[len(foo)]

will raise IndexError:. This is EXACTLY what always happens in your encrypt(ptxt) function here

counter = 0
while counter <= len(ptxt):
    ctxt = ctxt + exp_ciph(ptxt[counter])
    counter += 1

You will want to do this instead:

counter = 0
while counter <= len(ptxt) - 1:
    ctxt = ctxt + exp_ciph(ptxt[counter])
    counter += 1

Those are the first two problem I encounter running this. I won't guarantee there are no more. Hopefully this gets you farther down the path though.

clj
  • 303
  • 2
  • 5
  • 13