Difference between revisions of "CSC111 Lab 9 2018"

From dftwiki3
Jump to: navigation, search
 
(15 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
[[User:Thiebaut|D. Thiebaut]] ([[User talk:Thiebaut|talk]]) 09:54, 1 April 2018 (EDT)
 
[[User:Thiebaut|D. Thiebaut]] ([[User talk:Thiebaut|talk]]) 09:54, 1 April 2018 (EDT)
 
----
 
----
+
<onlydft>
 
<bluebox>
 
<bluebox>
 
This lab deals with exceptions and creating classes.   
 
This lab deals with exceptions and creating classes.   
The deadline for this lab is Friday 04/6/18 at 11:55 p.m.
+
The deadline for this lab is <strike>Friday 04/6/18</strike> Sunday 4/8/18, at 11:55 p.m.
 
</bluebox>
 
</bluebox>
 
   
 
   
<br />
 
 
<br />
 
<br />
 
__TOC__
 
__TOC__
 
<br />
 
<br />
<showafterdate after="20180401 10:00" before="20180601 00:00"-->
 
 
<br />
 
<br />
 
<br />
 
<br />
Line 29: Line 27:
 
    
 
    
 
   while  True:
 
   while  True:
       x = int( input( "Enter an integer greater than 0: " ) )
+
       x = eval( input( "Enter an integer greater than 0: " ) )
 
       if x <= 0:
 
       if x <= 0:
 
         print( "Invalid entry.  Try again!" )
 
         print( "Invalid entry.  Try again!" )
Line 44: Line 42:
 
</source>
 
</source>
 
* Test it with numbers such as -3, -10, 0, 5.  Verify that the input function works well when you enter numbers.
 
* Test it with numbers such as -3, -10, 0, 5.  Verify that the input function works well when you enter numbers.
* Test your program again, and this time enter expressions such as "6.3", or "hello" (without the quotes).   
+
* Test your program again, and this time enter expressions such as "as", "if", or "hello" (without the quotes).   
 
* Make a note of the <font color="red">Error</font> reported by Python:
 
* Make a note of the <font color="red">Error</font> reported by Python:
 
<br />
 
<br />
Line 61: Line 59:
 
       # try to get an int
 
       # try to get an int
 
       try:
 
       try:
           x = int( input( "Enter an integer greater than 0: " ) )
+
           x = eval( input( "Enter an integer greater than 0: " ) )
 
       except ValueError:
 
       except ValueError:
 
           # the user must have entered something other than an int
 
           # the user must have entered something other than an int
Line 76: Line 74:
 
</source>
 
</source>
 
<br />
 
<br />
* Run your program and try different invalid inputs, such as strings or floats.  You can also try just pressing the '''Return''' key, indicating that you are not providing anything to the input function.  Verify that your program catches all these invalid entries and does not crash.
+
* Run your program and try more different invalid inputs.  You can also try just pressing the '''Return''' key, indicating that you are not providing anything to the input function.  Verify that your program catches all these invalid entries and does not crash.
 
<br />
 
<br />
  
 
==Review Class Example==
 
==Review Class Example==
 
<br />
 
<br />
* Below is an example we saw in class, and that is taken from Zelle.  It illustrates how we can guard some code against several types of errors.  Review it.  You will need to follow this example for the next set of exercises.
+
* Below is an example we saw in class, and that is taken from Zelle.  It prompts the user for 3 integers, separated by comas, and then it outputs the root of the equation <tt>a x^2 + b x + c = 0</tt>.
 
<br />
 
<br />
 
::<source lang="python">
 
::<source lang="python">
 +
from math import sqrt
 
def ZelleExample():
 
def ZelleExample():
     import math
+
     print( "solution to quadratic equation" )
 +
    a, b, c = eval( input( "enter 3 coefficients (a,b,c) " ) )
 +
    disc = sqrt( b*b - 4*a*c )
 +
    root1 = (-b + disc )/ (2*a)
 +
    root2 = (+b + disc )/ (2*a)
 +
    print( "solutions: ", root1, root2 )
 +
 
 +
ZelleExample()
 +
 
 +
</source>
 +
<br />
 +
* Run this program a few times and first give it numbers that will correspond to valid roots of the equation.  For example 2, 3, -4. 
 +
* Now try making the program crash entering values that will make the part in the square root negative: 2, 1, 4.
 +
* Notice the error you get: <tt><font color="red">ValueError: math domain error</font></tt>.
 +
* Add a '''try/except''' statement to protect the whole block:
 +
::<source lang="python">
 +
def ZelleExample():
 +
    from math import sqrt
 
     print( "solution to quadratic equation" )
 
     print( "solution to quadratic equation" )
 
     try:
 
     try:
 
         a, b, c = eval( input( "enter 3 coefficients (a,b,c) " ) )
 
         a, b, c = eval( input( "enter 3 coefficients (a,b,c) " ) )
         disc = math.sqrt( b*b - 4*a*c )
+
         disc = sqrt( b*b - 4*a*c )
 
         root1 = (-b + disc )/ (2*a)
 
         root1 = (-b + disc )/ (2*a)
 
         root2 = (+b + disc )/ (2*a)
 
         root2 = (+b + disc )/ (2*a)
 
         print( "solutions: ", root1, root2 )
 
         print( "solutions: ", root1, root2 )
     except NameError:
+
     except ValueError:
 +
        print( "No real roots, negative discriminant" )
 +
 
 +
 
 +
ZelleExample()
 +
</source>
 +
<br />
 +
* Run your program again with 2, 1, 4 as input and verify that you now catch the ValueError exception.
 +
* Continue testing your program with different inputs (try fewer than 3 number, forgetting a coma, inputing a string with the number, or providing 0 as the first number. 
 +
* Every time your program crashes, figure out the name of the exception and add it in a new '''except''' clause.
 +
* Your code should looks something like this at some point...
 +
<br />
 +
::<source lang="python">
 +
def ZelleExample():
 +
    from math import sqrt
 +
    print( "solution to quadratic equation" )
 +
    try:
 +
        a, b, c = eval( input( "enter 3 coefficients (a,b,c) " ) )
 +
        disc = sqrt( b*b - 4*a*c )
 +
        root1 = (-b + disc )/ (2*a)
 +
        root2 = (+b + disc )/ (2*a)
 +
        print( "solutions: ", root1, root2 )
 +
    except xxx:
 
         print( "You didn't enter 3 numbers" )
 
         print( "You didn't enter 3 numbers" )
     except TypeError:
+
     except xxx:
 
         print( "Your inputs were not all numbers" )
 
         print( "Your inputs were not all numbers" )
     except SyntaxError:
+
     except xxx:
 
         print( "Forgot commas between the numbers?" )
 
         print( "Forgot commas between the numbers?" )
     except ValueError:
+
     except xxx:
 
         print( "No real roots, negative discriminant" )
 
         print( "No real roots, negative discriminant" )
 +
</source>
 +
<br />
 +
* If you really want to be thorough and catch all kinds of exceptions, you could add a final '''except''' statement at the end of the list of except lines:
 +
<br />
 +
::<source lang="python">
 
     except:
 
     except:
         print( "Something went wrong..." )
+
         print( "Something went wrong" )
 
 
 
</source>
 
</source>
 
<br />
 
<br />
 +
* By not specifying any error in this except clause, you indicate that *ALL* exceptions that do not trigger one of the exceptions above should be caught, and greeted with a "Something went wrong" message.
 +
* Run your program, and when it prompts you for 3 numbers, type Control-C, which normally would stop a program by making it crash.  See what this last except does with Control-C?
 +
 +
<!-- =========================================================================================
  
 
==Part 2: Exercise==
 
==Part 2: Exercise==
Line 191: Line 237:
 
* Repeat the same process for the other functions.
 
* Repeat the same process for the other functions.
 
<br />
 
<br />
 +
 +
======================================================================== -->
 +
 
=Classes and Objects=
 
=Classes and Objects=
 
<br />
 
<br />
Line 199: Line 248:
 
<br />
 
<br />
 
::<source lang="python">
 
::<source lang="python">
# cats1.py
+
# lab9_3.py
 
# D. Thiebaut
 
# D. Thiebaut
 
# Program for Week #9
 
# Program for Week #9
Line 268: Line 317:
 
</source>
 
</source>
 
<br />
 
<br />
* Recreate this code in a program called Lab9_2.py
+
* Recreate this code in a program called Lab9_3.py
 
* Run it.
 
* Run it.
 
* Add a loop to your main program that outputs only the cats that are '''not vaccinated''', and only those.
 
* Add a loop to your main program that outputs only the cats that are '''not vaccinated''', and only those.
Line 291: Line 340:
 
|-
 
|-
 
|
 
|
==Challenge   #0: getBreed() method==
+
==Challenge #0: getBreed() method==
 
|}
 
|}
 
[[Image:QuestionMark3.jpg|right|120px]]
 
[[Image:QuestionMark3.jpg|right|120px]]
Line 314: Line 363:
 
</source>
 
</source>
 
<br />
 
<br />
* Add another loop to your main function, once more, and make it output the '''Non-vaccinated cats 2 or older'''.
+
* Add another loop to your main function, once more, and make it output the '''Non-vaccinated cats that are 2 or older'''.
 
* Example of what your output should look like:
 
* Example of what your output should look like:
 
<br />
 
<br />
Line 435: Line 484:
 
[[Image:QuestionMark7.jpg|right|120px]]
 
[[Image:QuestionMark7.jpg|right|120px]]
 
<br />
 
<br />
* Create the short program below and name it '''createCatCSV.py'''.
+
* Create a new file with Idle, and copy/paste the following text in it.  Call it '''cats.csv'''.
<br />
+
::<source lang="text">
::<source lang="python">
+
Minou, 3, vaccinated, tattooed, stray
# createCatCSV.py
 
# D. Thiebaut
 
# save several cat definitions into a CSV file.
 
 
 
def createCatCSV( fileName ):
 
    file = open( fileName, "w" )
 
    file.write( """Minou, 3, vaccinated, tattooed, stray
 
 
Max, 1, not vaccinated, tattooed, Burmese
 
Max, 1, not vaccinated, tattooed, Burmese
 
Gizmo, 2, vaccinated, tattooed, Bengal
 
Gizmo, 2, vaccinated, tattooed, Bengal
 
Garfield, 4, not vaccinated, not tattooed, Orange Tabby
 
Garfield, 4, not vaccinated, not tattooed, Orange Tabby
 
Silky, 3, vaccinated, tattooed, Siamese
 
Silky, 3, vaccinated, tattooed, Siamese
Winston, 1, not vaccinated, not tattooed, stray\n""" )
+
Winston, 1, not vaccinated, not tattooed, stray
    file.close()
 
 
 
 
 
def main():
 
    createCatCSV( "cats.csv" )
 
 
 
main()
 
 
</source>
 
</source>
<br />
 
* Run the program once.  Verify that it will have created a new file in the same folder/directory where your program resides.  Verify (using Notepad or TextEdit) that this file contains a collection of lines, each representing a cat.
 
 
<br />
 
<br />
 
* Now, play with the program below:
 
* Now, play with the program below:
 
<br />
 
<br />
 
::<source lang="python">
 
::<source lang="python">
# Lab9CatsCSV.py
+
# Lab9_4.py
 
# D. Thiebaut
 
# D. Thiebaut
 
# Seed for a program that reads cat data from
 
# Seed for a program that reads cat data from
Line 490: Line 523:
 
         for i in range( len( words ) ):
 
         for i in range( len( words ) ):
 
             print( "words[",i,"]=", words[i].strip(), end=", " )
 
             print( "words[",i,"]=", words[i].strip(), end=", " )
 +
       
 +
        # if words[2].find( "not" ) != -1:
 +
        #    print( "might want to vaccinate this guy!" )
 
         print()
 
         print()
  
Line 500: Line 536:
 
* This means that your program must
 
* This means that your program must
 
::# extract each cat from a line of the file,  
 
::# extract each cat from a line of the file,  
::# transform the string "vaccinated" in True, and "not vaccinated" in False (it's simpler than you think!)
+
::# transform the string "vaccinated" in True, and "not vaccinated" in False (You may want to uncomment the if statement in the program above, and run it to see how to detected vaccination!)
::# transform the string "tattooed" in True, and "not tattooed" in False (same comment),
+
::# transform the string "tattooed" in True, and "not tattooed" in False (same comment as above),
 
::# transform the string containing the age into an int,
 
::# transform the string containing the age into an int,
 
::# and store all this information into a Cat object.  All the cats should be added to a list.   
 
::# and store all this information into a Cat object.  All the cats should be added to a list.   
Line 538: Line 574:
 
Silky              :==> Siamese, vaccinated, tattooed, 3 yrs old
 
Silky              :==> Siamese, vaccinated, tattooed, 3 yrs old
 
</source>
 
</source>
 +
<br />
 +
<br />
 +
{| style="width:100%; background:silver"
 +
|-
 +
|
 +
==Challenge  #4: Reading the Cat information from a CSV file==
 +
|}
 +
[[Image:QuestionMark8.jpg|right|120px]]
 +
<br />
 +
Make your program output the cat information formatted as shown below.  This will be the program you'll be submitting to Moodle in the next section.
 +
<br />
 +
;Example CSV file:
 +
::<source lang="text">
 +
Max, 21, vaccinated, not tattooed, stray
 +
Toto, 3, not vaccinated, tattooed, stray
 +
Garfield, 1, not vaccinated, not tattooed, Burmese
 +
Bob, 4, not vaccinated, tattooed, Orange Tabby
 +
Minou, 10, not vaccinated, not tattooed, stray
 +
</source>
 +
<br />
 +
;Program output
 +
<br />
 +
::<source lang="text">
 +
Complete List:
 +
Max                :==> stray, vaccinated, not tattooed, 21 yrs old
 +
Toto                :==> stray, not vaccinated, tattooed, 3 yrs old
 +
Garfield            :==> Burmese, not vaccinated, not tattooed, 1 yrs old
 +
Bob                :==> Orange Tabby, not vaccinated, tattooed, 4 yrs old
 +
Minou              :==> stray, not vaccinated, not tattooed, 10 yrs old
 +
 +
Non-vaccinated cats:
 +
Toto                :==> stray, not vaccinated, tattooed, 3 yrs old
 +
Garfield            :==> Burmese, not vaccinated, not tattooed, 1 yrs old
 +
Bob                :==> Orange Tabby, not vaccinated, tattooed, 4 yrs old
 +
Minou              :==> stray, not vaccinated, not tattooed, 10 yrs old
 +
 +
Stray cats:
 +
Max                :==> stray, vaccinated, not tattooed, 21 yrs old
 +
Toto                :==> stray, not vaccinated, tattooed, 3 yrs old
 +
Minou              :==> stray, not vaccinated, not tattooed, 10 yrs old
 +
 +
Non-vaccinated cats 2 or older:
 +
Toto                :==> stray, not vaccinated, tattooed, 3 yrs old
 +
Bob                :==> Orange Tabby, not vaccinated, tattooed, 4 yrs old
 +
Minou              :==> stray, not vaccinated, not tattooed, 10 yrs old
 +
 +
Non-tattooed cats:
 +
Max                :==> stray, vaccinated, not tattooed, 21 yrs old
 +
Garfield            :==> Burmese, not vaccinated, not tattooed, 1 yrs old
 +
Minou              :==> stray, not vaccinated, not tattooed, 10 yrs old
 +
 +
Not vaccinated and tattooed cats:
 +
Toto                :==> stray, not vaccinated, tattooed, 3 yrs old
 +
Bob                :==> Orange Tabby, not vaccinated, tattooed, 4 yrs old
 +
 +
 +
</source>
 +
<br />
 +
<br />
 
<br />
 
<br />
  
 
=Moodle Submission=
 
=Moodle Submission=
 
<br />
 
<br />
Take the final program you wrote for Part 2 of this lab, and make it get the name of a file from the user (who will enter cats.csv at the prompt), and output only the cats that are not vaccinated, and 2 years '''or''' older.
+
Submit your final lab9_3.py program to Moodle.  Your program should prompt the user for the name of a CSV file that will contain a list of cats.
Your program should not output any other information, otherwise the Moodle test program will assume your output is incorrect.
 
Your program should do its work by using a list of Cat objects instantiated from a class called Cat.  
 
  
<tanbox>Make sure your program prints a blank line after getting the name of the file from the user!  This blank line is used by Moodle to test the output.  If you forget this blank line, Moodle will skip the first line of your program's output, and will think you have missed something!</tanbox>
+
<tanbox>Make sure your program prints a blank line after getting the name of the file from the user!  This blank line is used by the autograder to figure out where the output of your program starts.
 +
</tanbox>
 
<br />
 
<br />
 
==Example==
 
==Example==
Line 571: Line 665:
 
File name? cats2.csv
 
File name? cats2.csv
  
 +
Complete list:
 +
Max                :==> stray, vaccinated, not tattooed, 1 yrs old
 
Black              :==> stray, not vaccinated, tattooed, 3 yrs old
 
Black              :==> stray, not vaccinated, tattooed, 3 yrs old
Bob                :==> Orange Tabby, not vaccinated, tattooed, 4 yrs old
+
etc...
Silky              :==> Siamese, not vaccinated, tattooed, 3 yrs old
 
 
</source>
 
</source>
 
<br />
 
<br />
Line 745: Line 840:
 
-->
 
-->
  
</showafterdate>
+
</onlydft>
 
 
 
<!-- ============================================================= -->
 
<!-- ============================================================= -->
 
<!-- ============================================================= -->
 
<!-- ============================================================= -->
Line 752: Line 846:
 
<!-- ============================================================= -->
 
<!-- ============================================================= -->
  
<showafterdate after="20180407 12:00" before="20180601 00:00">
+
<showafterdate after="20180409 12:00" before="20180601 00:00">
 
=Solution Programs=
 
=Solution Programs=
 
==Part 1 ==
 
==Part 1 ==

Latest revision as of 12:59, 1 June 2018

D. Thiebaut (talk) 09:54, 1 April 2018 (EDT)



...


<showafterdate after="20180409 12:00" before="20180601 00:00">

Solution Programs

Part 1


# lab9 programs
# D. Thiebaut

# getInput: returns an integer larger
# than 0.  Expected to be robust
def getInput():
   
   while  True:
      x = int( input( "Enter an integer greater than 0: " ) )
      if x <= 0:
         print( "Invalid entry.  Try again!" )
      else:   
         return x

# betterGetInput: returns an integer larger
# than 0.  Expected to be robust
def betterGetInput():
    
   # repeat forever...
   while  True:

      # try to get an int
      try:
          x = int( input( "Enter an integer greater than 0: " ) )
      except ValueError:
          # the user must have entered something other than an int
          print( "Invalid entry.  Not an integer.  Try again!" )
          continue

      # There was no errors.  See if the number is negative
      if x <= 0:
         print( "You entered a negative number.  Try again!" )
      else:   
         return x

def main1():
   num = betterGetInput()
   print( "You have entered", num )

# =======================================================================

def example1():
    print( "You will need to enter 3 pairs of ints..." )
    while True:
       try:
            x = int( input( "enter a number: " ) )
            y = int( input( "enter another number: " ) )
            print( x, '/', y, '=', x/y )
            break
       except ZeroDivisionError:
            print( "Can't divide by 0!" )
       except ValueError:
            print( "That doesn't look like a number!" )
       except:
            print( "something unexpected happend!" )

def example2( L ):
    print( "\n\nExample 2" )
    sum = 0
    for i in range( len( L ) ):
        try:
            sum +=  L[i]
        except TypeError:
            continue

    print( "sum of items in ", L, "=", sum )


def printUpperFile( fileName ):
    try:
       file = open( fileName, "r" )
    except FileNotFoundError:
       print( "***Error*** File", fileName, "not found!" )
       return

    # if we're here, the file is found and open
    for line in file:
       print( line.upper() )
    file.close()

def createTextFile( fileName ):
   file = open( fileName, "w" )
   file.write( "Welcome\nto\nCSC111\nIntroduction\nto\nComp.\nSci.\n" )
   file.close()

def main2():
    createTextFile( "csc111.txt" )

    example1()

    L = [ 10, 3, 5, 6, 9, 3 ]
    example2( L )
    #example2( [ 10, 3, 5, 6, "NA", 3 ] )

    printUpperFile( "csc111.txt" )
    #printUpperFile( "csc1111.txt" )

main2()


Part 2


# cats1.py
# D. Thiebaut
# Program for Week #9
# Define a Cat class, and
# use it to create a collection of
# cats.


class Cat:
    """a class that implements a cat and its
    information.  Name, breed, vaccinated,
    tattooed, and age."""

    def __init__( self, na, brd, vacc, ag, tat ):
        """constructor.  Builds a cat with all its information"""
        self.name       = na
        self.breed      = brd
        self.vaccinated = vacc
        self.age        = ag
        self.tattooed   = tat

    def isTattooed( self ):
        """returns True if cat is tattooed, False otherwise"""
        return self.tattooed

    def isVaccinated( self ):
        """returns True if cat is vaccinated, False otherwise"""
        return self.vaccinated

    def getAge( self ):
        """returns cat's age"""
        return self.age

    def getName( self ):
        """returns name of cat"""
        return self.name

    def getBreed( self ):
        return self.breed
    
    def __str__( self ):
        """default string representation of cat"""
        vacc = "vaccinated"
        if not self.vaccinated:
            vacc = "not vaccinated"

        tatt = "tattooed"
        if not self.tattooed:
            tatt = "not tattooed"
        
        return "{0:20}:==> {1:1}, {2:1}, {3:1}, {4:1} yrs old".format(
            self.name, self.breed, vacc, tatt, self.age )

def readCatCSV( fileName ):
    """ reads the CSV file and puts all the cats
    in a list of Cat objects"""

    # get the lines from the CSV file
    file = open( fileName, "r" )
    lines = file.readlines()
    file.close()

    # create an empty list of cats
    cats = []
    
    # get one line at a time
    for line in lines:
        # split a line in words
        fields = line.split( ", " )

        # skip lines that do not have 5 fields
        if len( fields ) != 5:
            continue

        # get 5 fields into 5 different variables
        name, age, vac, tat, breed = fields
        breed = breed.strip()
        
        # transform "vaccinated" or "not vaccinated" in True or False
        if vac.lower().find( "not " )==-1:
            vac = True
        else:
            vac = False
            
        # transform "tattooed" or "not tattooed" in True or False
        if tat.lower().find( "not " )==-1:
            tat = True
        else:
            tat = False

        # add a new cat to the list
        cats.append( Cat( name, breed, vac, int(age), tat ) )

    # done with the lines.  Return the cat list
    return cats

def main():
    """ main program.  Creates a list of cats and displays
    groups sharing the same property.
        Minou, 3, vac, stray, tat
        Max, 1, not-vac, Burmese, tat
        Gizmo, 2, vac, Bengal, tat
        Garfield, 4, not-vac, Orange Tabby
    """
    cats = readCatCSV( input( "File name? " ) )
    """
    cat = Cat( "Minou", "stray", True, 3, True)
    cats.append( cat )
    
    cats.append( Cat( "Max", "Burmese", False, 1, True ) )
    cats.append( Cat( "Gizmo", "Bengal", True, 2, True ) )
    cats.append( Cat( "Garfield", "Orange Tabby", False, 4, False ) )
    """
    
    # print the list of all the cats
    print( "\nComplete List:" )
    for cat in cats:
        print( cat )

    print( "\nNon-vaccinated cats:" )
    for cat in cats:
        if cat.isVaccinated()==False:
            print( cat )

    print( "\nStray cats:" )
    for cat in cats:
        if cat.getBreed().lower() == "stray":
            print( cat )

    print( "\nNon-vaccinated cats 2 or older:" )
    for cat in cats:
        if cat.isVaccinated()==False and cat.getAge() >= 2:
            print( cat )

    print( "\nNon-tattooed cats:" )
    for cat in cats:
        if cat.isTattooed()==False:
            print( cat )
            
    print( "\nVaccinated and tattooed cats:" )
    for cat in cats:
        if cat.isVaccinated() and cat.isTattooed():
            print( cat )

def lab9Solution():
    """prompts user for file name, and outputs
    cats that are not vaccinated, and 2 years or older"""
    
    cats = readCatCSV( input( "File name? " ) )
    print()

    for cat in cats:
        if cat.isVaccinated()==False and cat.getAge() >= 2:
            print( cat )
            
#main()
lab9Solution()


</showafterdate>