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.