DAY 7 Continuing with our problem solving: NEXT CODE (not a function - why? no particular reason) reverse a string. how would a human do that? s = 'abcde' get the e, add the d, add the c, add the b, add the a another thing you can do, which will enable us to use a simple for loop starting from the beginning of the string: let's build up the string in variable reverse. it will start as '' the for loop: for char in s: so, as above, we'll go through it char by char from the beginning see the example: each char reverse [fill in this column first] 'a' 'a' NOW: let's put the next character on the front of our new list! 'b' 'ba' 'c' 'cba' SO: take reverse so far -- the 'cba' and put 'd' on the front of it 'd' 'dcba' 'e' 'edcba' take reverse so far and put char on the front of it. how do we do that? reverse = char + reverse! reverse = "" # An accumulator for char in s: reverse = char + reverse print reverse *** Look at string_funs.py - show them how I tested it. ***** *** it will save you time to do this. some extra typing to do the *** test cases, but you will know right away if it is right. Save *** these tests. Then, if you ever change the code, you can just run *** these print statements, and see if it still works! *** ===You can also index strings Each position is numbered starting at 0 myString = "Computer Science" ch = myString[4] Or, what will this print? print(myString[0],myString[5],myString[0]) of course, you will get an error if you use an index that doesn't exist. myString[35] len(myString) how do I print the last character of a string? myString[len(myString)-1] === NOW: Let's grab our count_vowel function from the stringFuns.py file, and use it here. def askAndCount(): ''' Prompt the user to enter a string, and return the number of vowels it contains as an int''' myString = input("Enter a string: ") num = num_vowels(myString) return num == introduction to while loops == - The function askAndCatch only gets one set of input from the user. - We'd like the user to continue entering strings until it finds a string that contains at least one vowel - Other similar scenarios: type your password twice; must retry until get it to match! type your command; must retry until enter a correct one - That means we'd like to repeat lines as long as num == 0. myString = input("Enter a string: ") num = num_vowels(myString) - QU: How have we seen to make a chunk of code happen several times? For-loops, like for char in s: for i in [1,2,3]: for i in range(4): - QU: How would you write a for-loop for this? Can't; would require us to have some specific sequence we are iterating over. Here, we are not going through some sequence ** and, we have no idea ahead of time how many times the line should be repeated. we don't know the number of "iterations" - There's another kind of loop for our situation: a while loop while (condition): while-body - Good News!!! (condition) is the same as in the for-loop! So, everything you learned about conditions for the if-statements, you can use that knowledge here! - Let's write a new version of the function that uses while: [CODE: askAndCountVowels.py] def askAndCountRepeat(): ''' Prompt the user to enter a string and find out if it contains any vowels. Repeat this task until a string containing a vowel is found. When you find a string containing a vowel, return the number of vowels in that string (an int)''' num = 0 # need an initial value while num == 0: myString = input("Enter a string: ") num = num_vowels(myString) return num - Debugger: run this multiple times and point out the number of times the loop executes. - QU: Min number of times? 1 QU: Max number of times? infinite - How while loops are different from for loops - QU: Do they have loop variables? for - yes while loop - no, no specific loop variable - QU: When do they stop? for loop - definite - len of the sequence Can you predict the number of times a while loop will execute? nope! depends on when the condition becomes false. === What happens with this loop? [infiniteLoop.py] def main(): keepGoing = 'y' while keepGoing == 'y': sales = float(input("sales ")) rate = float(input("rate ")) commission = sales * rate print("commission: ",commission) main() Will keep going forever and ever! (eventually, you will kill it or something will stop it) INFINITE LOOP The body of the loop does nothing that will ever make the condition true. ===Augmented assignment operator Kind of an aside; covered in chapter 5 A short hand, now in most languages. #pairs below are the same x = x + 4 x += 4 y = y - 2 y -= 2 x = x * 10 x *= 10 ====Input validation loop You can use a loop to check the user's input, and ask him or her to enter other values, if the input was not right. [noValidateInput.py] def main(): hours = int(input('enter hours worked this week ')) rate = float(input('enter hourly pay rate ')) grossPay = hours * rate print("Gross pay: $",format(grossPay,',.2f'),sep="") main() enter 400 20 Wow, you made a lot of money this week! The payroll clerk entered 400 instead of 40. Or, you could end up with garbage: enter -40 20 oops! The employee now *owes* $800. You read stories that "computer errors" lead to huge tax refunds that shouldn't be paid, or people being overcharged by 1000's of dollars. It's not the computer that made the error! It was whoever entered the information. And, sloppy programming, that doesn't check that the values are "within the range" they are supposed to be in. "garbage in, garbage out". [lead up to validateInput.py] **In class, start with noValidateInput.py and add to it. [noValidateInput.py] def main(): hours = int(input('enter hours worked this week ')) rate = float(input('enter hourly pay rate ')) grossPay = hours * rate print("Gross pay: $",format(grossPay,',.2f'),sep="") main() def main(): hours = int(input('enter hours worked this week ')) #test for invalid hours ADD #if the test is invalid get input from the user again! #repeat this line: hours = int(input('enter hours worked this week ')) #same for rate rate = float(input('enter hourly pay rate ')) grossPay = hours * rate print("Gross pay: $",format(grossPay,',.2f'),sep="") main() QU: What condition are we going to test for? We want to test for a BAD INPUT. For the hours? hours < 0 or hours > 40: If either thing is wrong, then the hours isn't valid! for rate, let's set these as he min and max vals: rate < 15.50 or rate > 100: If either thing is wrong, then the hours isn't valid! def main(): hours = int(input('enter hours worked this week ')) if hours < 0 or hours > 40: print("hours must be between 0 and 40") hours = int(input('enter hours worked this week ')) rate = float(input('enter hourly pay rate ')) if rate < 15.50 or rate > 100: print("min rate is 15.50 and max rate is 100") rate = float(input('enter hourly pay rate ')) grossPay = hours * rate print("Gross pay: $",format(grossPay,',.2f'),sep="") main() **Run this. 400 45 4.50 115.0 **Hmm, input still wrong. The user could keep making mistakes. ** Change the ifs to whiles!!!! RUN IT. This simpler version. RUN IT IN THE DEBUGGER, so they can see when the values get what they get. ** now, what if we want to print a message for the rate saying what is wrong. *** put the input statement in both the if and the else clauses. ** then show, you really only need it in the one place. def main(): hours = int(input('enter hours worked this week ')) while hours < 0 or hours > 40: print("Hours must be a number from 0 to 40") hours = int(input('enter hours worked this week ')) rate = float(input('enter hourly pay rate ')) while rate <= 15.50 or rate > 100: # Print a different message, depending on what # is wrong if rate <= 15.50: print("the minimum rate is 15.50") elif rate > 100: print("the maximum rate is 100") rate = float(input('enter hourly pay rate ')) grossPay = hours * rate print("Gross pay: $",format(grossPay,',.2f'),sep="") main()