Can someone help...
My driver file is here:
from functions import process_marks def main():try:f = open(argv[1])except FileNotFoundError:print("\nFile ", argv[1], "is not available")exit()process_marks(f)f.close()main()
I'm trying to modify process_marks(f)
to run my code. and produce this (from file that runs without functions):
Names of students who have written tests:
Anthony Austyn Bronson Conor Mark
Enter name of student whose test results you wish to see: AnthonySummary of Test Results for Anthony
===================================
Test scores: 85 85 85 85
Number of tests written .................. 4
This is what I currently have:
names = []
name_print = "\nSummary of Test Results for "def process_marks(file_name):namesfor line in file_name:names.append(line.split()[0])print('\nNames of students who have written tests:')print(*sorted(names), sep=' ')name = input('Enter name of student whose test results ''you wish to see: ')check_name(name)parts = line.split()if parts[0] == name:print_scores(name)def check_name(person):if person not in names:print('\nNo test data found for ', person)input("Press Enter to continue ...")else:print(name_print + person) def print_scores(person, parts):print('=' * ((len(name_print)) - 1))test_scores = ' '.join(parts[1:])print('Test scores: ', end=' ')print(test_scores)
Which outputs:
Names of students who have written tests:
Anthony Austyn Bronson Conor Mark
Enter name of student whose test results you wish to see: AnthonySummary of Test Results for Anthony
I need help making print_scores()
function work in process_marks()
.
Can someone see where my errors lie?
Your error (mainly) lies in the fact that you are comparing the input name to the last row of the file. This is because you check if parts[0] == name
where parts = line.split()
. This means the parts
are of the last row of the file always - no matter what name provided.
To fix this, I would start by a better way of storing your data. Right now you are just saving the names in a list. But what about the grades? I think a better solution would be to use a dict
. So start by changing to:
names = {} # instead of []
Now you want to fill that dict with the names as keys (keeps the logic similar as with the list) and the list of grades as the value for that key. So your file parsing can look like:
for line in file_name:elements = line.split()names[elements[0]] = elements[1:]
# names now look like: {'Anthony': ['85', '85', '85', '85'], 'Conor': [...], ... }
Now another thing is that you call the check_name
function but then make another check in process_marks
. This seems redundant. I would change the ceck_name
function to return a boolean indicating if the name is ok or not:
def check_name(person):if person not in names:print('\nNo test data found for ', person)input("Press Enter to continue ...")return Falseelse:print(name_print + person)return True
And in process_marks
you can use it as:
name = input('Enter name of student whose test results you wish to see: ')
if check_name(name):print_scores(name)
Lastly, regarding the parts
issue. Now you have the grades stored in names
along with the matching name they belong to. So all we have left to do is change print_scores
to take only one argument grades
and use that instead of parts
, and from process_marks
just call it:
print_scores(names[name])
A view of a possible complete code:
names = {}
name_print = "\nSummary of Test Results for "def process_marks(file_name):with open(file_name) as f:for line in f:elements = line.split()names[elements[0]] = elements[1:]print(names)print('\nNames of students who have written tests:')print(*sorted(names), sep=' ')name = input('Enter name of student whose test results you wish to see: ')if check_name(name):print_scores(names[name])def check_name(person):if person not in names:print('\nNo test data found for ', person)input("Press Enter to continue ...")return Falseelse:print(name_print + person)return Truedef print_scores(grades):print('=' * (len(name_print) - 1))test_scores = ' '.join(grades)print('Test scores: ', end=' ')print(test_scores)