GPA Calculator troubles

Question:

For some reason that is unknown to me, my GPA calculator only calculates the last input in the list, I only have 2 days left to complete this and hopefully i can in time.

I tried to make it to where it calculates every input nd not just the last one, but i dont know how.
here is my code:

name = input("What is your name? n")
h1 = ("Class Name")
h2 = ("Class Grade")
h3 = ("Credit Hours")
point = input("nEnter your class name followed by your letter grade and hours (say Done to stop input):n")
class_data = []
while point != "Done":
    words = point.split(" ")
    if len(words) == 1:
        print("Error: No spaces in string. Try again.")
    elif len(words) > 4:
        print("Error: Too many spaces in input. Try again. ")
    else:
        try:
            class_name = words[0]
            grades = (words[1])
            hrs = int(words[2])
            print("Name of class:", class_name)
            print("Grade:", grades)
            print("Class Hours:", hrs)
            class_data.append((class_name, grades, hrs,))
        except ValueError:
            print("Error: Space not followed by an integer.")
    point = input("nEnter your class name followed by your letter grade and hours (say Done to stop input):n")

    def gpa_calculator(grades):
        points = 0
        i = 0
        grade_c = {"A":4,"A-":3.67,"B+":3.33,"B":3.0,"B-":2.67, "C+":2.33,"C":2.0,"C-":1.67,"D+":1.33,"D":1.0,"F":0}
        if grades != class_data:
            for grade in grades:
                points += grade_c[grades]
            gpa = points / len(grades)
            return gpa
        else:
            return None 

print("Name: ", name)
print("-" * 66)
print("%-15s|%11s|%5s|" % (h1, h2, h3))
print("-" * 66)
for item in class_data:
    print("%-15s|%11s|%12s|" % (item[0], item[1], item[2]))
print("-" * 66)
print('Your projected GPA is: ',(gpa_calculator(grades)))
print("-" * 66)

here is the output :

What is your name? 
John Smith

Enter your class name followed by your letter grade and hours (say Done to stop input):
poop D 50
Name of class: poop
Grade: D
Class Hours: 50

Enter your class name followed by your letter grade and hours (say Done to stop input):
poop D 50poop D 50poop D 50
Error: Too many spaces in input. Try again. 

Enter your class name followed by your letter grade and hours (say Done to stop input):
poop D 50
Name of class: poop
Grade: D
Class Hours: 50

Enter your class name followed by your letter grade and hours (say Done to stop input):
poop D 50
Name of class: poop
Grade: D
Class Hours: 50

Enter your class name followed by your letter grade and hours (say Done to stop input):
perfecgt A 1
Name of class: perfecgt
Grade: A
Class Hours: 1

Enter your class name followed by your letter grade and hours (say Done to stop input):
Done
Name:  John Smith
------------------------------------------------------------------
Class Name     |Class Grade|Credit Hours|
------------------------------------------------------------------
poop           |          D|          50|
poop           |          D|          50|
poop           |          D|          50|
perfecgt       |          A|           1|
------------------------------------------------------------------
Your projected GPA is:  4.0
------------------------------------------------------------------
Asked By: Grimmo

||

Answers:

It looks like the problem is the input you give to the function, grades this variable will be changed and then added to class_data in the tuple but it will keep just one value, meaning it will keep the last value it was given and calculate the gpa with just that. Instead you should give a list so it can iterate through all the values.
Here is what I changed and for the case you gave give the right output 1.75

def gpa_calculator(grades:list):
    points = 0
    grade_c = {"A":4,"A-":3.67,"B+":3.33,"B":3.0,"B-":2.67, "C+":2.33,"C":2.0,"C-":1.67,"D+":1.33,"D":1.0,"F":0}

    for x in grades:
        if x[1] not in grade_c:
            return "ERROR"
        points += grade_c[x[1]]
    gpa = points / len(grades)
    return gpa
gpa_calculator(class_data)

EDIT: I did not comment the code assuming that you would understand what the problem was. If you have any question pls comment it.

EDIT2: Also you should define the function at the begining of the line not indented, check PEP8 Python Style Guide

Answered By: StarLight

I tried out your code and found a few quirks in the code. First off, the variable "grades" is just a single variable within your program and is not defined anywhere as a list. That seemed to be the main point of contention with the code. It appears that you want to extract the second element within the class_data list to determine a dictionary value. With that, I tweaked the code a bit, specifically in the gpa_calculator" function. Following is your code with the tweaks.

name = input("What is your name? n")
h1 = ("Class Name")
h2 = ("Class Grade")
h3 = ("Credit Hours")
point = input("nEnter your class name followed by your letter grade and hours (say Done to stop input):n")
class_data = []
while point != "Done":
    words = point.split(" ")
    if len(words) == 1:
        print("Error: No spaces in string. Try again.")
    elif len(words) > 4:
        print("Error: Too many spaces in input. Try again. ")
    else:
        try:
            class_name = words[0]
            grades = (words[1])
            hrs = int(words[2])
            print("Name of class:", class_name)
            print("Grade:", grades)
            print("Class Hours:", hrs)
            class_data.append((class_name, grades, hrs,))
        except ValueError:
            print("Error: Space not followed by an integer.")
    point = input("nEnter your class name followed by your letter grade and hours (say Done to stop input):n")

    def gpa_calculator(grades):
        points = 0
        i = 0
        grade_c = {"A":4,"A-":3.67,"B+":3.33,"B":3.0,"B-":2.67, "C+":2.33,"C":2.0,"C-":1.67,"D+":1.33,"D":1.0,"F":0}
        if grades != class_data:
            for item in class_data:         # Need to read through the class data list to acquire grade element for each class
                # print(item[1])
                points += grade_c[item[1]]  # Grade is the second element in each grade_list entry
            gpa = points / len(class_data)
            return gpa
        else:
            return None 

print("Name: ", name)
print("-" * 66)
print("%-15s|%11s|%5s|" % (h1, h2, h3))
print("-" * 66)
for item in class_data:
    print("%-15s|%11s|%12s|" % (item[0], item[1], item[2]))
print("-" * 66)
print('Your projected GPA is: ',(gpa_calculator(grades)))
print("-" * 66)

Testing it out provided the following sample output.

@Dev:~/Python_Programs/GPA$ python3 GPA.py 
What is your name? 
John Smith

Enter your class name followed by your letter grade and hours (say Done to stop input):
History D 40
Name of class: History
Grade: D
Class Hours: 40

Enter your class name followed by your letter grade and hours (say Done to stop input):
Physics C 20
Name of class: Physics
Grade: C
Class Hours: 20

Enter your class name followed by your letter grade and hours (say Done to stop input):
Math A 20
Name of class: Math
Grade: A
Class Hours: 20

Enter your class name followed by your letter grade and hours (say Done to stop input):
Done
Name:  John Smith
------------------------------------------------------------------
Class Name     |Class Grade|Credit Hours|
------------------------------------------------------------------
History        |          D|          40|
Physics        |          C|          20|
Math           |          A|          20|
------------------------------------------------------------------
Your projected GPA is:  2.3333333333333335
------------------------------------------------------------------

That appears to be the output you are expecting.

Give that a try to see if it meets the spirit of your project.

Answered By: NoDakker

I just tested out your code and it seems it’s mostly working. I noticed that you send the variable grades into the gpa_calculator function, but not the class_data item (which includes all the data which you want to average over). Try to do this at the end:

# ...

def gpa_calculator(grades):
    points = 0
    grade_c = {"A":4,"A-":3.67,"B+":3.33,"B":3.0,"B-":2.67, "C+":2.33,"C":2.0,"C-":1.67,"D+":1.33,"D":1.0,"F":0}
    
    for grade in grades:
        points += grade_c[grade[1]] # get middle item in tuple (name, grade, hrs), equals the 
    gpa = points / len(grades)
    return gpa

# ...
print('Your projected GPA is: ',(gpa_calculator(class_data))) # noticed I changed this to class data, not grades
# ...
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.