Theo Pearson-Bray
Theo Pearson-Bray

Reputation: 775

Where is this Index out of range coming from?

I am writing an algorithm to encrypt and decrypt using a key. or rather I have, this is more of a rewrite to organise my code. Anyway I just started to build a text based interface, Tkinter will come later.

When indexing a Key, which I have been setting to something like 12345 I get an "IndexError: string index out of range". I know what this means. But I also know that the whole string is being indexed in a loop. starting at 0. This is where it gets the error. Ive even tried testing it seperately e.g. print(Key[0]) But Python still throws an error. I dont understand why. It is referencing the string 12345 with 0, which should return 1.

Do you want to encrypt or decrypt? encrypt
Input a string toencrypt- Hello123
Input a key- 12345
123451
1234512
12345123
Key = 
Traceback (most recent call last):
  File "C:\Users\Theo_2\Google Drive\Computer science\Encryption and decryption work\Cipher 2\Cipher 2.5.0 Beta .py", line 142, in <module>
    User_text_interface(True)
  File "C:\Users\Theo_2\Google Drive\Computer science\Encryption and decryption work\Cipher 2\Cipher 2.5.0 Beta .py", line 137, in User_text_interface
    print(str(Encrypt(User_input)))
  File "C:\Users\Theo_2\Google Drive\Computer science\Encryption and decryption work\Cipher 2\Cipher 2.5.0 Beta .py", line 27, in Encrypt
    print(Key[0])
IndexError: string index out of range

For reference here is my code:

Specifically I think my problem is in the Encrypt function, although it may well be in Decrypt as well. Please ignore the commented out stuff in the middle, I was running every value through a loop of encryption and decryption which worked fine

import time, sys
Master_Key = "0123456789 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#£$%&'()*+,-./:;?@[\\]^_`{|}~\t\n\r\x0b\x0c"
global Output
Output = ""
global Key
Key = ""
##global User_input
def Compatibility_check(Key, User_input):
    Temp = 0
    while Key == "":  
        print("Your key cannot be blank")
        Key = input("Please input a new key: ")
    while len(Key) > len(User_input):
        Key = Key[:-1]
    while len(Key) < len(User_input):
        Key += (Key[Temp])
        Temp += 1
        print(Key)

def Encrypt(User_input):
    ##Compatibility_check(Key)
    Count = 0
    global Output
    Output = ""
    while Count < len(User_input):
        print(Key[0])
        print("Count = " + str(Count))
        print("Key count = " + str(Key[Count]))
        print("Master_key.index")
        print("Testing- Input indexer- " + str(Master_Key.index(User_input[Count])))
        print("Testing- Key indexer- " + str(Master_Key.index(Key[Count])))


        ref_for_output = Master_Key.index(User_input[Count]) + Master_Key.index(Key[Count])
        if ref_for_output >= len(Master_Key): ## As [] starts from zero
            ref_for_output -= len(Master_Key)
        Output += Master_Key[ref_for_output]
        Count += 1
    ##print("Output is " + Output)
    return Output

def Decrypt(User_input):
    ##Compatibility_check(Key)
    Count = 0
    global Output
    Output = ""
    while Count < len(User_input):
        ref_for_output = Master_Key.index(User_input[Count]) - Master_Key.index(Key[Count])
        if ref_for_output < 0:
            ref_for_output += len(Master_Key)
        Output += Master_Key[ref_for_output]
        Count += 1
    ##print("Output is " + Output)
    return Output

def Test_algorithm(Null):
    Counter1 = 0
    while Counter1 < (len(Master_Key)-1): ##If <= doesnt work use (len(Master_Key)-1)
        Input, Counter2 = Master_Key[Counter1], 0
        print("Input = " + Input)
        Counter1 += 1
        print("Loop 1")
        if Counter1 == len(Master_Key):
            print("The program works.")
        while Counter2 < (len(Master_Key)-1):
            global Key
            Key = Master_Key[Counter2]
            Encrypt(Input)
            ##Temp = Output
            Decrypt(Output)
            print("Encryption and decryption of Input- " + str(Input) + " with the Key- " + str(Key) + " results in an output of " + str(Output))
            if Input == Output:
                print("Pass")
            else:
                print("Fail")
                sys.exit
            Counter2 += 1
            ##Counters are used here, it is simply easier to use a counter and a while loop when dealing with references from a for loop

def User_text_interface(Repeat):
    while Repeat == True:
        ED = input("Do you want to encrypt or decrypt? ")
        User_input = input("Input a string to" + str(ED) + "- ")
        Key = input("Input a key- ")
        Compatibility_check(Key, User_input)
        if ED.lower() == "encrypt" or ED.lower() == "e":
            print(str(Encrypt(User_input)))
        elif ED.lower() == "decrypt" or ED.lower() == "d":
            print(str(Decrypt(User_input)))


User_text_interface(True)

Upvotes: 0

Views: 655

Answers (2)

Theo Pearson-Bray
Theo Pearson-Bray

Reputation: 775

Turns out my problem was obvious. It was in the way I had written my compatibility check function. Basically It took two inputs, Key and User_input. So it was supposed to check Key for a variety of things and change it if it didn't meet them. Unfortunately I had overlooked the fact that it was just changing its internal variable 'Key', which has the same name as the 'Key' being used later.

This meant that the Key was shorter than the input, and my encrypt function tried to reference a character in Key which didn't exist.

Upvotes: 0

Martijn Pieters
Martijn Pieters

Reputation: 1121486

Your Key variable is an empty string:

>>> Key = ''
>>> Key[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: string index out of range

That's because you are never changing the global Key variable, only a local. global statements must be put in the function:

def Compatibility_check(Key, User_input):
    global Key
    Temp = 0
    while Key == "":  
        print("Your key cannot be blank")
        Key = input("Please input a new key: ")
    while len(Key) > len(User_input):
        Key = Key[:-1]
    while len(Key) < len(User_input):
        Key += (Key[Temp])
        Temp += 1
        print(Key)

but it'd be better to have the function return the new value; you'd use return Key (ending the function) then assign that return value:

Key = Compatibility_check(Key, User_input)

Upvotes: 2

Related Questions