Python Forum
What am I doing wrong?
Thread Rating:
  • 2 Vote(s) - 2.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
What am I doing wrong?
#1
This is driving me crazy.

*** Program Description ***
Write a program to read in a file of years, one per line, and output to a separate file "only those years that are in fact leap years" (according to the Gregorian calendar). Ask the user to input the file names of both files, and use the try-except construct when you open each in your program.

# function 1
def leapYear(year):
    """ Calculates whether a year is or isn't a leap year. """
    year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
# function 2
def appendFile():
    file = open("leap_years.txt", "a") # create new - empty - data list
    for line in lines: # loop through raw data
        if leapYear():
            ... idk ...
try:
    file = open("all_years.txt", "r")
    lines = file.readlines()
    file.close()
    
    appendFile()
except FileNotFoundError as e:
    print(e)
I have been working on this for like 20 hours total and am getting nowhere. I have the part down where I read the "all_years.txt" file, but now I need the program to loop through the already read file, calculate if each line is a leap year or not, and write to a new blank file all of the years that are leap years. What am I doing wrong?
Reply
#2
def find_leap(year):
    if (year % 100 != 0 and year % 4 == 0) or
        (year % 100 == 0 and year % 400 == 0):
        return True
    return False
Not tested.
I would create the test file with an editor as it is not required, at least in your spec above

To read the file, use:
with open('all_years.txt') as f:
    year = f.readlines()
    if find_leap(year.strip()):
        # ... add print here
Reply
#3
The first thing your are doing wrong is not telling us what error you are getting, or how the program is not working.

The lines variable is going to be a list of strings. That's how files are read in. You need to convert those to integers with the int() function. Then, you have a parameter to your leapYear function, but you are not supplying a parameter to it when you call it in appendFile. You need to supply the integer year to leapYear so it knows what year to calculate on. Next, leapYear is not returning anything explicity. That means it implicitly returns None, which evaluates to False, so if leapYear(): will always be false. You need to return the value you are calculating in leapYear. Just put a return statement before the calculation and that will work. Finally, when leapYear() is True, you want to write it to a file. At which point I realize you've named your file 'file', which is a bad idea because file is a keyword in Python. So rename those files something like all_file and leap_file. Then to write to the file, you use the write method of the file. You can just write the line you read: leap_file.write(line).

In previous posts you made, it seemed that the input file had lines that weren't years and lines that had years and other text. If that is the case, get this program working with a dummy file that is just years, and then you can worry about the full file.

I would suggest checking out a functions tutorial. There should be a link to one in my signature below.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#4
I would not use the with statement Larz suggested unless your professor has gone over it in class. It is good/standard practice, but as I recall your professor specifically told you to use a try/except block, as you have done.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#5
(Sep-15-2017, 08:39 PM)forumer444 Wrote:
# function 1
def leapYear(year):
    """ Calculates whether a year is or isn't a leap year. """
    year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)

You never return from the function. So when you call leapYear(), the return will always be None, so your if leapYear(some_number): blocks will never execute, because it's never true.
Reply
#6
Quote:The first thing your are doing wrong is not telling us what error you are getting, or how the program is not working.

Yeah, I should have mentioned that. I have to at least 2 functions, have to use a try-except construct and can't use a split method.

Where the program is going wrong is that I haven't been able to finish it at all. I just don't understand how to have the program read through the "all_years.txt" file, ignore the letters inside, and write all the years that are leap years inside the empty "leap_years.txt" file.

I haven't been able to finish the program at all is where it's wrong :(

So are my functions supposed to return something?

Also, I really would like to come up with a structure that I know is going to work. I'm not too experienced in programming and this class just picked up way too fast. I've spent over 20 hours on this getting nowhere.

I just need to know what to put and where. Also, are my functions supposed to return something?

# function 1
def leapYear():
... calculation ...
# function 2
def appendFile():
... loop/other stuff ...

# user input
...

# construct
try:
... open/read files ...
except FileNotFoundError as e:
print(e)

This is what I have so far:

# function 1
def leapYear(year):
    """ Calculates whether a year is or isn't a leap year. """
    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
# function 2
def appendFile():
    pass
        
try:
    file = open("all_years.txt", "r")
    lines = file.readlines()
    file.close()
    
    leapYear(lines)
except FileNotFoundError as e:
    print(e)
This is what error I'm getting:

TypeError: unsupported operand type(s) for %: 'list' and 'int'
Reply
#7
As I said, lines are read in from files as strings. The readlines method gives you a list of strings. You were looping over them in appendFile before, that was fine, and was giving you individual strings. As I said, you need to convert those to integers using int().

>>> text = '1984' # a string
>>> leapYear(text) # this will give a TypeError
>>> leapYear(int(text)) # this will work
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#8
How do you filter out the letters in the "all_years.txt" file?

I assume it goes in my appendFile() function.

Am I getting anywhere? :(

I took out the appendFile() function.
# calculate function
def leapYear(year):
    """ Calculates whether a year is or isn't a leap year. """
    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)

# main function
def main():
    try:
        file = open("all_years.txt", "r")
        lines = file.readlines()
        
        for line in lines:
            if leapYear(int(line)):
                file2 = open("leap_years.txt", "w")
                print(file2.write(line))
    except FileNotFoundError as e:
        print(e)
main()

Reply
#9
You are looking better. You still have a file named 'file', which you should change. I would take the opening of file2 out of the loop. You are currently opening it every time you write to it. You don't need to do that. Just open it once, and then close it (file2.close()) after the loop when you have finished writing to it.

Did you make a test file of just years with no text? That will tell you if you are getting anywhere. If it works on that easy file, then you are ready to work on the extra text.

The extra text you can probably deal with using the split method of strings. line.split() will break line into a list of words based on white space (spaces and tabs). Then you can check the first word with the isdigit method. word.isdigit() will be true if all the characters in the word are numbers. You just need to watch out for empty lines. The split method will give you an empty list for a blank line.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#10
This is my update if anyone can help me finish it.

# calculation function
def leapYear(year):
    """ Calculates whether a year is or isn't a leap year. """
    year = int(year)
    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)

# main function
def main():
    try:
        file_1 = open("all_years.txt", "r") # open file
        lines = file_1.readlines()
        file_1.close()

        file_2 = open("leap_years.txt", "a") # open file

        for line in lines:
            if line.isdigit():
                if leapYear(line):
                    file_2.write(line)
        file_2.close()
    except ValueError as e:
        print(e)

main()
It's FINALLY writing to the other file, but only one line which is "6464", which is the very last line in the "all_years.txt" file. Any reasons why?

Quote:The extra text you can probably deal with using the split method of strings. line.split() will break line into a list of words based on white space (spaces and tabs). Then you can check the first word with the isdigit method. word.isdigit() will be true if all the characters in the word are numbers. You just need to watch out for empty lines. The split method will give you an empty list for a blank line.

I believe I'm not a loud to use the split() method, but I used the isdigit method. Can you take a look at my latest post?
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020