why does the while loop not work? - python-2.7

I'm creating a program that takes in the users grade(A-F), health(0-100) and economic output(0-100). I need a while loop for when the user inputs a value wrong e.g A for health. why does the loop keep repeating? how do I do this for the grade as well?
name = raw_input(' Enter your name: ')
grade = raw_input(' Enter your grade: ')
string_two = raw_input(' Enter your economic out put: ')
while string_two not in range (0,100):
print 'please enter a value between 0 and 100.'
string_two = raw_input(' Enter your economic out put: ')
string_one = raw_input(' Enter your health: ')
while string_one not in range (0,100):
print 'please enter a value between 0 and 100.'
string_one = raw_input(' Enter your health: ')
health == int(string_one)
economic_output == int(string_two)
if economic_output > 85:
print name + ' you are exceptional! Welcome aboard!'
elif grade == 'A':
print name + ' you are exceptional! Welcome aboard!'
elif economic_output > 60:
if health > 60:
if grade == 'B' or 'C':
print 'Congatulations ' + name +'!' + ' Come aboard!'
else:
print 'Sorry, ' + name + ' but you dont meet the criteria and cammot be permitted to board. '

The while loop keeps repeating because raw_input always returns a string object, regardless if you typed digits only or something else. string_two not in range (0,100) is always true because a string cannot be in any range of ints.
So what you can do. If I were you, I would define a function which would ask the user to enter something in a while loop until his input satisfies some pattern (just as you are trying to do in your code) and convert it to a specific type if necessary. There is a very useful tool to check a string for matching some pattern, it is called regular expressions (RE).
import re
def inputAndValidate(prompt, pattern, convertFunc=str):
result = raw_input(prompt)
while re.match(pattern, result) is None:
print 'Input pattern is "' + pattern + '". Please enter a string matching to it.'
result = raw_input(prompt)
return convertFunc(result)
Putting a piece of code being used several times to a function is a good practice. So here I defined a function called inputAndValidate with 2 mandatory parameters - a prompt to be displayed for user to let him understand what do you want from him, and the pattern to check his input. The third parameter is optional - it's a function which will be applied to the user input. By default, it's str, a function converting something to a string. User input is already a string, so this function will do nothing, but if we need an int, we'll pass int as the third parameter and get an int from the inputAndValidate function, and so on.
re.match(pattern, string) returns a match object if the string did match the pattern, and None if it didn't. See official re documentation for more information.
Usage of the function
name = inputAndValidate('Enter your name: ', r'.+')
# This pattern means any string except empty one. Thus we ensure user will not enter an empty name.
grade = inputAndValidate('Enter your grade (A-F): ', r'[A-F]')
# This pattern means a string containing only one symbol in the A-F range (in the ASCII table).
economic_output = inputAndValidate('Enter your economic output (0-100): ', r'\d{1,3}', int)
# This pattern means a string containing from one to three digits. `int` passed to the third parameter means the result will be an int.
health = inputAndValidate('Enter your health (0-100): ', r'\d{1,3}', int)
# Same as the previous one.
re module documentation also contains information about the regular expressions language, it can help you understand the patterns I used.

Related

Input validation python 2.7.13

I am trying to validate input that is going into a list. The input needs to be an integer. How I have it works if I input an integer or a single letter. but if I enter something like 'qw' the program crashes. What can I do to better validate the input? Here is my code:
def getPints(pints):
counter = 0
while counter < 7:
pints[counter] = raw_input("Enter the number of pints donated: ")
check = isinstance(pints[counter], int)
while check == False:
print "Please enter an integer!"
pints[counter] = input("Enter the number of pints donated: ")
counter = counter + 1
As written, check will always evaluate to False, because raw_input() only returns a string, never an integer. Then you'll get stuck in an infinite while loop, because you don't update check in it.
Instead of isinstance, use the string isdigit() method.
check = pints[counter].isdigit()
You'll also need to re-evaluate check inside the loop. But really, you don't need check at all.
pints[counter] = raw_input("Enter the number of pints donated: ")
while not pints[counter].isdigit():
print "Please enter an integer!"
pints[counter] = raw_input("Enter the number of pints donated: ")
I suspect you also want to convert pints[counter] to an int once you have a suitable input.
You're using the LBYL method (Look Before You Leap). You can also use the EAFP (Easier to Ask Forgiveness than Permission) method by just trying to convert the input to an int and catching the exception if the input is bad:
while True:
try:
pints[counter] = int(raw_input("Enter the number of pints donated: "))
break
except ValueError:
print "Please enter an integer!"

Python: Trying to loop through a string to find matching characters

I am trying to create a simple "guess the word" game in Python. My output is something like:
String: _____ _____
Guess a word: 'e'
String:_e__o __e_e
Guess a word: 'h'
(and so on)
String: hello there
I have a function to do this, and within this function I have this code:
def guessing(word):
count = 0
blanks = "_" * len(word)
letters_used = "" #empty string
while count<len(word):
guess = raw_input("Guess a letter:")
blanks = list(blanks)
#Checks if guesses are valid
if len(guess) != 1:
print "Please guess only one letter at a time."
elif guess not in ("abcdefghijklmnopqrstuvwxyz "):
print "Please only guess letters!"
#Checks if guess is found in word
if guess in word and guess not in letters_used:
x = word.index(guess)
for x in blanks:
blanks[x] = guess
letters_used += guess
print ("".join(blanks))
print "Number of misses remaining:", len(word)-counter
print "There are", str(word.count(guess)) + str(guess)
guess is the raw input I get from the user for a guess, and letters_used is just a collection of guesses that the user has already input. What I'm trying to do is loop through blanks based on the word.index(guess). Unfortunately, this returns:
Guess a letter: e
e___
Yes, there are 1e
Help would be much appreciated!
Your code was almost correct. There were few mistakes which I have corrected:
def find_all(needle, haystack):
"""
Finds all occurances of the string `needle` in the string `haystack`
To be invoked like this - `list(find_all('l', 'hello'))` => #[2, 3]
"""
start = 0
while True:
start = haystack.find(needle, start)
if start == -1: return
yield start
start += 1
def guessing(word):
letters_uncovered_count = 0
blanks = "_" * len(word)
blanks = list(blanks)
letters_used = ""
while letters_uncovered_count < len(word):
guess = raw_input("Guess a letter:")
#Checks if guesses are valid
if len(guess) != 1:
print "Please guess only one letter at a time."
elif guess not in ("abcdefghijklmnopqrstuvwxyz"):
print "Please only guess letters!"
if guess in letters_used:
print("This character has already been guessed correctly before!")
continue
#Checks if guess is found in word
if guess in word:
guess_positions = list(find_all(guess, word))
for guess_position in guess_positions:
blanks[x] = guess
letters_uncovered_count += 1
letters_used += guess
print ("".join(blanks))
print "Number of misses remaining:", len(word)-letters_uncovered_count
print "There are", str(word.count(guess)) + str(guess)
else:
print("Wrong guess! Try again!")

How can I check if a string contains specific charcaters in VB.net?

So, I did some research but didn't come up with any answers. I read about the Regex method, but I'm practically new in this and I have never heard of it.
What I'm trying to do is to identify, whether the user entered a password (in my case I call it "Student Number") that must only contain an uppercase letter S, eight numbers after the uppercase S, and finally a special character * (specifically in that order).
I already programmed this:
Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
Dim InvalidName As Integer = 0
Dim InvalidStudentNumber_Numeric As Integer = 0
For intIndex = 0 To txtName.Text.Length - 1
If IsNumeric(txtName.Text.Substring(intIndex, 1)) Then
InvalidName = 1
End If
Next
For intIndex = 0 To txtStudentNumber.Text.Length - 1
If IsNumeric(txtStudentNumber.Text.Substring(intIndex, 1)) Then
InvalidStudentNumber_Numeric += 1
End If
Next
If InvalidName <> 0 Then
MessageBox.Show("The name entered does not meet the characters criteria. Provide a non-numeric name, 10 characters or longer.",
"Invalid Information: Name")
txtName.Focus()
ElseIf InvalidStudentNumber_Numeric <> 8 Then
MessageBox.Show("The student number entered does not meet the characters criteria. Provide a non-numeric student number, 10 characters long.",
"Invalid Information: Student Number")
txtStudentNumber.Focus()
So, as for the Student's Name I have no problems, but the password is what gets me. I already figured out how to know if it has numbers (it must have 8), but I don't know how to search for the uppercase S at the beginning and for the * at the end of the string.
No need for regex.
Public Function IsValidStudentNumber(ByVal id As String) As Boolean
' Note that the `S` and the `*` appear to be common to all student numbers, according to your definition, so you could choose to not have the users enter them if you wanted.
Dim number As Int32 = 0
id = id.ToUpper
If id.StartsWith("S") Then
' Strip the S, we don't need it.
' Or reverse the comparison (not starts with S), if you want to throw an error.
id = id.Substring(1)
End If
If id.EndsWith("*") Then
' Strip the *, we don't need it.
' Or reverse the comparison (not ends with *), if you want to throw an error.
id = id.Substring(0, id.Length - 1)
End If
If 8 = id.Length Then
' Its the right length, now see if its a number.
If Int32.TryParse(id, number) Then
Return True
End If
End If
Return False
End Function

Getting error "NameError: name 'letter' is not defined"

I'm fairly new to python and don't know much but i tried to make a program that sees how fast it can guess a string in this case a password. I tried to create an individual variable for each letter by making a loop that sets the variable. (I added the print letter1... at the end so i can see if it works).Then when i went to test it i got this error.
letter[x] = password[x - 1:-(len(password)-1)]
NameError: name 'letter' is not defined
print "Password guesser"
password = raw_input('Enter Password (1-30 carechters only): ')
passwordLength= len(password)
for x in range(0,passwordLength):
letter[x] = password[x - 1:-(len(password)-1)]
print letter1
print letter2
print letter3
Since you're assigning letters with dictionary syntax, you may want to declare the letter variable as a dictionary: letter = {}, then output it as a dictionary. This may get you in the direction you want to go:
letter = {}
for x in range(passwordLength):
letter[x] = password[x - 1:-(passwordLength-1)]
print letter[0]
print letter[1]
print letter[2]

Python: The code disobeys the conditional depending on the input

I'm making a hang man game. When I made the code with out a conditional and classes, it worked fine. Basically my issues with the code below are:
Only the letter "t" will match. I can't get any other letter to match.
If I enter "t" on the first try, then purposely get the next 4 letters wrong, it won't end until after 7 turns. Yet if I enter any other letter first, it will end after 4 wrong turns, like it should.
My questions....
How can I get it to match with the other letters that are in the self.word index?
Why is it not obeying the condition I set with the while loop in the main method if I enter "t" on my first try and get every other letter wrong thereafter?
class Hang():
def __init__(self):
self.turns = 0
self.word = ['t', 'h', 'i', 's']
self.empty = ["__", "__", "__", "__"]
self.wrong = []
def main(self):
while self.turns < 4:
for i in self.word:
choice = raw_input("Enter a letter a-z: ")
if choice == i:
index = self.word.index(i)
self.empty.pop(index)
self.empty.insert(index, i)
print self.empty
else:
print "Wrong"
self.wrong.append(choice)
print self.wrong
print self.empty
self.turns += 1
char1 = Hang()
char1.main()
In the game of hangman you can guess any character in the phrase in any order. But you're using a for loop to go through each character in order and it is only correct if the player correctly guesses the characters in order
Try this instead
while self.turns < 4:
choice = raw_input("Enter a letter a-z: ")
# optional, if user enters more than a single letter
if len(choice) > 1:
print "invalid choice"
continue # loop again from start
index = self.word.index(choice)
if index != -1:
# -1 indicates character in not int the string
# so this block is only executed if character is
# in the string
self.empty[index] = choice # no need to pop, you can simply change the value of the list at a given index
else:
print "wrong"
self.turns += 1
print self.empty