Search code examples
pythonstringfunctioncaesar-cipher

Caesar-cypher: ord() function receives a string, says it receives an integer


I'm supposed to be creating a Caesar-cypher function. It was recommended I use the built-in ord() and chr() functions to help me do this(from the textbook my course is using). That may or may not be the best way(definitely not from what I've looked up), but it's what they want you to do.

My problem is that in a for loop when I send the placeholder variable into the ord() function I get an error that it expected a string of length 1, but receives an integer instead. I put a print function just before it to confirm that the variable, c in this case, has the value of 'i' but it seems to fail regardless.

Here is the function I created:

def rotate_word(word, num):
    count = 0
    newWord = ''
    while count < len(word):
        for c in word:
            print(c)
            newWord += chr(((ord(c)) - (ord(num) -1)))
            count += 1
    print(newWord)

And this is the error I receive:

rotate_word('ibm', -1)
i
Traceback (most recent call last):
  File "<pyshell#95>", line 1, in <module>
    rotate_word('ibm', -1)
  File "<pyshell#94>", line 7, in rotate_word
    newWord += chr(((ord(c)) - (ord(num) -1)))
TypeError: ord() expected string of length 1, but int found

This error occurs for integers other than -1 as well. To be fair, I'm not totally certain if the code itself does what I want(I've been stuck trying to figure this part out and I don't see the point in ensuring the rest works if this part does not).


Solution

  • ord takes string as a parameter and returns int:

    Given a string representing one Unicode character, return an integer representing the Unicode code point of that character. For example, ord('a') returns the integer 97 and ord('€') (Euro sign) returns 8364. This is the inverse of chr().

    In your code you're passing int instead which gives you the error you see on command line. You don't need to convert num to anything. Just convert the character to number, add the rotation amount and convert the result back to character again with chr:

    def rotate_word(word, num):
        count = 0
        newWord = ''
        while count < len(word):
            for c in word:
                newWord += chr(ord(c) + num)
                count += 1
        print(newWord)
    
    rotate_word('ibm', -1)  # 'hal'
    

    Note that above doesn't handle the overflow/underflow cases where 'a' is rotated left or 'z' is rotated right.