简体   繁体   中英

how do i use rot 13 on a file in python

im trying to rewrite every character in a file with rot 13 and im stuck, im not sure how to go through the file and look at every character and not worry about the spaces between paragraphs

# [import statements]
import q2fun
# [constants]

# [rest of program code]
f = open("rot-13.txt", "w", encoding="utf-8")
result = q2fun.rot13(f)

def rot13(f):

    f.seek(0)
#   y = 0
    result = ""
    for char in f:
        x = ord(char)
        if 97 <= x < 110 or 65 <= x < 78:
#           string[y]=char.replace(char, chr(x+13))
            char = char.replace(char, chr(x + 13))
            result = result + char
            print(char)
            continue
#           y+=1
        elif x >= 110 or 78 <= x < 91:
#           string[y]=char.replace(char, chr(x-13))
            char = char.replace(char, chr(x - 13))
            print(char)
            result = result + char
            continue
#           y+=1
        result = result + char
    return result
import codecs


with open("plaintext.txt") as f_in, open("rot-13.txt", "w") as f_out:
    f_out.write(codecs.encode(f_in.read(),"rot_13"))

with open("rot-13.txt") as encoded:
    print (codecs.decode(encoded.read(),"rot_13"))

See the documentation on the codecs module, or the built-in help in the interactive interpreter, for an explanation of these functions. See the documentation on the Standard Encodings (and following sections), or import the encodings module and use the built-in help , to see a list of encodings you can use with these functions.

If you just want to do this as easily as possible, use the rot_13 codec, as described in Joran Beasley's answer.

If you want to know how to do it manually, or what was wrong with your existing code, I can explain. You're actually very close.

If f is a file, for char in f: iterates over the lines of the file, not the characters . If you want to iterate over the characters one by one, either loop around f.read(1) , or read the whole thing into a string with s = f.read() and then iterate over s .

If you fix that, your program now works as written. However, it's more complicated than necessary.

First, char = char.replace(char, chr(x + 13)) is unnecessary. str.replace searches the string, substitutes the replacement character for all instances of the search character, and returns the resulting string. But you don't need any of that—you're searching all one character, replacing the one instance of the search character with the resulting character, and returning the resulting character as a one-character string—in other words, the same string you already had. All you want to do here is char = chr(x + 13) .

Also, you can remove the three separate result = result + char and continue ; all three conditions lead to the same thing.

Also, instead of comparing x to ordinal values (which are hard to read, and easy to get wrong), you can just compare char to character values. So:

def rot13(f):
    s = f.read()
    result = ""
    for char in s:
        x = ord(char)
        if 'a' <= char <= 'm' or 'A' <= char <= 'M':
            char = chr(x + 13)
        elif 'n' <= char <= 'z' or 'N' <= char <= 'Z':
            char = chr(x - 13)
        result = result + char
    return result

You can simplify your comparisons further by using str.lower :

        if 'a' <= char.lower() <= 'm':

(This replaces the if 'a'… line in the above code, and you do the same thing for the elif 'n'… line.)

You can simplify things even further by using the collections in the string class:

        if char in string.ascii_letters:
            if char.lower() <= 'm':
                char = chr(x + 13)
            else:
                char = chr(x - 13)

(This replaces the whole if / elif block.)

Or, if you know that the % (mod/remainder) operator does, you can simplify it even further: rot13(ch) is just (ch+13) % 26 (where ch is a letter number from 0 to 25 , which you can get with ord(char) % 32 ). The usual C implementations take advantage of this, and you can write them more clearly with the divmod function in Python. But I'll leave that as an exercise for the reader.

An old-school implementation with python3


def ROT_13(realText):
    outText = ""
    cryptText = []
    step = 13
    uppercase = ['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']
    lowercase = ['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']
    puncuation = [",","'",":","!","~","`","@","#","$","%","^","&","*","(",")","-","_","+","=","<",">","/","?",";","\\","|","{","}","[","]"]

    for eachLetter in realText:
        if eachLetter in uppercase:
            index = uppercase.index(eachLetter)
            crypting = (index + step) % 26
            #print("{}  index={} Crypt={}".format(eachLetter,index,crypting))
            cryptText.append(crypting)
            newLetter = uppercase[crypting]
            outText += (newLetter)
        elif eachLetter in lowercase:
            index = lowercase.index(eachLetter)
            crypting = (index + step) % 26
            #print("{}  index={} Crypt={}".format(eachLetter,index,crypting))
            cryptText.append(crypting)
            newLetter = lowercase[crypting]
            outText += (newLetter)
        elif eachLetter in puncuation:
          outText += eachLetter 
        else:
          outText += " "
    return outText

You may call it like this

code = ROT_13("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
print(code)

to get the result

NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm

it even handles spaces, special characters as , # and CAPS

code2 = ROT_13("it even handles spaces, special characters as , # and CAPS")

to get

"vg rira unaqyrf fcnprf, fcrpvny punenpgref nf , # naq PNCF"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM