~~SLIDESHOW~~ ====== Simple IO and a Case Study ====== Simple input and output and introduction of the case study. * [[#Simple IO]] * [[#Case Study: An Adventure Game|Case Study]] The slides and notes in this presentation are adapted from //Groovy Programming// (See [[lecture0#Reading|Recommended Reading]]). An index to the source code for all the examples in this lecture is [[/~eechris/at-m42/Examples/lecture04|available]]. ===== Simple IO ===== Console input and output is not part of the Groovy language. Nonetheless, real programs need to communicate with their environment. * to produce text output in Groovy we use: print xxx print(xxx) println xxx println(xxx) ---- The methods ''print'' and ''println'' are used to display the value concerned (denoted by ''xxx''). The value may represent a ''String'' literal, a variable or expression, or an intepreted ''String''. Method ''print'' outputs its value, and any further output appears on the same line. Method ''println'' advances to the next output line after displaying its value. Java programmers will be interested to observe that ''print'' and ''println'' are actually calls to ''System.out.print'' and ''System.out.println'' respectively. Parenthesis are optional. ===== Simple output ===== extern> http://www.cpjobling.org.uk/~eechris/at-m42/Examples/lecture04/example1.groovy ---- Example 1 demonstrates how to print a simple ''String'' literal using the ''print'' and ''println'' methods. When the groovy script is executed, the output is: My name is Chris. This is my first program. Isn't this fun! Lines 2 and 3 are responsible for the first line of output. Method ''print'' displays its parameter on the console (standard output). any further output continues on the same line. The simple method call ''println()'' prints a line break (new line). Note how the value parameters may optionally be encosed in parentheses. ===== Printing numbers ===== extern> http://www.cpjobling.org.uk/~eechris/at-m42/Examples/lecture04/example2.groovy ---- From [[lecture2#Interpreted Strings|lecture 2]], we know that ''String''s enclosed in double quotes are interpreted, and any ''${expression}'' is evaluated and becomes part of the ''String''. Example 2 shows this at work with some integers. The output from running this script is: My age is: 49 My age is: 49 ===== Printing lists and maps ===== extern> http://www.cpjobling.org.uk/~eechris/at-m42/Examples/lecture04/example3.groovy ---- We can also print the contents of a ''List'' or a ''Map''. Example 3 shows how we use the same scheme as already cited. The output is: numbers: [11, 12, 13, 14] staff telephones: [Chris:5580, Joe:5582, Tim:5583] ===== Formatted output ===== Formatted output is achieved with the ''printf'' method call. The formal description of ''printf'' is: printf(String format, List values) Example //Simple formatted output printf('My name is Chris', []) printf('my name is Chris\n' []) ---- The ''printf'' method prints its values to the console. The ''values'' are any expressions representing what is to be printed. The presentation of these values is under control of the //formatting string//. this string contains two types of information: ordinary characters, which are simply copied to the output, and //conversion specifications//, which control conversion and printing of the values. Two examples of ''printf'' are shown in the slide. in both examples, the ''List'' of values to be printed is empty. The format string comprises ordinary characters. The first ''printf'' method call (line 2) displays its format ''String''. Further output continues on the same output line. The second example (line 3) includes the escape character ''\n'', representing a newline. Any output after that will begin on the next line. The expression on line 2 is equivalent to ''print %%'My name is Chris'%%''. The expression on line 3 is equivalent to ''println %%'My name is Chris'%%''. ===== Conversion specifications ===== extern> http://www.cpjobling.org.uk/~eechris/at-m42/Examples/lecture04/example4.groovy ---- In these examples, we include a list of values. The format string then includes conversion specifications for each of the values. The conversion specifications are introduced by the percent (%) character. In the first example (line 6), ''%d'' denotes printing an integer value. In the second (line 11), the ''%f'' is used for printing floating point values. The output is: The sum of 10 and 15 is 25 56.780000 from 1.234000 gives -55.546000 Lines 14--16 illustrates using the ''%s'' conversion to print a ''String''. In all three examples, the output string is enclosed in ''['' and '']'' to reveal the effect of the conversions. We see that ''%s'' simply outputs the string. The conversion ''%20s'' outputs the string right justified in a field of 20 characters. The conversion ''%-20s'' left justifies the output. The output is: [Hello there] [ Hello there] [hello there ] A more detailed discussion of the conversion specifications [[Formatted Output|is available]]. ===== Simple input ===== // Get an input reader def input = new BufferedReader(new InputStreamReader(System.in)) print "Please enter your first name: " def name = input.readLine() println "Hello ${name}!" ---- The object ''in'' in the Java class ''System'' represents the standard input. unfortunately, it is an ''InputStream'' and is not designed for text input. To make it usable for text input, it has to be wrapped in an ''InputStreamReader'' which itself has to be buffered using a ''BufferedReader''. This arcane formula, shown on line 2 in the slide, is required to enable console input from the keyboard. Once we have the ''BufferedReader'' ''input'' we can use the method ''readLine'' to get a line of text from the keyboard and return it as a ''String''. ===== Inputting data values ===== def a = input.readLine().toInteger() def x = input.readLine().toDouble() ---- Method ''readLine'' returns a ''String'' value. In Java/Groovy there is no equivalent to C's ''scanf''. Instead, we can use the method ''toInteger'' on the ''String'' to convert it into an integer value or ''toDouble'' to convert it to a floating point value. In Example 5, below, we define three helper [[lecture5|methods]] to make it easier to read a ''String'', ''Integer'' and ''Double'' from the console. We have to pass in the ''BufferedReader input'' as an argument in order to enable the method to access the input. The methods ''toInteger'' and ''toDouble'' expect that the input ''String'' be correctly formatted with no unexpected characters and no leading or trailing spaces. extern> http://www.cpjobling.org.uk/~eechris/at-m42/Examples/lecture04/example5.groovy **Note** Scripts with keyboard input cannot be run inside the //groovyConsole//. Instead you have to run it from the windows command line using //groovy example5.groovy//. If you run the script this way, the output is:
  e:\dev\at-m42-2009\Examples\lecture04>groovy example5.groovy
  Please enter your first name: Chris
  Hello Chris!
  Please enter your surname: Jobling
  Please enter your age: 49
  Please enter your weight in kg: 100
  Hello Chris Jobling: your age is 49 and you weigh   100.00 kg
===== The Console class ===== package console class Console { def static readString() { ... } def static readLine() { ... } def static readInteger() { ... } def static readDouble() { ... } def static readBoolean() { ... } } ---- The methods ''readString'', ''readInteger'', etc. are very useful and will find uses in other examples to come. They have been collected as a set of static methods in the the class ''Console'' that can be imported into other examples. The code for the ''Console'' class is provided in the source-code download in <[[http://www.cpjobling.org.uk/~eechris/at-m42/src/lib/console/Console.groovy|at-m42\src\lib\console\Console.groovy]]>. The methods of class ''Console'' tokenize the input, so that for example, leading whitespace on an integer value is ignored by method ''readInteger''. Example 6 shows the use of these methods to reimplement Example 5. extern> http://www.cpjobling.org.uk/~eechris/at-m42/Examples/lecture04/example6.groovy To use ''Console'' you have to ensure that ''at-m42\src\lib'' is on the ''CLASSPATH'' for your project. Let us say that you download the example code and install it at ''h:\work\at-m42''. To set the classpath, open the windows command window and type: h:\work\at-m42> set CLASSPATH=h:\work\at-m42\src\lib;%CLASSPATH% If the classpath is set properly, Example 6 should run ok. ===== Case Study: An Adventure Game ===== This part of the lecture module will illustrate how ''List''s and ''Map''s might be used in practice. For this first case study we construct a simple model of the items in a text-based adventure game. More elaborate solutions are presented in the [[at-m42:casestudies|case studies]].] * For the first iteration we use a ''List'' to define players in a location. * For the second iteration we use a ''Map'' to make a more elaborate implementation. The //iterative// approach illustrated here is in keeping with modern practice ===== Iteration 1: Specification ===== * A text-based adventure game maintains a record of items being carried by its players. * Each item is known by its name and each player by his/her name. * The database of items being carried could be represented in a number of ways. * We will use ''List'' and ''Map''. ===== Iteration 1: Using a List ===== * The game is represented by a ''List'' * Each element in the ''List'' is another list of two elements: * the player's //name//; * an //item// that the player is carrying. ===== Iteration 1: List Implementation ===== def dng = [ ['Chris', 'Sword'], ['Chris', 'Food'], ['Jenny', 'Dagger'] ] ---- The ''List'' ''dng'' (dngs and Dragons) is a list of three elements, each of which is a list of two elements. The first shows that player ''Chris'' has a ''Sword'' and the second also that he has ''Food''. The third states that ''Jenny'' has a ''Dagger''. ===== Adding a new item ==== dng <<['Jenny', 'Food'] dng.add(['Joe', 'Magic Wand']) ===== Printing a location ===== println "dng: ${dng}" ===== A simple adventure game ===== The [[http://www.cpjobling.org.uk/~eechris/at-m42/Examples/lecture04/casestudy1.groovy|attached code]] (listed in the notes) produces the following output: dng: [[Chris, Sword], [Chris, Food], [Jenny, Dagger], [Jenny, Food], [Joe, Magic Wand]] Player Chris has a sword? true Number of items in the dng: 5 ---- extern> http://www.cpjobling.org.uk/~eechris/at-m42/Examples/lecture04/casestudy1.groovy We can determine if ''Chris'' has a sword with dng.contains(['Chris', 'Sword']) and determine the number of items being carries by players in the location with; dng.size() ===== Iteration 2: Using a Map ===== * Each location is represented by a ''Map'' * Each //key// in the ''Map'' represents a player; * Each //value// in the ''Map'' is a ''List'' of the items that the player is carrying. ===== Iteration 2: Map Implementation ===== def dng = [ 'Chris': ['Sword', 'Food'], 'Jenny': ['Dagger'] ] ---- in this revised implementation we associate a list of items with a player in a location. The key is the player's name and the value is a ''List'' of items being carried. Here is the code to initialise the location ''dng''. The result is a ''Map'' with two entries. The first has player ''Chris'' as the key and an associate value which is a list of items that ''Chris'' is carrying. The second entry records that states that ''Jenny'' has a ''Dagger''. ===== Adding items ==== // add a new player dng['Joe'] = ['Magic Wand'] // update an existing player dng['Jenny'] = dng['Jenny'] << 'Food' ---- We can add a new player and his items to the game as shown in line 2. To update a player's items we have to be careful to add to the player's items rather than over-writing the values as shown in line 5. ===== Location queries ===== def hasSword = dng['Chris'].contains('Sword') def nPlayers = dng.size() ---- As with the ''List'' implementation, we can determine if ''Chris'' is carrying a particular ''Item'' with the code shown in line 1 in the slide. We can also determine the number of players in the room as shown in line 2. ===== More Queries ===== def players = dng.keySet().sort() def carriedItems = dng['Chris'].size() ---- Line 1 in the slide obtains the players' names and presents them as a sorted list. Line 2 determines how many items ''Chris'' is carrying. ===== Putting it all together ===== The [[http://www.cpjobling.org.uk/~eechris/at-m42/Examples/lecture04/casestudy2.groovy|attached code]] (listed in the notes) produces the following output: dng: [Chris:[Sword, Food], Jenny:[Dagger, Food], Joe:[Magic Wand]] Player Chris has a sword? true Number of items in the dng: 3 Players: [Chris, Jenny, Joe] Number of items being carried by Chris: 2 ---- extern> http://www.cpjobling.org.uk/~eechris/at-m42/Examples/lecture04/casestudy2.groovy We can determine if ''Chris'' has a sword with dng.contains(['Chris', 'Sword']) and determine the number of items being carries by players in the location with; dng.size() ===== Summary of this Lecture ===== Simple input and output and introduction of the case study. * [[#Simple IO]] * [[#Case Study: An Adventure Game|Case Study]] ===== Lab Exercises ===== * [[at-m42:labs:lab1|Lab 1]] all exercises [[at-m42:labs:lab1#Part 3: Simple IO and Case Study I|Part 3]]. ---- [[Home]] | [[lecture3|Previous Lecture]] | [[Lectures]] | [[lecture5|Next Lecture]]