Search code examples
pythonfileloopsdictionarymorse-code

looping through a textfile and adding certain strings to a dictionary


So I have a file morsecode.txt that contains

A2.-B4-...C4-.-.D3-..E1.F4..-.G3--.H4....I2..J4.---K3-.-L4.-..M2--N2-.O3---P4.--.Q4--.-R3.-.S3...T1- all the way to Z.

what it does is state the letter "A" has 2 symbols ".-" as its morse equivalent, the rest of the textfile follows the same order. "B" has 4 symbols "-..." etc...

What I want to do is create a morse dictionary, that stores the alphabetical letter with its morse equivalent.

What I have so far:

morse_dict=dict()
letter = 1
number = 1
with open('...morse.txt') as f:
    read_letter = f.read(1)
    code_length = f.read(1)
    read_code = f.read(int(code_length))
    morse_dict[read_letter] = read_code

this returns {'A': '.-'} just as I want it to.

this works for additional letters if you rerun it, i.e:

with open('...morse.txt') as f:
    read_letter = f.read(1)
    code_length = f.read(1)
    read_code = f.read(int(code_length))
    morse_dict[read_letter] = read_code
    read_letter = f.read(1)
    code_length = f.read(1)
    read_code = f.read(int(code_length))
    morse_dict[read_letter] = read_code
    read_letter = f.read(1)
    code_length = f.read(1)
    read_code = f.read(int(code_length))
    morse_dict[read_letter] = read_code
    read_letter = f.read(1)
    code_length = f.read(1)
    read_code = f.read(int(code_length))
    morse_dict[read_letter] = read_code

which returns {'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..'}.

Now for the problem: I want to create a loop that runs this on the entire textfile.

What i've tried:

with open('...morse.txt') as f:
while True :
    read_letter = f.read(letter)
    code_length = f.read(number)
    read_code = f.read(int(code_length))
    morse_dict[read_letter] = read_code
    if read_letter == '':
        break

however, this returns read_code = f.read(int(code_length)) ValueError: invalid literal for int() with base 10: ''

I tried using a for loop and im getting the same error. in my mind the loop works as following:

1)reads the letter with f.read(1)
2)reads the number of symbols of the morse equivalent of the letter above with f.read(1)
3) calls the integer given above with f.read(integer) and returns the morse equivalent of the letter
4) stores the given letter with given morse equivalent in a dictionary
5) reruns this entire loop above until it reaches the string '', then it breaks.

Im still very new to programming overall, there's probably a much better way of doing this, but i'd very much like some input on how to implement it using steps 1)-4). Any directions are greatly appreciated.


Solution

  • The error messages generally tell you what the problem is, once you get used to them, and it will make debugging much easier.

    When it reads the code_length from the file, it expects to find a string that it can convert to an integer. That was not the case. Therefore something is wrong with code_length, because it is an empty string. Looking at the code, I see you detect end of file by looking for that empty string, but you do so AFTER you try to convert it to an integer.

    In general, you should check the result of all IO functions. Also, you should expect and handle errors if there is a bad "morse.txt" file, and maybe even make your own exception. But in this case, the file was good, and you just didn't check the read to detect the normal end condition.

    morse_dict = {}
    letter = 1
    number = 1
    
    with open('morse.txt') as f:
        while True :
            read_letter = f.read(letter)
            if read_letter == '':
                # detect normal end of file, stop reading
                break
    
            # here is your bug. It can still crash on a bad data file if you don't check code_length here.
            code_length = f.read(number)
            read_code = f.read(int(code_length))
            morse_dict[read_letter] = read_code
    
    import pprint
    pprint.pprint(morse_dict)
    

    There are also a lot of stack overflow questions for converting a string to integer without raising an exception. Python: Check if a string represents an int, Without using Try/Except? But you want to check it, not just "succeed" at converting it to int(0)