My Python code is looping at the wrong place - python

I have written this code for an assignment and it not working as it should. I want my program to validate user input for 3 users when they enter the names and grades for 3 test. my program just check the first input and then asks for the other user name and skips asking the user for an input or validating the input.
validInput1 = False
validInput2 = False
validInput3 = False
studentnames = []
studentMarkTest1 = []
studentMarkTest2 = []
studentMarkTest3 = []
totalScores = []
sum = 0
for i in range(3):
sname = input("Enter Student name:")
while not validInput1:
score1 = int(input("What did {} get on their test 1?".format(sname)))
if score1 < 0 or score1 >20:
print("Invalid input")
else:
validInput1 = True
while not validInput2:
score2 = int(input("What did {} get on their test 2?".format(sname)))
if score2 < 0 or score2 >25:
print("Invalid input")
else:
validInput2 = True
while not validInput3:
score3 = int(input("What did {} get on their test 3?".format(sname)))
if score3 < 0 or score3 >35:
print("Invalid input")
else:
validInput3 = True
totalScore = score1+ score2+ score3
sum = sum + totalScore
AverageTestScore = sum / 3
# saving name and grade
studentnames.append(sname)
studentMarkTest1.append(score1)
studentMarkTest2.append(score2)
studentMarkTest3.append(score3)
totalScores.append(totalScore) for i in range(3):
print(studentnames[i],"total Test score",totalScores[i]) print("class average", AverageTestScore)
here what happens when i run the program
>>>
Enter Student name:g
What did g get on their test 1?44
Invalid input
What did g get on their test 1?33
Invalid input
What did g get on their test 1?44
Invalid input
What did g get on their test 1?22
Invalid input
What did g get on their test 1?20
What did g get on their test 2?34
Invalid input
What did g get on their test 2?23
What did g get on their test 3?55
Invalid input
What did g get on their test 3?44
Invalid input
What did g get on their test 3?32
Enter Student name:e
Enter Student name:e
g total Test score 75
e total Test score 75
e total Test score 75
class average 75.0
>>>
How can I get the highest test score value stored in totalscore and then print out the highest score with the name of the student with the highest score?

its easy to get confused when you have a big chunk of code like this ... instead try and split your problem into smaller parts
start with a function to get the details of only one student
def get_student_detail(num_tests): # get the detail for just 1 student!
student_name = input("Enter Student Name:")
scores = []
for i in range(1,num_tests+1):
scores.append(float(input("Enter Score on test %s:"%i)))
return {'name':student_name,'scores':scores,'avg':sum(scores)/float(num_tests)}
now just call this for each student
student_1 = get_student_detail(num_tests=3)
student_2 = get_student_detail(num_tests=3)
student_3 = get_student_detail(num_tests=3)
print("Student 1:",student_1)
print("Student 2:",student_2)
print("Student 3:",student_3)
or better yet implement a function that lets you keep going as long as you want
def get_students():
resp="a"
students = []
while resp[0].lower() != "n":
student = get_student_detail(num_tests=3)
students.append(student)
resp = input("Enter another students details?")
return student
you may want to split out get_student_details even further writing a method to get a single test score and validate that its actually a number (this will crash as is if you enter something that isnt a number as a test score), or to keep asking for test scores until an empty response is given, etc
def get_number(prompt):
while True:
try:
return float(input(prompt))
except ValueError:
print ("That is not a valid number!")
def get_test_score(prompt):
while True:
score = get_number(prompt)
if 0 <= score <= 100:
return score
print("Please enter a value between 1 and 100!")
test_score = get_test_score("Enter test score for test 1:")
print(test_score)

Let's take a look at the while-loops you have:
while not validInput1:
The first time that your application runs, validInput1 is False, so this block evaluates. However, on subsequent loops (from for i in range(3):), validInput1 is already true, so this block is entirely skipped.
You can fix this by changing validInput1, validInput2 and validInput3 to False at the beginning of your for-loop.

That is because validInput1, validInput2 and validInput3 variables were set to True at first iteration but were not set to false for the second iteration.
Therefore for after first iteration your while conditions are always false due to "not True" i.e. False
Can set them to false again after each iteration i.e. at the end of the loop

You need to put validInput back to False after the while loops or even better replace them to the beginning of the for loop.

Related

Python how to limit the score (Code doesn't work after adding the if avg== etc

I am trying to find scores from only 7 judges and to have the numbers between 1-10 only, what is the problem with my code I am an newbie trying to self teach myself:)
So what I'm asking is how to limt the input to have to be 7 inputs per name and to limt the user input to 1-10 for numbers.
import statistics#Importing mean
def check_continue(): #defining check_continue (checking if the user wants to enter more name/athletes
response = input('Would you like to enter a another athletes? [y/n] ') #Asking the user if they want another name added to the list
if response == 'n': #if n, ends the loop
return False
elif response == 'y': # if y, continues the loop
return True
else:
print('Please select a correct answer [y/n]') #making sure the awsener is valid
return check_continue() #calling check continue
while(True):
name = input('Please enter a athletes name: ') #asking for an athletes name
if name == (""):
print ("try again")
continue
else:
try:
print("Enter the judges scores with space inbetween each score") #asking for scores
avg = [float(i) for i in input().split( )] #spliting the scores so the user only needs to put a space for each score
except ValueError:
continue
print("Please enter scores only in numbers")
scores = '' .join(avg)
print("please only enter number")
if scores ==("") or scores <=0 or scores >=10:
print("Please enter a score between 1-10")
continue
else:
print("_______________________________________________________________________________")
print("Athlete's name ",name) #Printing athletes name
print("Scores ", avg) #printing athletes scores
avg.remove(max(avg)) #removing the highest score
avg.remove(min(avg)) #removing the lowest score
avgg = statistics.mean(avg) #getting the avg for the final score
print("Final Result: " +
str(round(avgg, 2))) #printing and rounding the fianl socre
if not check_continue():
break
else:
continue
After reading input scores from judges, make sure that len(input.split()) == 7 to match first criteria.
Once you have the list of scores, just have a check that for each score, 1 <= int(score) <= 10.
If necessary, I can provide a working code too.
import statistics # Importing mean
def check_continue(): # defining check_continue (checking if the user wants to enter more name/athletes
# Asking the user if they want another name added to the list
response = input('Would you like to enter a another athletes? [y/n] ')
if response == 'n': # if n, ends the loop
return False
elif response == 'y': # if y, continues the loop
return True
else:
# making sure the awsener is valid
print('Please select a correct answer [y/n]')
return check_continue() # calling check continue
while(True):
# asking for an athletes name
name = input('Please enter a athletes name: ')
if name == (""):
print("try again")
continue
else:
scores = [float(i) for i in input('Enter the judges scores with space inbetween each score').split() if 1 <= float(i) <= 10]
if len(scores) != 7:
print("try again")
continue
print("_______________________________________________________________________________")
print("Athlete's name ", name) # Printing athletes name
print("Scores ", scores) # printing athletes scores
scores.remove(max(scores)) # removing the highest score
scores.remove(min(scores)) # removing the lowest score
# getting the avg for the final score
avg = statistics.mean(scores)
print("Final Result: " + str(round(avg, 2))) # printing and rounding the final score
if not check_continue():
break
This one should work. Let me know if there are any issues.
scores = [float(i) for i in input('Enter the judges scores with space inbetween each score').split() if 1 <= float(i) <= 10]
This line of code only saves values between 1 and 10, thus already checking for those values. Then the number of elements is checked to be 7.
PS: Would also want to point out that in your code, nothing ever executes after the except ValueError: continue. The continue basically skips to the next iteration without running any of the next lines of code.
My two cents. All checks of input you can warp before printing results with if all(): function for length of input scores list and range of nums between 1 and 10 (see code below).
For mean calc you don't need to delete value from list. You can make sorting and then slicing of list.
check_continue() can be simplify. Check entering for y or n value and return True or False by cases in dict. Otherwise loop.
import statistics
def check_continue():
response = input('Would you like to enter a another athletes? [y/n] ').lower() # Format Y and N to y and n
if response in ['y', 'n']: # Check if response is y or n
return {'y': True, 'n': False}[response]
check_continue()
while True:
name = input('Please enter a athletes name: ') #asking for an athletes name
if name: # Check if name not empty
while True: # make a loop with break at only 7 scores enter
scores_input = input("Enter the judges scores with space inbetween each score (only 7 scores)").split(' ')
try:
scores = [float(s) for s in scores_input] # sort list for extract part for avgg calc
except ValueError:
print("Please enter scores only in numbers")
continue
if all([len(scores) == 7, max(scores) <= 10.0, min(scores) >= 1]):
print("_______________________________________________________________________________")
print(f"Athlete's name {name}") #Printing athletes name
print(f"Scores {scores}") #printing athletes scores
avgg = statistics.mean(sorted(scores)[1:-1]) #getting the avg for the final score
print(f'Final result - {avgg :.2f}')
break
else:
print("Please enter 7 numbers for scores between 1-10")
if not check_continue():
break

How to average user inputs with while loop using a sentinal value?

For a classroom assignment I have been asked to create a program that averages a number of user input exam grades using a while loop. I have come up with a functioning program, however it does not meet the specific criteria required by my instructor.
I need to Use a while-loop to allow the user to enter any number of exam scores, one number per line, until a sentinel value is entered.
How might I alter this program to get the same result using a while loop and a sentinel value of 9999?
here is what I have so far.
scores=int(input("how many test scores will you enter: "))
total_sum=0
for n in range(scores):
numbers=float(input("Enter exam score : "))
total_sum+=numbers
avg=total_sum/scores
print("average of ", scores, " test scores is :", avg)
The output should look something like this
Enter exam score. 9999 to quit: 100
Enter exam score. 9999 to quit: 95.5
Enter exam score. 9999 to quit: 90
Enter exam score. 9999 to quit: 9999
These 3 scores average to : 95.16666667
Think the best way to do it would be store the scores in a list and then compute the average of them after the user enters the sentinel value:
SENTINEL = float(9999)
scores = []
while True:
number = float(input("Enter exam score (9999 to quit): "))
if number == SENTINEL:
break
scores.append(number)
if not scores:
print("You didn't enter any scores.")
else:
avg = sum(scores)/len(scores)
print("average of ", len(scores), " test scores is :", avg)
There are a couple ways to go about this. The general approach would be to keep a running total of the scores, as well as how many scores you've read, and then check whether the next score to read is == 9999 to see whether or not to exit the while loop.
A quick version might be the following:
num_scores = 0
total_sum = 0
shouldExit = False
while shouldExit is False:
nextScore = float(input("Enter exam score : "))
if nextScore == 9999: #find a way to do this that does not involve a == comparison on a floating-point number, if you can
shouldExit = True
if shouldExit is False:
num_scores += 1
total_sum += nextScore
avg = total_sum / num_scores
See how that sort of approach works for you
You can just break out of your for loop after getting input.
for n in range(scores):
c = int(Input('Enter test score, enter 9999 to break'))
if c == 9999:
break;
scores += c
Something like that at least.

NameError after using input in Python 2

I am learning Python this semester and this is my homework.
Can anyone tell me why my code is wrong?
QUESTION:
You want to know your grade in Computer Science, so write a program that continuously takes grades between 0 and 100 to standard input until you input "stop", at which point it should print your average to standard output.
MY CODE:
total=0
count=0
while True:
grade=input("Enter Your Grades between 0 and 100 [put 'stop' when done]:")
if grade<0 or grade>100:
print("Invalid Input")
continue
elif grade=="stop":
break
else:
count+=1
total+=grade
print "Your Average Grade is:"+format(total/count,'.2f')
When I run the code, the Python keeps giving me this messages:
Change input to raw_input
grade = raw_input("Enter Your Grades between 0 and 100 [put 'stop' when done]:")
You are using Python 2.7, so use raw_input instead of input. The latter evaluates the input, so 5 + 2 will return 7 instead of the string '5 + 2'. Entering stop tries to evaluate stop as a variable, which doesn't exist.
Another note, total and count are both integers, so total/count performs integer division in Python 2 (Python 3 gives a float result). If you want a floating point average, use float(total)/count. One of the variables must be float to get a float answer.
You'll also find that grade is a string, so test for 'stop' first, then convert it to an int to test the grade grade = int(grade). You might want to think about handling errors. What if the user types 10a?
You can evaluate first the string stop, try capture the input with raw_input:
total = 0
count = 0
while True:
grade = raw_input("Enter Your Grades between 0 and 100 [put 'stop' when done]:")
if grade == "stop":
break
if grade.isdigit():
grade = int(grade)
if grade < 0 or grade > 100:
print("Invalid Input")
continue
else:
count += 1
total += grade
if count == 0:
print "Empty values"
else:
print "Your Average Grade is: %.2f" % (float(total)/count)
I added different conditions for correct execution, check the lines, for example if grade.isdigit(): for verify that the input value is a numeric value, when this evaluation we can work normally with any math calculation.
count == 0: for the error division by zero if the user write stop in first iteration.
In the last line you can use two different ways to print the values:
print "Your Average Grade is: %.2f" % (float(total)/count)
or
print "Your Average Grade is: {:.2f}".format(float(total)/count)
You're running this program in Python 2 where input evaluates the user input. So if you enter "stop", Python tries to find the variable stop which doesn't exist and raises the NameError.
There are more problems and you need to restructure the code. The first thing you should do is to change input to raw_input which just returns the user input as a string. Then you need to check if the user entered "stop" and break, otherwise convert the input string to an int and then increment the count and total.
total = 0
count = 0
while True:
grade = raw_input("Enter Your Grades between 0 and 100 [put 'stop' when done]:")
if grade == "stop":
break
# Skip if the string can't be converted to an int.
if not grade.isdigit():
print("Invalid Input")
continue
# Now convert the grade to an int.
grade = int(grade)
if grade < 0 or grade > 100:
print("Invalid Input")
continue
else:
count += 1
total += grade
# Convert total to a float for true division.
print "Your Average Grade is: {:.2f}".format(float(total)/count)

Running the following on python

trying to get a program to enter a students name and score, test it to make sure score is a vaule >=0 and <=100 and save results to a file and loop back
gradeFile = open("grade.dat","a")
Score = "0"
while Score>=0:
Name = raw_input("What is the students's name?: ")
Score = float(raw_input("What is the students's score?: "))
while Score <0 or Score >100 :
print("ERROR: the grade cannot be less than 0 or more than 100")
Score = float(raw_input("What is the students's score?: "))
gradeFile.write(Name+"\n")
gradeFile.write(Score+"\n")
gradeFile.close()
print("Data saved to grade.dat")
You need to have a way to exit the loop. For your outer loop, you automatically go in. Then you loop again until you get a valid score, via your inner loop, and you repeat. In your current configuration, there's no way to exit the loop.
Additionally, score should be a number, but you enter it as a string in Score = "0". When outputting, you're going to want to write str(Score) so that you can concatenate it with "\n".
I suggest that your outer loop have something like while Score >= 0 and userWantsToContinue. You can handle userWantsToContinue in whatever way you see fit.
Your datatpe doesn't match
Score = "0" # So, score is a string
while Score >= 0: # Oh, thenm it's a integer?

For loop only executes 1 time, though given a range of 5

This question already has answers here:
How can I use `return` to get back multiple values from a loop? Can I put them in a list?
(2 answers)
Closed 2 days ago.
I have the following code:
def input_scores():
scores = []
y = 1
for num in range(5):
score = int(input(print('Please enter your score for test %d: ' %y)))
while score < 0 or score > 100:
print ('Error --- all test scores must be between 0 and 100 points')
score = int(input('Please try again: '))
scores.append(score)
y += 1
return scores
When I run it, the output is as follows:
Please enter your score for test 1:
None
Then I'll enter the test score next to None, as, say 95
It then runs through the rest of the program without prompting me for the next test score to add to the scores list. I'm really curious why that is
Thanks in advance for taking the time to help
Sincerely,
~Dustin
You return from inside the loop. Move return scores one indent left.
your return statement is indented too much, causing the function to return on the first iteration. It needs to be outside of the for block. This code works:
def input_scores():
scores = []
y = 1
for num in range(5):
score = int(input('Please enter your score for test %d: ' %y))
while score < 0 or score > 100:
print ('Error --- all test scores must be between 0 and 100 points')
score = int(input('Please try again: '))
scores.append(score)
y += 1
return scores
You indentation of the code seems whacky. It looks like the return statement is inside the scope of the for loop. So after the first iteration the return statement takes you out of the function completely.
You're returning scores at the end of each loop iteration (so in other words, after the first loop iteration finishes, you return all the scores thereby exiting the function, and the loop).
Change your code to be:
for num in range(5):
# ...
return scores # Note the indentation is one tab less than the loop's contents
Others have correctly pointed out that the indentation of your return statement was causing the problem. Also, you might want to try it like this, using len(scores) to control the loop, as #max suggested:
def input_scores(num_tests=5, max=100, min=0):
scores = []
while len(scores) < num_tests:
score = int(input('Please enter your score for test {0}: '.format(len(scores)+1)))
if score < min or score > max:
print ('Error --- all test scores must be between 0 and 100 points.')
else:
scores.append(score)
return scores

Categories

Resources